From 18c85a662ad8a250177493cc50965ea682746451 Mon Sep 17 00:00:00 2001 From: Sindre Kjelsrud Date: Tue, 12 Sep 2023 11:10:57 +0200 Subject: [PATCH 1/5] =?UTF-8?q?:construction:=20pr=C3=B8ver=20=C3=A5=20gj?= =?UTF-8?q?=C3=B8re=20queryparams=20p=C3=A5=20nytt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: haraldnilsen --- src/App.tsx | 55 +++++++++++++++++-------------------------- src/api/fetchMovie.ts | 26 ++++++++++++++++++++ src/main.tsx | 5 +++- src/types/movie.ts | 6 +++++ src/util/navigate.ts | 20 ++++++++++++++++ 5 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 src/api/fetchMovie.ts create mode 100644 src/util/navigate.ts diff --git a/src/App.tsx b/src/App.tsx index 65aa179..c57d9b1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,35 +3,39 @@ import './App.css' import q from 'qjuul' import { MovieForm, Pagination, MovieTable, MovieModal } from './components' import type { movieObject } from './types/movie' +import { fetchMovie } from './api/fetchMovie' +import { useLocation } from 'react-router' function App() { - const API_MOVIE_KEY = 'd92949d8' const [movies, setMovies] = useState([]) const [loading, setLoading] = useState(true) const [currentPage, setCurrentPage] = useState(1) const [totalPages, setTotalPages] = useState(0) const [modalOpen, setModalOpen] = useState(false) const [modalMovie, setModalMovie] = useState(null) - const [movieType, setMovieType] = useState('') - const [movieYear, setMovieYear] = useState('') - const [movieTitle, setMovieTitle] = useState('') const [sortAscending, setSortAscending] = useState(true) - - console.log('App mounted') + const location = useLocation() useEffect(() => { - fetch( - `http://www.omdbapi.com/?apikey=${API_MOVIE_KEY}&s=${movieTitle}&page=${currentPage}` - ) - .then((response) => response.json()) - .then((data) => { - setMovies(data.Search) - console.log(data) - setTotalPages(data.totalResults) - }) - .then(() => setLoading(false)) - .catch((error) => console.log(error)) - }, [currentPage]) + const searchParams = new URLSearchParams(location.search) + const title = searchParams.get('title') || '' + const page = searchParams.get('page') || '' + const type = searchParams.get('type') || '' + const year = searchParams.get('y') || '' + + const handleFetchMovie = async () => { + const response = await fetchMovie(title, page, type, year) + if (response.Response == 'true') { + setMovies(response.Search) + setTotalPages(Number(response.totalResults)) + setLoading(false) + } + } + + if (title) { + handleFetchMovie() + } + }, []) const calculatePages = (totalResults: number): number => { return Math.round(totalResults / 10) @@ -46,21 +50,6 @@ function App() { setModalMovie(movie) } - const handleMovieSubmit = (event: any) => { - event.preventDefault() - fetch( - `http://www.omdbapi.com/?apikey=${API_MOVIE_KEY}&s=${movieTitle}&type=${movieType}&y=${movieYear}` - ) - .then((response) => response.json()) - .then((data) => { - setMovies(data.Search) - console.log(data) - setTotalPages(data.totalResults) - }) - .then(() => setLoading(false)) - .catch((error) => console.log(error)) - } - const sortHandler = (sortType: string) => { let sortedMovies: movieObject[] = [] diff --git a/src/api/fetchMovie.ts b/src/api/fetchMovie.ts new file mode 100644 index 0000000..aaa92ff --- /dev/null +++ b/src/api/fetchMovie.ts @@ -0,0 +1,26 @@ +import { movieResponse } from '../types/movie' + +const API_MOVIE_KEY = 'd92949d8' + +export const fetchMovie = async ( + title: string, + page: string = '1', + type?: string, + year?: string +): Promise => { + let query = `http://www.omdbapi.com/?apikey=${API_MOVIE_KEY}s=${title}&page=${page}` + + if (type) query += `&type=${type}` + if (year) query += `&year=${year}` + + const response = await fetch(query) + .then((response) => response.json()) + .then((data) => { + return data + }) + .catch((error) => { + console.log('Error:', error) + }) + + return response +} diff --git a/src/main.tsx b/src/main.tsx index ed31931..d7fb535 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,9 +1,12 @@ import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' +import { BrowserRouter as Router } from 'react-router-dom' ReactDOM.createRoot(document.getElementById('root')!).render( - + + + ) diff --git a/src/types/movie.ts b/src/types/movie.ts index 25c5ae4..7bbc260 100644 --- a/src/types/movie.ts +++ b/src/types/movie.ts @@ -7,3 +7,9 @@ export type movieObject = { } export type modalMovieType = movieObject | null + +export type movieResponse = { + Response: string + totalResults: string + Search: movieObject[] +} diff --git a/src/util/navigate.ts b/src/util/navigate.ts new file mode 100644 index 0000000..276f3d7 --- /dev/null +++ b/src/util/navigate.ts @@ -0,0 +1,20 @@ +import { useNavigate } from 'react-router' + +const navigate = useNavigate() + +export const navigateToPage = ( + title?: string, + page: string = '1', + type?: string, + year?: string +) => { + if (!title) navigate('') + else { + let query = `?title=${title}&page=${page}` + + if (type) query += `&type=${type}` + if (year) query += `&year=${year}` + + navigate(query) + } +} From cd63407d0332a3c57ba4ed94c4369f6e7e5dff5a Mon Sep 17 00:00:00 2001 From: haraldnilsen Date: Tue, 12 Sep 2023 11:53:12 +0200 Subject: [PATCH 2/5] :sparkles: working query params from url - not form Co-authored-by: Sindre Kjelsrud --- src/App.tsx | 32 ++++++++++++------------------ src/api/fetchMovie.ts | 4 ++-- src/components/MovieForm/index.tsx | 23 ++++++++------------- src/util/navigate.ts | 23 ++++++++++----------- 4 files changed, 33 insertions(+), 49 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index c57d9b1..61e6cdc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,23 +17,24 @@ function App() { const location = useLocation() useEffect(() => { + const handleFetchMovie = async () => { + const response = await fetchMovie(title, page, type, year) + if (response.Response == 'True') { + setMovies(response.Search) + setTotalPages(Number(response.totalResults)) + setLoading(false) + } + } const searchParams = new URLSearchParams(location.search) const title = searchParams.get('title') || '' const page = searchParams.get('page') || '' const type = searchParams.get('type') || '' const year = searchParams.get('y') || '' - const handleFetchMovie = async () => { - const response = await fetchMovie(title, page, type, year) - if (response.Response == 'true') { - setMovies(response.Search) - setTotalPages(Number(response.totalResults)) - setLoading(false) - } - } - if (title) { handleFetchMovie() + } else { + setLoading(false) } }, []) @@ -78,16 +79,9 @@ function App() { All movies - + - {!loading && totalPages && ( + {!loading && movies.length > 0 && ( {loading ? ( Loading... - ) : movies ? ( + ) : movies.length > 0 ? ( ) : ( Find a list of movies by searching above ☝️ diff --git a/src/api/fetchMovie.ts b/src/api/fetchMovie.ts index aaa92ff..83ff466 100644 --- a/src/api/fetchMovie.ts +++ b/src/api/fetchMovie.ts @@ -1,6 +1,6 @@ import { movieResponse } from '../types/movie' -const API_MOVIE_KEY = 'd92949d8' +const API_MOVIE_KEY = import.meta.env.VITE_API_MOVIE_KEY export const fetchMovie = async ( title: string, @@ -8,7 +8,7 @@ export const fetchMovie = async ( type?: string, year?: string ): Promise => { - let query = `http://www.omdbapi.com/?apikey=${API_MOVIE_KEY}s=${title}&page=${page}` + let query = `http://www.omdbapi.com/?apikey=${API_MOVIE_KEY}&s=${title}&page=${page}` if (type) query += `&type=${type}` if (year) query += `&year=${year}` diff --git a/src/components/MovieForm/index.tsx b/src/components/MovieForm/index.tsx index eaa65ba..1235ff6 100644 --- a/src/components/MovieForm/index.tsx +++ b/src/components/MovieForm/index.tsx @@ -1,24 +1,17 @@ -import type { movieObject } from '../../types/movie' -import Modal from 'react-modal' +import { useState } from 'react' import q from 'qjuul' +import { useNavigateToPage } from '../../util/navigate' -interface MovieFormProps { - handleMovieSubmit: (event: any) => void - setMovieTitle: (title: string) => void - setMovieYear: (year: string) => void - setMovieType: (type: string) => void -} +const MovieForm: React.FC = () => { + const [movieTitle, setMovieTitle] = useState('') + const [movieYear, setMovieYear] = useState('') + const [movieType, setMovieType] = useState('') + const navigateToPage = useNavigateToPage() -const MovieForm: React.FC = ({ - handleMovieSubmit, - setMovieTitle, - setMovieType, - setMovieYear, -}) => { return ( navigateToPage(movieTitle, movieYear, movieType)} > Choose a movie title: { + const navigate = useNavigate() -export const navigateToPage = ( - title?: string, - page: string = '1', - type?: string, - year?: string -) => { - if (!title) navigate('') - else { - let query = `?title=${title}&page=${page}` + return (title?: string, page: string = '1', type?: string, year?: string) => { + if (!title) navigate('') + else { + let query = `?title=${title}&page=${page}` - if (type) query += `&type=${type}` - if (year) query += `&year=${year}` + if (type) query += `&type=${type}` + if (year) query += `&year=${year}` - navigate(query) + navigate(query) + } } } From 20aaef67d719aae8ad8badaf2901934d5d15aef9 Mon Sep 17 00:00:00 2001 From: haraldnilsen Date: Tue, 12 Sep 2023 12:04:41 +0200 Subject: [PATCH 3/5] :sparkles: Working form submission with query params Co-authored-by: Sindre Kjelsrud --- src/App.tsx | 2 +- src/components/MovieForm/index.tsx | 5 ++++- src/util/navigate.ts | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 61e6cdc..109a21b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -36,7 +36,7 @@ function App() { } else { setLoading(false) } - }, []) + }, [location.search]) const calculatePages = (totalResults: number): number => { return Math.round(totalResults / 10) diff --git a/src/components/MovieForm/index.tsx b/src/components/MovieForm/index.tsx index 1235ff6..ff05ac5 100644 --- a/src/components/MovieForm/index.tsx +++ b/src/components/MovieForm/index.tsx @@ -11,7 +11,10 @@ const MovieForm: React.FC = () => { return ( navigateToPage(movieTitle, movieYear, movieType)} + onSubmit={(e) => { + e.preventDefault() + navigateToPage(movieTitle, movieYear, movieType) + }} > Choose a movie title: { if (type) query += `&type=${type}` if (year) query += `&year=${year}` + console.log(query) + navigate(query) } } From a4c06834e47ed552fe36c6225e594c9098a1e794 Mon Sep 17 00:00:00 2001 From: haraldnilsen Date: Tue, 12 Sep 2023 13:22:16 +0200 Subject: [PATCH 4/5] :construction: back to working query params Co-authored-by: Sindre Kjelsrud --- src/App.tsx | 3 ++- src/components/MovieForm/index.tsx | 8 +++++--- src/util/navigate.ts | 6 ++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 109a21b..47d49ef 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,7 +4,7 @@ import q from 'qjuul' import { MovieForm, Pagination, MovieTable, MovieModal } from './components' import type { movieObject } from './types/movie' import { fetchMovie } from './api/fetchMovie' -import { useLocation } from 'react-router' +import { useLocation } from 'react-router-dom' function App() { const [movies, setMovies] = useState([]) @@ -22,6 +22,7 @@ function App() { if (response.Response == 'True') { setMovies(response.Search) setTotalPages(Number(response.totalResults)) + setCurrentPage(Number(page)) setLoading(false) } } diff --git a/src/components/MovieForm/index.tsx b/src/components/MovieForm/index.tsx index ff05ac5..5dd5ee3 100644 --- a/src/components/MovieForm/index.tsx +++ b/src/components/MovieForm/index.tsx @@ -3,9 +3,10 @@ import q from 'qjuul' import { useNavigateToPage } from '../../util/navigate' const MovieForm: React.FC = () => { - const [movieTitle, setMovieTitle] = useState('') - const [movieYear, setMovieYear] = useState('') - const [movieType, setMovieType] = useState('') + const searchParams = new URLSearchParams(window.location.search) + const [movieTitle, setMovieTitle] = useState(searchParams.get('title') || '') + const [movieYear, setMovieYear] = useState(searchParams.get('y') || '') + const [movieType, setMovieType] = useState(searchParams.get('type') || '') const navigateToPage = useNavigateToPage() return ( @@ -21,6 +22,7 @@ const MovieForm: React.FC = () => { type="text" id="movieTitle" placeholder="Movie title" + value={movieTitle.charAt(0).toUpperCase() + movieTitle.slice(1)} onChange={(e) => setMovieTitle(e.target.value)} className="border text-black border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent" /> diff --git a/src/util/navigate.ts b/src/util/navigate.ts index 56c2504..5bbb435 100644 --- a/src/util/navigate.ts +++ b/src/util/navigate.ts @@ -3,15 +3,13 @@ import { useNavigate } from 'react-router' export const useNavigateToPage = () => { const navigate = useNavigate() - return (title?: string, page: string = '1', type?: string, year?: string) => { + return (title?: string, type?: string, year?: string, page: string = '1') => { if (!title) navigate('') else { let query = `?title=${title}&page=${page}` - if (type) query += `&type=${type}` if (year) query += `&year=${year}` - - console.log(query) + if (type) query += `&type=${type}` navigate(query) } From 49144b1cc126f6b60f8a1cd9e4a82fe8643c3a0d Mon Sep 17 00:00:00 2001 From: Sindre Kjelsrud Date: Tue, 12 Sep 2023 14:06:53 +0200 Subject: [PATCH 5/5] =?UTF-8?q?:construction:=20pagination=20funker,=20men?= =?UTF-8?q?=20ikke=20=C3=A5r/type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: haraldnilsen --- src/App.tsx | 29 +++++++++++++++++++++++++--- src/api/fetchMovie.ts | 4 ++-- src/components/MovieForm/index.tsx | 31 +++++++++++++++++++++--------- src/util/navigate.ts | 8 +++++--- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 47d49ef..2a2d6b2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,7 @@ import { MovieForm, Pagination, MovieTable, MovieModal } from './components' import type { movieObject } from './types/movie' import { fetchMovie } from './api/fetchMovie' import { useLocation } from 'react-router-dom' +import { useNavigateToPage } from './util/navigate' function App() { const [movies, setMovies] = useState([]) @@ -13,12 +14,18 @@ function App() { const [totalPages, setTotalPages] = useState(0) const [modalOpen, setModalOpen] = useState(false) const [modalMovie, setModalMovie] = useState(null) + const navigateToPage = useNavigateToPage() + const searchParams = new URLSearchParams(window.location.search) + const [movieTitle, setMovieTitle] = useState(searchParams.get('title') || '') + const [movieYear, setMovieYear] = useState(searchParams.get('year') || '') + const [movieType, setMovieType] = useState(searchParams.get('type') || '') const [sortAscending, setSortAscending] = useState(true) const location = useLocation() useEffect(() => { const handleFetchMovie = async () => { const response = await fetchMovie(title, page, type, year) + console.log(year) if (response.Response == 'True') { setMovies(response.Search) setTotalPages(Number(response.totalResults)) @@ -30,7 +37,7 @@ function App() { const title = searchParams.get('title') || '' const page = searchParams.get('page') || '' const type = searchParams.get('type') || '' - const year = searchParams.get('y') || '' + const year = searchParams.get('year') || '' if (title) { handleFetchMovie() @@ -45,6 +52,7 @@ function App() { const handlePageChange = (pageNumber: number) => { setCurrentPage(pageNumber) + navigateToPage(movieTitle, movieType, movieYear, pageNumber.toString()) } const handleModalOpen = (movie: movieObject) => { @@ -79,8 +87,23 @@ function App() { - All movies - + navigateToPage()} + className="py-8 hover:cursor-pointer text-red-800 text-5xl font-bold" + co="rgb(220 38 38)" + > + Cinemateket + + {!loading && movies.length > 0 && ( response.json()) diff --git a/src/components/MovieForm/index.tsx b/src/components/MovieForm/index.tsx index 5dd5ee3..044542b 100644 --- a/src/components/MovieForm/index.tsx +++ b/src/components/MovieForm/index.tsx @@ -1,12 +1,23 @@ -import { useState } from 'react' import q from 'qjuul' import { useNavigateToPage } from '../../util/navigate' -const MovieForm: React.FC = () => { - const searchParams = new URLSearchParams(window.location.search) - const [movieTitle, setMovieTitle] = useState(searchParams.get('title') || '') - const [movieYear, setMovieYear] = useState(searchParams.get('y') || '') - const [movieType, setMovieType] = useState(searchParams.get('type') || '') +interface MovieFormInterface { + movieTitle: string + movieType: string + movieYear: string + setMovieTitle: (title: string) => void + setMovieType: (type: string) => void + setMovieYear: (year: string) => void +} + +const MovieForm: React.FC = ({ + movieTitle, + movieType, + movieYear, + setMovieTitle, + setMovieType, + setMovieYear, +}) => { const navigateToPage = useNavigateToPage() return ( @@ -14,7 +25,7 @@ const MovieForm: React.FC = () => { className="flex flex-col gap-3 card p-4 rounded-lg w-full lg:px-14" onSubmit={(e) => { e.preventDefault() - navigateToPage(movieTitle, movieYear, movieType) + navigateToPage(movieTitle, movieType, movieYear) }} > Choose a movie title: @@ -28,8 +39,9 @@ const MovieForm: React.FC = () => { /> Choose year movie was made: (OPTIONAL) setMovieYear(e.target.value)} + value={movieYear} > {/* Option for year 1923-2023 */} All years @@ -44,8 +56,9 @@ const MovieForm: React.FC = () => { Choose type: (OPTIONAL) setMovieType(e.target.value)} + value={movieType} > All types Movies diff --git a/src/util/navigate.ts b/src/util/navigate.ts index 5bbb435..74520c6 100644 --- a/src/util/navigate.ts +++ b/src/util/navigate.ts @@ -4,12 +4,14 @@ export const useNavigateToPage = () => { const navigate = useNavigate() return (title?: string, type?: string, year?: string, page: string = '1') => { - if (!title) navigate('') - else { + if (!title) { + navigate('') + window.location.reload() + } else { let query = `?title=${title}&page=${page}` - if (year) query += `&year=${year}` if (type) query += `&type=${type}` + if (year) query += `&year=${year}` navigate(query) }