From e891b37384f740c793d5bf8ae4856bdf0370c46e Mon Sep 17 00:00:00 2001 From: Norbert Maciaszek Date: Mon, 18 Aug 2025 14:18:46 +0200 Subject: [PATCH] feat: replace MovieGallery with new Gallery component for improved image handling; update styles and functionality in related components --- src/app/aktor/[id]/page.tsx | 9 +- src/app/globals.css | 3 +- src/components/molecules/Gallery/index.tsx | 114 ++++++++++ src/components/molecules/MovieCast/index.tsx | 12 +- .../molecules/MovieGallery/index.tsx | 214 ------------------ 5 files changed, 124 insertions(+), 228 deletions(-) create mode 100644 src/components/molecules/Gallery/index.tsx delete mode 100644 src/components/molecules/MovieGallery/index.tsx diff --git a/src/app/aktor/[id]/page.tsx b/src/app/aktor/[id]/page.tsx index 8a1f356..96c5d03 100644 --- a/src/app/aktor/[id]/page.tsx +++ b/src/app/aktor/[id]/page.tsx @@ -1,7 +1,7 @@ import { MovieCard } from "@/components/atoms/MovieCard"; import { ActorHero } from "@/components/molecules/ActorHero"; import { Carousel } from "@/components/molecules/Carousel"; -import { MovieGallery } from "@/components/molecules/MovieGallery"; +import { Gallery } from "@/components/molecules/Gallery"; import { convertToMovie } from "@/helpers/convertToMovie"; import { TMDB } from "@/lib/tmdb"; import { FaStar } from "react-icons/fa"; @@ -14,16 +14,11 @@ export default async function Page({ const actorId = Number((await params).id); const personDetails = await TMDB.getPersonDetails(actorId); - const images = { - backdrops: personDetails.images.profiles, - posters: [], - logos: [], - }; return (
- +
; + limit?: number; +}; + +export const Gallery: FC = ({ + images, + heading, + limit: initialLimit = 14, +}) => { + const categories = Array.isArray(images) ? [] : Object.keys(images); + const [limit, setLimit] = useState(initialLimit); + const [selectedCategory, setSelectedCategory] = useState( + categories[0] || null + ); + + const currentImages: ImageData[] = + selectedCategory && typeof images === "object" + ? (images[selectedCategory as keyof typeof images] as ImageData[]) + : (images as ImageData[]); + + const getImageUrl = (path: string, size: string = "w500") => { + return `https://image.tmdb.org/t/p/${size}${path}`; + }; + + return ( +
+
+
+ {heading && ( +
+
+ +
+

+ {heading} +

+
+ )} + + {/* Category tabs */} + {categories.length > 0 && ( +
+ {Object.entries(images).map(([category, categoryImages]) => { + if (!categoryImages.length) return null; + + return ( + + ); + })} +
+ )} + + {/* Image grid */} +
div]:contents`}> + + {currentImages.slice(0, limit).map((image, index) => ( + + + + ))} + +
+ {limit < currentImages.length && ( +
+ +
+ )} +
+
+
+ ); +}; diff --git a/src/components/molecules/MovieCast/index.tsx b/src/components/molecules/MovieCast/index.tsx index 97461be..4f06541 100644 --- a/src/components/molecules/MovieCast/index.tsx +++ b/src/components/molecules/MovieCast/index.tsx @@ -10,11 +10,11 @@ type Props = { }; export const MovieCast: FC = ({ movieDetails }) => { - const [limitCast, setLimitCast] = useState(8); + const [limit, setLimit] = useState(8); const director = movieDetails?.credits.crew.find( (member) => member.job === "Director" ); - const mainCast = movieDetails?.credits.cast.slice(0, limitCast) || []; + const mainCast = movieDetails?.credits.cast.slice(0, limit) || []; const formatCurrency = (amount: number) => new Intl.NumberFormat("pl-PL", { @@ -67,18 +67,18 @@ export const MovieCast: FC = ({ movieDetails }) => { ))}
- {limitCast < movieDetails.credits.cast.length && ( + {limit < movieDetails.credits.cast.length && (
)} diff --git a/src/components/molecules/MovieGallery/index.tsx b/src/components/molecules/MovieGallery/index.tsx deleted file mode 100644 index 89a512c..0000000 --- a/src/components/molecules/MovieGallery/index.tsx +++ /dev/null @@ -1,214 +0,0 @@ -"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 */} -
-
- )} -
-
-
- ); -};