From d21b4052b15450d5a5c66f05835647ab0ddd5e56 Mon Sep 17 00:00:00 2001 From: albdert Date: Mon, 14 Sep 2026 15:51:21 +0200 Subject: [PATCH] =?UTF-8?q?la=20til=20en=20visning=20p=C3=A5=20toppen=20fo?= =?UTF-8?q?r=20nye/trending=20filmer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 14 ++-- src/api/tmdb.ts | 8 +-- src/components/Button.tsx | 8 --- .../{Movie_card.css => MovieCard.css} | 0 .../{Movie_card.tsx => MovieCard.tsx} | 2 +- src/components/MovieList.tsx | 9 +-- src/components/Section.css | 0 src/components/TrendingPreview.css | 71 +++++++++++++++++++ src/components/TrendingPreview.tsx | 70 ++++++++++++++++++ .../{usePopMovies.ts => bak.usePopMovies} | 0 src/hooks/useMovies.ts | 4 +- src/types/tmdb.ts | 25 +++++++ 12 files changed, 186 insertions(+), 25 deletions(-) delete mode 100644 src/components/Button.tsx rename src/components/{Movie_card.css => MovieCard.css} (100%) rename src/components/{Movie_card.tsx => MovieCard.tsx} (98%) create mode 100644 src/components/Section.css create mode 100644 src/components/TrendingPreview.css create mode 100644 src/components/TrendingPreview.tsx rename src/hooks/{usePopMovies.ts => bak.usePopMovies} (100%) diff --git a/src/App.tsx b/src/App.tsx index 580fb31..e628e9c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,10 +3,11 @@ import { usePopMovies, useCurMovies, useSearchMovies } from './hooks/useMovies'; import { usePopularPeople } from './hooks/usePeople'; import { Sidebar } from './components/sidebar'; import { Section } from './components/Section'; -import MovieList from './components/MovieList'; +import { MovieList } from './components/MovieList'; import { PersonList } from './components/PersonList'; -import './App.css'; import { useDebouncedValue } from './hooks/useDebouncedValue'; +import './App.css'; +import { TrendingPreview } from './components/TrendingPreview'; function App() { @@ -26,16 +27,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 9a2df84..162cb09 100644 --- a/src/api/tmdb.ts +++ b/src/api/tmdb.ts @@ -1,13 +1,13 @@ +import type { Movie, Person, TmdbResponse, CreditsResponse } from '../types/tmdb'; + // TOKEN er lagret i root/.env.local, denne må alle legge til manuelt selv // og så må vi finne en løsning for å ha den tilgjengelig på serveren når vi // får satt den opp senere. -// BASE_URL er lenken vi bruker i en API request, her til TMDB - // TOKEN er lagret i .env.local, denne må alle legge til manuelt selv -import type { Movie, Person, TmdbResponse, CreditsResponse } from '../types/tmdb'; - const TOKEN = import.meta.env.VITE_TMDB_TOKEN; // v4 read access token + +// BASE_URL er lenken vi bruker i en API request, her til TMDB const BASE_URL = 'https://api.themoviedb.org/3'; async function tmdbFetch(path: string, errorMessage: string): Promise { diff --git a/src/components/Button.tsx b/src/components/Button.tsx deleted file mode 100644 index 332f004..0000000 --- a/src/components/Button.tsx +++ /dev/null @@ -1,8 +0,0 @@ -type ButtonProps = { - text: string; - onClick: () => void; -}; - -export function Button({ text, onClick }: ButtonProps) { - return ; -} \ No newline at end of file diff --git a/src/components/Movie_card.css b/src/components/MovieCard.css similarity index 100% rename from src/components/Movie_card.css rename to src/components/MovieCard.css diff --git a/src/components/Movie_card.tsx b/src/components/MovieCard.tsx similarity index 98% rename from src/components/Movie_card.tsx rename to src/components/MovieCard.tsx index c856d10..fb9fd10 100644 --- a/src/components/Movie_card.tsx +++ b/src/components/MovieCard.tsx @@ -1,5 +1,5 @@ import { useMovieCredits } from "../hooks/useMovieCredits"; -import "./Movie_card.css"; +import "./MovieCard.css"; // Definerer hvilke props (data utenfra) komponenten forventer å motta, // og hvilken type hver av dem skal ha. diff --git a/src/components/MovieList.tsx b/src/components/MovieList.tsx index 794d4f4..d7b2d4c 100644 --- a/src/components/MovieList.tsx +++ b/src/components/MovieList.tsx @@ -1,5 +1,5 @@ // Henter inn MovieCard-komponenten vår, slik at vi kan bruke den til å vise hver film. -import MovieCard from "./Movie_card"; +import MovieCard from "./MovieCard"; import type { Movie } from "../types/tmdb"; import "./MovieList.css"; @@ -11,7 +11,7 @@ type MovieListProps = { movies: Movie[]; }; -function MovieList({ movies }: MovieListProps) { +export function MovieList({ movies }: MovieListProps) { return ( // Ytre container for hele filmlisten, kan style'es med CSS senere
@@ -39,7 +39,4 @@ function MovieList({ movies }: MovieListProps) { ))}
); -} - -// Eksporterer komponenten slik at App.tsx (eller en layout-komponent) kan bruke -export default MovieList; \ No newline at end of file +} \ No newline at end of file diff --git a/src/components/Section.css b/src/components/Section.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/TrendingPreview.css b/src/components/TrendingPreview.css new file mode 100644 index 0000000..32702d2 --- /dev/null +++ b/src/components/TrendingPreview.css @@ -0,0 +1,71 @@ +.hero { + position: relative; + width: 100%; + height: 30vh; /* adjust to taste, or set a fixed px value */ + overflow: hidden; + border-radius: 1rem; +} + +.backdrop { + width: 33.333%; + height: 100%; + object-fit: cover; + flex-shrink: 0; +} + +.hero-title { + position: absolute; + left: 1.5rem; + bottom: 1.5rem; + color: white; + margin: 0; + z-index: 2; + cursor: pointer; +} + +.hero-track { + display: flex; + width: 300%; + height: 100%; +} + +.hero-zone { + position: absolute; + top: 0; + height: 100%; + width: 10%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + z-index: 3; + user-select: none; +} + +.hero-zone-left { + left: 0; +} + +.hero-zone-middle { + left: 10%; + width: 80%; + cursor: pointer; +} + +.hero-zone-right { + right: 0; +} + +.hero-arrow { + display: inline-block; + /*transform: skewX(-15deg);*/ + font-size: 2rem; + color: white; + opacity: 0.7; + transition: opacity 0.2s; + user-select: none; +} + +.hero-zone:hover .hero-arrow { + opacity: 1; +} diff --git a/src/components/TrendingPreview.tsx b/src/components/TrendingPreview.tsx new file mode 100644 index 0000000..ae18d56 --- /dev/null +++ b/src/components/TrendingPreview.tsx @@ -0,0 +1,70 @@ +import { useState } from "react"; +import type { Movie } from "../types/tmdb"; +import "./TrendingPreview.css" + +type TrendingPreviewProps = { + movies : Movie[]; +}; + +export function TrendingPreview({ movies }: TrendingPreviewProps) { + const [index, setIndex] = useState(0); + const [offset, setOffset] = useState(0); + const [transitioning, setTransitioning] = useState(false); + + const prevIndex = ( (index-1+movies.length) % movies.length ); + const nextIndex = ( (index+1) % movies.length ); + const movie = movies[index]; + + function handleClick( n: number ) { + if (transitioning) { return; } + setTransitioning(true); + setOffset(-n); + + setTimeout(() => { + setIndex( (i) => ((i+n+movies.length) % movies.length) ); + setOffset(0); + setTransitioning(false); + }, 400); + } + + function openDetails() { + return; + } + + return ( +
+
+ + + +
+ +

{movie.title}

+ +
handleClick(-1)}> + {"❮"} +
+ +
+ +
handleClick(1)}> + {"❯"} +
+
+ ); +} \ No newline at end of file diff --git a/src/hooks/usePopMovies.ts b/src/hooks/bak.usePopMovies similarity index 100% rename from src/hooks/usePopMovies.ts rename to src/hooks/bak.usePopMovies diff --git a/src/hooks/useMovies.ts b/src/hooks/useMovies.ts index 6a59a98..24fc303 100644 --- a/src/hooks/useMovies.ts +++ b/src/hooks/useMovies.ts @@ -6,6 +6,7 @@ export function usePopMovies() { return useQuery({ queryKey: ['movies', 'popular'], queryFn: fetchPopularMovies, + select: (data) => data.results, }) } @@ -13,7 +14,7 @@ export function useCurMovies() { return useQuery({ queryKey: ['movies', 'current'], queryFn: fetchCurrentMovies, - + select: (data) => data.results, }) } @@ -22,5 +23,6 @@ export function useSearchMovies(query: string) { queryKey: ['movies', 'search', query], queryFn: () => fetchSearchMovies(query), enabled: query.trim().length > 0, + select: (data) => data.results, }) } \ No newline at end of file diff --git a/src/types/tmdb.ts b/src/types/tmdb.ts index 053c623..0563d0b 100644 --- a/src/types/tmdb.ts +++ b/src/types/tmdb.ts @@ -1,11 +1,36 @@ export type Movie = { id: number; title: string; + overview: string; + backdrop_path: string | null; poster_path: string | null; vote_average: number; release_date: string; }; +/* +{ + "adult": false, + "backdrop_path": "/gMJngTNfaqCSCqGD4y8lVMZXKDn.jpg", + "genre_ids": [ + 28, + 12, + 878 + ], + "id": 640146, + "original_language": "en", + "original_title": "Ant-Man and the Wasp: Quantumania", + "overview": "Super-Hero partners Scott Lang and Hope van Dyne, along with with Hope's parents Janet van Dyne and Hank Pym, and Scott's daughter Cassie Lang, find themselves exploring the Quantum Realm, interacting with strange new creatures and embarking on an adventure that will push them beyond the limits of what they thought possible.", + "popularity": 8567.865, + "poster_path": "/ngl2FKBlU4fhbdsrtdom9LVLBXw.jpg", + "release_date": "2023-02-15", + "title": "Ant-Man and the Wasp: Quantumania", + "video": false, + "vote_average": 6.5, + "vote_count": 1886 + }, + + */ export type Person = { id: number; name: string;