diff --git a/src/app/film/[id]/page.tsx b/src/app/film/[id]/page.tsx index c1a90a4..f63528a 100644 --- a/src/app/film/[id]/page.tsx +++ b/src/app/film/[id]/page.tsx @@ -1,5 +1,8 @@ import { HeroMovie } from "@/components/molecules/HeroMovie"; import { MovieCast } from "@/components/molecules/MovieCast"; +import { SimilarMovies } from "@/components/molecules/SimilarMovies"; +import { RecommendedMovies } from "@/components/molecules/RecommendedMovies"; +import { MovieGallery } from "@/components/molecules/MovieGallery"; import { TMDB } from "@/lib/tmdb"; // Main movie details component. @@ -16,6 +19,12 @@ export default async function Page({
+ + +
); } diff --git a/src/components/atoms/MovieCard/layouts/AuroraLayout.tsx b/src/components/atoms/MovieCard/layouts/AuroraLayout.tsx index 8be99dd..6c6d8cd 100644 --- a/src/components/atoms/MovieCard/layouts/AuroraLayout.tsx +++ b/src/components/atoms/MovieCard/layouts/AuroraLayout.tsx @@ -205,17 +205,6 @@ export const AuroraLayout: FC = ({
- {/* Zobacz więcej button */} - -
- - Zobacz więcej -
- - {alreadyInStore && (
{seen && ( @@ -234,6 +223,17 @@ export const AuroraLayout: FC = ({ )}
+ + {/* Zobacz więcej button */} + +
+ + Zobacz więcej +
+ {/* Decorative border glow */} diff --git a/src/components/molecules/MovieGallery/index.tsx b/src/components/molecules/MovieGallery/index.tsx new file mode 100644 index 0000000..89a512c --- /dev/null +++ b/src/components/molecules/MovieGallery/index.tsx @@ -0,0 +1,214 @@ +"use client"; + +import { FC, useState } from "react"; +import { + FaImages, + FaTimes, + FaChevronLeft, + FaChevronRight, +} from "react-icons/fa"; + +type ImageData = { + aspect_ratio: number; + file_path: string; + height: number; + width: number; +}; + +type Props = { + images: { + backdrops: ImageData[]; + logos: ImageData[]; + posters: ImageData[]; + }; + movieTitle: string; +}; + +export const MovieGallery: FC = ({ images, movieTitle }) => { + const [selectedCategory, setSelectedCategory] = useState< + "backdrops" | "posters" | "logos" + >("backdrops"); + const [lightboxOpen, setLightboxOpen] = useState(false); + const [lightboxIndex, setLightboxIndex] = useState(0); + + const allImages = { + backdrops: images.backdrops.slice(0, 12), // Limit to first 12 for performance. + posters: images.posters.slice(0, 12), + logos: images.logos.slice(0, 8), + }; + + const currentImages = allImages[selectedCategory]; + + if ( + !images.backdrops.length && + !images.posters.length && + !images.logos.length + ) { + return null; + } + + const openLightbox = (index: number) => { + setLightboxIndex(index); + setLightboxOpen(true); + }; + + const closeLightbox = () => { + setLightboxOpen(false); + }; + + const nextImage = () => { + setLightboxIndex((prev) => (prev + 1) % currentImages.length); + }; + + const prevImage = () => { + setLightboxIndex( + (prev) => (prev - 1 + currentImages.length) % currentImages.length + ); + }; + + const getImageUrl = (path: string, size: string = "w500") => { + return `https://image.tmdb.org/t/p/${size}${path}`; + }; + + return ( +
+
+
+
+
+ +
+

+ Galeria +

+
+ + {/* Category tabs */} +
+ {Object.entries(allImages).map(([category, categoryImages]) => { + if (!categoryImages.length) return null; + + const labels = { + backdrops: "Kadry", + posters: "Plakaty", + logos: "Loga", + }; + + return ( + + ); + })} +
+ + {/* Image grid */} +
+ {currentImages.map((image, index) => ( +
openLightbox(index)} + > + {`${movieTitle} +
+
+
+ +
+
+
+ ))} +
+ + {/* Lightbox */} + {lightboxOpen && ( +
+
+ {/* Close button */} + + + {/* Navigation buttons */} + {currentImages.length > 1 && ( + <> + + + + )} + + {/* Image */} + {`${movieTitle} + + {/* Image counter */} + {currentImages.length > 1 && ( +
+ {lightboxIndex + 1} / {currentImages.length} +
+ )} +
+ + {/* Background click to close */} +
+
+ )} +
+
+
+ ); +}; diff --git a/src/components/molecules/RecommendedMovies/index.tsx b/src/components/molecules/RecommendedMovies/index.tsx new file mode 100644 index 0000000..b38ef42 --- /dev/null +++ b/src/components/molecules/RecommendedMovies/index.tsx @@ -0,0 +1,110 @@ +"use client"; + +import { SearchResult } from "@/lib/tmdb/types"; +import { MovieCard } from "@/components/atoms/MovieCard"; +import { FC, useState } from "react"; +import { FaChevronLeft, FaChevronRight, FaStar } from "react-icons/fa"; + +type Props = { + movies: SearchResult; +}; + +export const RecommendedMovies: FC = ({ movies }) => { + const [currentPage, setCurrentPage] = useState(0); + const moviesPerPage = 4; + const totalPages = Math.ceil(movies.results.length / moviesPerPage); + + if (!movies.results.length) return null; + + const currentMovies = movies.results.slice( + currentPage * moviesPerPage, + (currentPage + 1) * moviesPerPage + ); + + const nextPage = () => { + setCurrentPage((prev) => (prev + 1) % totalPages); + }; + + const prevPage = () => { + setCurrentPage((prev) => (prev - 1 + totalPages) % totalPages); + }; + + return ( +
+
+
+
+
+
+ +
+

+ Polecane dla Ciebie +

+
+ + {totalPages > 1 && ( +
+ + +
+ )} +
+ +
+ {currentMovies.map((movie) => ( + + ))} +
+ + {totalPages > 1 && ( +
+
+ {Array.from({ length: totalPages }, (_, i) => ( +
+
+ )} +
+
+
+ ); +}; diff --git a/src/components/molecules/SimilarMovies/index.tsx b/src/components/molecules/SimilarMovies/index.tsx new file mode 100644 index 0000000..747e0c1 --- /dev/null +++ b/src/components/molecules/SimilarMovies/index.tsx @@ -0,0 +1,105 @@ +"use client"; + +import { SearchResult } from "@/lib/tmdb/types"; +import { MovieCard } from "@/components/atoms/MovieCard"; +import { FC, useState } from "react"; +import { FaChevronLeft, FaChevronRight } from "react-icons/fa"; + +type Props = { + movies: SearchResult; +}; + +export const SimilarMovies: FC = ({ movies }) => { + const [currentPage, setCurrentPage] = useState(0); + const moviesPerPage = 4; + const totalPages = Math.ceil(movies.results.length / moviesPerPage); + + if (!movies.results.length) return null; + + const currentMovies = movies.results.slice( + currentPage * moviesPerPage, + (currentPage + 1) * moviesPerPage + ); + + const nextPage = () => { + setCurrentPage((prev) => (prev + 1) % totalPages); + }; + + const prevPage = () => { + setCurrentPage((prev) => (prev - 1 + totalPages) % totalPages); + }; + + return ( +
+
+
+
+

+ Podobne filmy +

+ + {totalPages > 1 && ( +
+ + +
+ )} +
+ +
+ {currentMovies.map((movie) => ( + + ))} +
+ + {totalPages > 1 && ( +
+
+ {Array.from({ length: totalPages }, (_, i) => ( +
+
+ )} +
+
+
+ ); +};