diff --git a/.gitignore b/.gitignore index 1437c53..74b7586 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ yarn-debug.log* yarn-error.log* # local env files +.env .env.local .env.development.local .env.test.local diff --git a/components/Main.tsx b/components/Main.tsx index e63e4ff..a479977 100644 --- a/components/Main.tsx +++ b/components/Main.tsx @@ -1,13 +1,40 @@ +import Search from './Search'; import { Photo } from '../interfaces/photos'; +import { useSelector } from 'react-redux'; +import { RootState } from '../store/store'; +import { Container, Pagination } from 'semantic-ui-react'; -const Main = ({ photos }) => { - return ( -
+const Main = ({ defaultPhotos }) => { + const { + data: { + photos, + }, + } = useSelector((state: RootState) => state.photos); + + const renderList = () => { + if (photos.length) { + return ( + ) + } else { + return ( + + ) + } + }; + + return ( +
+ + {renderList()}
) }; diff --git a/components/Search.tsx b/components/Search.tsx new file mode 100644 index 0000000..5b0e98e --- /dev/null +++ b/components/Search.tsx @@ -0,0 +1,89 @@ +import { useState, useEffect, ChangeEvent } from 'react'; +import { Container, Input, Header, Menu } from 'semantic-ui-react'; +import { + useDispatch +} from 'react-redux'; +import { AppDispatch } from '../store/store'; +import { fetchPhotos } from '../store/photos'; + +const Search = () => { + const dispatch = useDispatch(); + const [query, setQuery] = useState(''); + const [activeItem, setActiveItem] = useState(10); + + useEffect(() => { + const debounce = setTimeout(() => { + if (query) { + dispatch(fetchPhotos({ + query, + page: 1, + per_page: activeItem, + })); + } + }, 1000); + return () => {clearTimeout(debounce)}; + }, [query]); + + useEffect(() => { + if (query) { + dispatch(fetchPhotos({ + query, + page: 1, + per_page: activeItem + })) + } + }, [activeItem]) + + const onInputChange = (event: ChangeEvent) => { + setQuery(event.target.value); + }; + + return ( + +
+ Search for free photos shared by talented creators +
+ onInputChange(e)} + /> + + + setActiveItem(10)} + /> + + setActiveItem(25)} + /> + + setActiveItem(50)} + /> + +
+ ) +}; + +export default Search; \ No newline at end of file diff --git a/next.config.js b/next.config.js index 8b61df4..67e29d1 100644 --- a/next.config.js +++ b/next.config.js @@ -1,4 +1,7 @@ /** @type {import('next').NextConfig} */ module.exports = { reactStrictMode: true, + env: { + API_KEY: process.env.API_KEY, + } } diff --git a/pages/index.tsx b/pages/index.tsx index 7318eb5..7390274 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -4,14 +4,14 @@ import Head from 'next/head'; import Main from '../components/Main'; import { PEXELS_URL } from '../utils/constants'; -const Home: NextPage = ({photos}) => { +const Home: NextPage = ({defaultPhotos}) => { return (
Interview Frontend App -
+
); }; @@ -30,7 +30,7 @@ export async function getStaticProps() { return { props: { - photos: data, + defaultPhotos: data, } }; }; diff --git a/store/photos.ts b/store/photos.ts index b6d6d89..91de3d3 100644 --- a/store/photos.ts +++ b/store/photos.ts @@ -26,24 +26,24 @@ export const initialState: SliceState = { export const fetchPhotos = createAsyncThunk< PhotosResponse, // return value - string, // parameters + {}, // parameters {} >( 'photos/fetchPhotos', - async phrase => { + async params => { + console.log(params) const { data } = await axios.get(PEXELS_URL, { headers: { Authorization: process.env.API_KEY, }, - params: { - query: phrase, - }, + params }); - + console.log(data) return data; } ); + const photosDataSlice = createSlice({ extraReducers: { [fetchPhotos.pending.toString()]: (state: SliceState) => {