diff --git a/src/App.tsx b/src/App.tsx index e628e9c..3ef9071 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,8 +6,9 @@ import { Section } from './components/Section'; import { MovieList } from './components/MovieList'; import { PersonList } from './components/PersonList'; import { useDebouncedValue } from './hooks/useDebouncedValue'; -import './App.css'; +import { useFavorites } from './hooks/useFavorites'; import { TrendingPreview } from './components/TrendingPreview'; +import './App.css'; function App() { @@ -19,6 +20,7 @@ function App() { const debouncedQuery = useDebouncedValue(query, 400); const search = useSearchMovies(debouncedQuery) const isSearching = query.trim().length > 0; + const { isFavorite, toggleFavorite} = useFavorites(); return (
@@ -27,19 +29,19 @@ function App() {
{isSearching ? (
- {search.data && } + {search.data && }
- ) : ( + ) : ( <>
{current.data && }
- {popular.data && } + {popular.data && }
- {current.data && } + {current.data && }
diff --git a/src/api/tmdb.ts b/src/api/tmdb.ts index 162cb09..a837d11 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/MovieCard.css b/src/components/MovieCard.css index 607d594..0e7996b 100644 --- a/src/components/MovieCard.css +++ b/src/components/MovieCard.css @@ -83,6 +83,21 @@ z-index: 1; } +/*Favorite merke som stjerne nede til venste*/ +.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; @@ -95,4 +110,4 @@ .movie-card__info { padding-right: 3rem; } -} \ No newline at end of file +} diff --git a/src/components/MovieCard.tsx b/src/components/MovieCard.tsx index fb9fd10..527203a 100644 --- a/src/components/MovieCard.tsx +++ b/src/components/MovieCard.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/MovieList.tsx b/src/components/MovieList.tsx index d7b2d4c..fa9e86a 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; }; -export function MovieList({ movies }: MovieListProps) { +export function MovieList({ movies, isFavorite, onToggleFavorite }: MovieListProps) { return ( // Ytre container for hele filmlisten, kan style'es med CSS senere
@@ -35,6 +37,8 @@ export 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/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