From f17deb1a6b63b094f9bd4d8d447970617ad7d622 Mon Sep 17 00:00:00 2001 From: johannes Date: Mon, 14 Sep 2026 14:54:58 +0200 Subject: [PATCH 1/3] Added favorite button, and saves favorite in local storage --- src/App.tsx | 10 ++++++---- src/api/tmdb.ts | 4 ++++ src/components/MovieList.tsx | 6 +++++- src/components/Movie_card.tsx | 14 +++++++++++++- src/components/sidebar.tsx | 2 +- src/hooks/useFavorites.ts | 25 +++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 src/hooks/useFavorites.ts diff --git a/src/App.tsx b/src/App.tsx index 580fb31..edcbc2f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,6 +7,7 @@ import MovieList from './components/MovieList'; import { PersonList } from './components/PersonList'; import './App.css'; import { useDebouncedValue } from './hooks/useDebouncedValue'; +import { useFavorites } from './hooks/useFavorites'; function App() { @@ -18,6 +19,7 @@ function App() { const debouncedQuery = useDebouncedValue(query, 400); const search = useSearchMovies(debouncedQuery) const isSearching = query.trim().length > 0; + const { isFavorite, toggleFavorite} = useFavorites(); return (
@@ -26,16 +28,16 @@ function App() {
{isSearching ? (
- {search.data && } + {search.data && }
- ) : ( + ) : ( <>
- {popular.data && } + {popular.data && }
- {current.data && } + {current.data && }
diff --git a/src/api/tmdb.ts b/src/api/tmdb.ts index 9a2df84..f10cc1c 100644 --- a/src/api/tmdb.ts +++ b/src/api/tmdb.ts @@ -42,4 +42,8 @@ export function fetchMovieCredits(movieId: number): Promise { `/movie/${movieId}/credits?language=en-US`, 'Klarte ikke hente skuespillere...', ); + + } + + diff --git a/src/components/MovieList.tsx b/src/components/MovieList.tsx index 794d4f4..ffac9db 100644 --- a/src/components/MovieList.tsx +++ b/src/components/MovieList.tsx @@ -9,9 +9,11 @@ import "./MovieList.css"; // MovieCard selv vet ingenting om TMDB eller fetching, den bare mottar props. type MovieListProps = { movies: Movie[]; + isFavorite: (id: number) => boolean; + onToggleFavorite: (id: number) => void; }; -function MovieList({ movies }: MovieListProps) { +function MovieList({ movies, isFavorite, onToggleFavorite }: MovieListProps) { return ( // Ytre container for hele filmlisten, kan style'es med CSS senere
@@ -35,6 +37,8 @@ function MovieList({ movies }: MovieListProps) { // Skuespillere ligger ikke i dette API-svaret (krever eget kall til /credits), // så vi sender en tom liste som placeholder inntil videre movieId={movie.id} + isFavorite={isFavorite(movie.id)} + onToggleFavorite={onToggleFavorite} /> ))}
diff --git a/src/components/Movie_card.tsx b/src/components/Movie_card.tsx index c856d10..c0ba426 100644 --- a/src/components/Movie_card.tsx +++ b/src/components/Movie_card.tsx @@ -8,9 +8,11 @@ interface MovieCardProps { title: string; // Filmens tittel, skal vises som overskrift posterUrl: string; // URL til filmplakat-bildet, brukes i rating: number; // Terningkast/prosent (0-100), f.eks. vote_average * 10 fra TMDB + isFavorite: boolean; // Om denne filmen er markert som favoritt + onToggleFavorite: (id: number) => void; // Kalles når stjernen klikkes } -function MovieCard({ movieId, title, posterUrl, rating }: MovieCardProps) { +function MovieCard({ movieId, title, posterUrl, rating, isFavorite, onToggleFavorite }: MovieCardProps) { // Henter skuespillere for akkurat denne filmen når kortet vises const { data: credits, isLoading } = useMovieCredits(movieId); @@ -19,6 +21,16 @@ function MovieCard({ movieId, title, posterUrl, rating }: MovieCardProps) { return (
+ + {rating}% {title} diff --git a/src/components/sidebar.tsx b/src/components/sidebar.tsx index b9e7248..a2a3cf3 100644 --- a/src/components/sidebar.tsx +++ b/src/components/sidebar.tsx @@ -47,7 +47,7 @@ export function Sidebar({onSearch, searchValue}: SidebarProps) { {section.label} - ))} + ))} diff --git a/src/hooks/useFavorites.ts b/src/hooks/useFavorites.ts new file mode 100644 index 0000000..06100a7 --- /dev/null +++ b/src/hooks/useFavorites.ts @@ -0,0 +1,25 @@ +import { useState, useEffect } from 'react'; + +const STORAGE_KEY = 'favorite-movies'; + +export function useFavorites() { + const [favoriteIds, setFavoriteIds] = useState(() => { + const stored = localStorage.getItem(STORAGE_KEY); + return stored ? JSON.parse(stored) : []; + }); + + useEffect(() => { + localStorage.setItem(STORAGE_KEY, JSON.stringify(favoriteIds)); + }, [favoriteIds]); + + function toggleFavorite(id: number) { + setFavoriteIds((prev) => + prev.includes(id) ? prev.filter((favId) => favId !== id) : [...prev, id] + ); + } + + function isFavorite(id: number) { + return favoriteIds.includes(id); + } + +return { toggleFavorite, isFavorite};} \ No newline at end of file From 823cef1da524ff640f0d3ff4318fb3daf02081c6 Mon Sep 17 00:00:00 2001 From: johannes Date: Mon, 14 Sep 2026 15:21:30 +0200 Subject: [PATCH 2/3] Made changes to favorites button, looks better --- src/components/Movie_card.css | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/components/Movie_card.css b/src/components/Movie_card.css index 607d594..f3c028b 100644 --- a/src/components/Movie_card.css +++ b/src/components/Movie_card.css @@ -83,6 +83,20 @@ z-index: 1; } +.movie-card__favorite { + position: absolute; + bottom: 0.5rem; + right: 0.5rem; + z-index: 1; + background: none; + border: none; + padding: 0; + font-size: 1.5rem; + line-height: 1; + color: #fbc02d; + cursor: pointer; +} + @media (max-width: 480px) { .movie-card__poster { width: 80px; From 4a3b176be5fcea7be522c2c173b8c0b9616d2383 Mon Sep 17 00:00:00 2001 From: Albert Paulsen Lindberg Date: Mon, 14 Sep 2026 16:31:48 +0200 Subject: [PATCH 3/3] Update MovieCard.css --- src/components/MovieCard.css | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/components/MovieCard.css b/src/components/MovieCard.css index 71ab0a5..0e7996b 100644 --- a/src/components/MovieCard.css +++ b/src/components/MovieCard.css @@ -98,20 +98,6 @@ cursor: pointer; } -.movie-card__favorite { - position: absolute; - bottom: 0.5rem; - right: 0.5rem; - z-index: 1; - background: none; - border: none; - padding: 0; - font-size: 1.5rem; - line-height: 1; - color: #fbc02d; - cursor: pointer; -} - @media (max-width: 480px) { .movie-card__poster { width: 80px; @@ -124,4 +110,4 @@ .movie-card__info { padding-right: 3rem; } -} \ No newline at end of file +}