Add movie gallery, similar movies, and recommended movies components: integrate MovieGallery, SimilarMovies, and RecommendedMovies into the film detail page for enhanced user engagement. Update AuroraLayout to improve button visibility and interaction.
This commit is contained in:
		
							parent
							
								
									61395ca1ec
								
							
						
					
					
						commit
						dc0d7693c1
					
				|  | @ -1,5 +1,8 @@ | ||||||
| import { HeroMovie } from "@/components/molecules/HeroMovie"; | import { HeroMovie } from "@/components/molecules/HeroMovie"; | ||||||
| import { MovieCast } from "@/components/molecules/MovieCast"; | 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"; | import { TMDB } from "@/lib/tmdb"; | ||||||
| 
 | 
 | ||||||
| // Main movie details component.
 | // Main movie details component.
 | ||||||
|  | @ -16,6 +19,12 @@ export default async function Page({ | ||||||
|     <div className="min-h-screen mt-16"> |     <div className="min-h-screen mt-16"> | ||||||
|       <HeroMovie movieDetails={movieDetails} /> |       <HeroMovie movieDetails={movieDetails} /> | ||||||
|       <MovieCast movieDetails={movieDetails} /> |       <MovieCast movieDetails={movieDetails} /> | ||||||
|  |       <MovieGallery | ||||||
|  |         images={movieDetails.images} | ||||||
|  |         movieTitle={movieDetails.title} | ||||||
|  |       /> | ||||||
|  |       <SimilarMovies movies={movieDetails.similar} /> | ||||||
|  |       <RecommendedMovies movies={movieDetails.recommendations} /> | ||||||
|     </div> |     </div> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -205,17 +205,6 @@ export const AuroraLayout: FC<AuroraLayoutProps> = ({ | ||||||
|             </div> |             </div> | ||||||
| 
 | 
 | ||||||
|             <div className="flex items-center gap-3"> |             <div className="flex items-center gap-3"> | ||||||
|               {/* Zobacz więcej button */} |  | ||||||
|               <Link |  | ||||||
|                 href={`/film/${id}`} |  | ||||||
|                 className="opacity-0 group-hover:opacity-100 transition-all duration-300 transform group-hover:scale-105" |  | ||||||
|               > |  | ||||||
|                 <div className="flex items-center gap-2 bg-gradient-to-r from-purple-600/90 to-pink-600/90 hover:from-purple-500 hover:to-pink-500 px-3 py-2 rounded-lg text-white text-sm font-medium shadow-lg border border-white/10 transition-all duration-300"> |  | ||||||
|                   <FaInfoCircle size={14} /> |  | ||||||
|                   <span>Zobacz więcej</span> |  | ||||||
|                 </div> |  | ||||||
|               </Link> |  | ||||||
| 
 |  | ||||||
|               {alreadyInStore && ( |               {alreadyInStore && ( | ||||||
|                 <div className="flex gap-2"> |                 <div className="flex gap-2"> | ||||||
|                   {seen && ( |                   {seen && ( | ||||||
|  | @ -234,6 +223,17 @@ export const AuroraLayout: FC<AuroraLayoutProps> = ({ | ||||||
|               )} |               )} | ||||||
|             </div> |             </div> | ||||||
|           </div> |           </div> | ||||||
|  | 
 | ||||||
|  |           {/* Zobacz więcej button */} | ||||||
|  |           <Link | ||||||
|  |             href={`/film/${id}`} | ||||||
|  |             className="transform hover:scale-105 transition-all duration-300 mt-4 flex justify-center" | ||||||
|  |           > | ||||||
|  |             <div className="inline-flex items-center gap-2 bg-gradient-to-r from-purple-600/90 to-pink-600/90 hover:from-purple-500 hover:to-pink-500 px-3 py-2 rounded-lg text-white text-sm font-medium shadow-lg border border-white/10 transition-all duration-300"> | ||||||
|  |               <FaInfoCircle size={14} /> | ||||||
|  |               <span>Zobacz więcej</span> | ||||||
|  |             </div> | ||||||
|  |           </Link> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         {/* Decorative border glow */} |         {/* Decorative border glow */} | ||||||
|  |  | ||||||
|  | @ -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<Props> = ({ 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 ( | ||||||
|  |     <section className="py-16"> | ||||||
|  |       <div className="px-6 lg:px-8"> | ||||||
|  |         <div className="max-w-7xl mx-auto"> | ||||||
|  |           <div className="flex items-center gap-3 mb-8"> | ||||||
|  |             <div className="p-2 rounded-lg bg-gradient-to-r from-purple-500 to-pink-500"> | ||||||
|  |               <FaImages className="text-white" size={20} /> | ||||||
|  |             </div> | ||||||
|  |             <h2 className="text-3xl font-bold bg-gradient-to-r from-purple-400 to-pink-400 bg-clip-text text-transparent"> | ||||||
|  |               Galeria | ||||||
|  |             </h2> | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           {/* Category tabs */} | ||||||
|  |           <div className="flex gap-4 mb-8"> | ||||||
|  |             {Object.entries(allImages).map(([category, categoryImages]) => { | ||||||
|  |               if (!categoryImages.length) return null; | ||||||
|  | 
 | ||||||
|  |               const labels = { | ||||||
|  |                 backdrops: "Kadry", | ||||||
|  |                 posters: "Plakaty", | ||||||
|  |                 logos: "Loga", | ||||||
|  |               }; | ||||||
|  | 
 | ||||||
|  |               return ( | ||||||
|  |                 <button | ||||||
|  |                   key={category} | ||||||
|  |                   onClick={() => | ||||||
|  |                     setSelectedCategory(category as keyof typeof allImages) | ||||||
|  |                   } | ||||||
|  |                   className={`px-6 py-3 rounded-xl font-medium transition-all duration-300 ${ | ||||||
|  |                     selectedCategory === category | ||||||
|  |                       ? "bg-gradient-to-r from-purple-600 to-pink-600 text-white shadow-lg" | ||||||
|  |                       : "bg-white/10 text-gray-300 hover:bg-white/20 hover:text-white" | ||||||
|  |                   }`}
 | ||||||
|  |                 > | ||||||
|  |                   {labels[category as keyof typeof labels]} ( | ||||||
|  |                   {categoryImages.length}) | ||||||
|  |                 </button> | ||||||
|  |               ); | ||||||
|  |             })} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           {/* Image grid */} | ||||||
|  |           <div | ||||||
|  |             className={`grid gap-4 ${ | ||||||
|  |               selectedCategory === "backdrops" | ||||||
|  |                 ? "grid-cols-1 md:grid-cols-2 lg:grid-cols-3" | ||||||
|  |                 : selectedCategory === "posters" | ||||||
|  |                 ? "grid-cols-2 md:grid-cols-4 lg:grid-cols-6" | ||||||
|  |                 : "grid-cols-2 md:grid-cols-3 lg:grid-cols-4" | ||||||
|  |             }`}
 | ||||||
|  |           > | ||||||
|  |             {currentImages.map((image, index) => ( | ||||||
|  |               <div | ||||||
|  |                 key={index} | ||||||
|  |                 className="group relative overflow-hidden rounded-xl cursor-pointer bg-slate-800" | ||||||
|  |                 onClick={() => openLightbox(index)} | ||||||
|  |               > | ||||||
|  |                 <img | ||||||
|  |                   src={getImageUrl( | ||||||
|  |                     image.file_path, | ||||||
|  |                     selectedCategory === "backdrops" ? "w780" : "w342" | ||||||
|  |                   )} | ||||||
|  |                   alt={`${movieTitle} - ${selectedCategory}`} | ||||||
|  |                   className="w-full h-full object-cover transition-all duration-500 group-hover:scale-110" | ||||||
|  |                   style={{ | ||||||
|  |                     aspectRatio: | ||||||
|  |                       selectedCategory === "backdrops" | ||||||
|  |                         ? "16/9" | ||||||
|  |                         : selectedCategory === "posters" | ||||||
|  |                         ? "2/3" | ||||||
|  |                         : "auto", | ||||||
|  |                   }} | ||||||
|  |                 /> | ||||||
|  |                 <div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" /> | ||||||
|  |                 <div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300"> | ||||||
|  |                   <div className="p-3 rounded-full bg-white/20 backdrop-blur-sm"> | ||||||
|  |                     <FaImages className="text-white" size={20} /> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             ))} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           {/* Lightbox */} | ||||||
|  |           {lightboxOpen && ( | ||||||
|  |             <div className="fixed inset-0 z-50 bg-black/90 flex items-center justify-center p-4"> | ||||||
|  |               <div className="relative max-w-6xl max-h-full"> | ||||||
|  |                 {/* Close button */} | ||||||
|  |                 <button | ||||||
|  |                   onClick={closeLightbox} | ||||||
|  |                   className="absolute top-4 right-4 z-10 p-2 rounded-full bg-black/50 text-white hover:bg-black/70 transition-colors" | ||||||
|  |                 > | ||||||
|  |                   <FaTimes size={20} /> | ||||||
|  |                 </button> | ||||||
|  | 
 | ||||||
|  |                 {/* Navigation buttons */} | ||||||
|  |                 {currentImages.length > 1 && ( | ||||||
|  |                   <> | ||||||
|  |                     <button | ||||||
|  |                       onClick={prevImage} | ||||||
|  |                       className="absolute left-4 top-1/2 -translate-y-1/2 z-10 p-3 rounded-full bg-black/50 text-white hover:bg-black/70 transition-colors" | ||||||
|  |                     > | ||||||
|  |                       <FaChevronLeft size={20} /> | ||||||
|  |                     </button> | ||||||
|  |                     <button | ||||||
|  |                       onClick={nextImage} | ||||||
|  |                       className="absolute right-4 top-1/2 -translate-y-1/2 z-10 p-3 rounded-full bg-black/50 text-white hover:bg-black/70 transition-colors" | ||||||
|  |                     > | ||||||
|  |                       <FaChevronRight size={20} /> | ||||||
|  |                     </button> | ||||||
|  |                   </> | ||||||
|  |                 )} | ||||||
|  | 
 | ||||||
|  |                 {/* Image */} | ||||||
|  |                 <img | ||||||
|  |                   src={getImageUrl( | ||||||
|  |                     currentImages[lightboxIndex].file_path, | ||||||
|  |                     "original" | ||||||
|  |                   )} | ||||||
|  |                   alt={`${movieTitle} - ${selectedCategory}`} | ||||||
|  |                   className="max-w-full max-h-full object-contain rounded-lg" | ||||||
|  |                 /> | ||||||
|  | 
 | ||||||
|  |                 {/* Image counter */} | ||||||
|  |                 {currentImages.length > 1 && ( | ||||||
|  |                   <div className="absolute bottom-4 left-1/2 -translate-x-1/2 px-4 py-2 rounded-full bg-black/50 text-white text-sm"> | ||||||
|  |                     {lightboxIndex + 1} / {currentImages.length} | ||||||
|  |                   </div> | ||||||
|  |                 )} | ||||||
|  |               </div> | ||||||
|  | 
 | ||||||
|  |               {/* Background click to close */} | ||||||
|  |               <div className="absolute inset-0 -z-10" onClick={closeLightbox} /> | ||||||
|  |             </div> | ||||||
|  |           )} | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </section> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | @ -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<Props> = ({ 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 ( | ||||||
|  |     <section className="py-16 bg-gradient-to-br from-slate-900/50 to-slate-800/50"> | ||||||
|  |       <div className="px-6 lg:px-8"> | ||||||
|  |         <div className="max-w-7xl mx-auto"> | ||||||
|  |           <div className="flex items-center justify-between mb-8"> | ||||||
|  |             <div className="flex items-center gap-3"> | ||||||
|  |               <div className="p-2 rounded-lg bg-gradient-to-r from-yellow-500 to-orange-500"> | ||||||
|  |                 <FaStar className="text-white" size={20} /> | ||||||
|  |               </div> | ||||||
|  |               <h2 className="text-3xl font-bold bg-gradient-to-r from-yellow-400 to-orange-400 bg-clip-text text-transparent"> | ||||||
|  |                 Polecane dla Ciebie | ||||||
|  |               </h2> | ||||||
|  |             </div> | ||||||
|  | 
 | ||||||
|  |             {totalPages > 1 && ( | ||||||
|  |               <div className="flex gap-2"> | ||||||
|  |                 <button | ||||||
|  |                   onClick={prevPage} | ||||||
|  |                   className="p-3 rounded-full bg-gradient-to-r from-yellow-500/20 to-orange-500/20 hover:from-yellow-500/30 hover:to-orange-500/30 text-white transition-all duration-300 border border-yellow-400/30" | ||||||
|  |                 > | ||||||
|  |                   <FaChevronLeft size={16} /> | ||||||
|  |                 </button> | ||||||
|  |                 <button | ||||||
|  |                   onClick={nextPage} | ||||||
|  |                   className="p-3 rounded-full bg-gradient-to-r from-yellow-500/20 to-orange-500/20 hover:from-yellow-500/30 hover:to-orange-500/30 text-white transition-all duration-300 border border-yellow-400/30" | ||||||
|  |                 > | ||||||
|  |                   <FaChevronRight size={16} /> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             )} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"> | ||||||
|  |             {currentMovies.map((movie) => ( | ||||||
|  |               <MovieCard | ||||||
|  |                 key={movie.id} | ||||||
|  |                 layout="aurora" | ||||||
|  |                 id={movie.id} | ||||||
|  |                 title={movie.title} | ||||||
|  |                 overview={movie.overview} | ||||||
|  |                 poster_path={movie.poster_path} | ||||||
|  |                 release_date={movie.release_date} | ||||||
|  |                 vote_average={movie.vote_average} | ||||||
|  |                 popularity={movie.popularity} | ||||||
|  |                 adult={movie.adult} | ||||||
|  |                 backdrop_path={movie.backdrop_path} | ||||||
|  |                 genre_ids={movie.genre_ids.join(",")} | ||||||
|  |                 original_language={movie.original_language} | ||||||
|  |                 original_title={movie.original_title} | ||||||
|  |                 video={movie.video} | ||||||
|  |                 vote_count={movie.vote_count} | ||||||
|  |                 seen={false} | ||||||
|  |                 favorite={false} | ||||||
|  |               /> | ||||||
|  |             ))} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           {totalPages > 1 && ( | ||||||
|  |             <div className="flex justify-center mt-8"> | ||||||
|  |               <div className="flex gap-2"> | ||||||
|  |                 {Array.from({ length: totalPages }, (_, i) => ( | ||||||
|  |                   <button | ||||||
|  |                     key={i} | ||||||
|  |                     onClick={() => setCurrentPage(i)} | ||||||
|  |                     className={`w-3 h-3 rounded-full transition-all duration-300 ${ | ||||||
|  |                       currentPage === i | ||||||
|  |                         ? "bg-gradient-to-r from-yellow-500 to-orange-500 scale-110" | ||||||
|  |                         : "bg-white/30 hover:bg-white/50" | ||||||
|  |                     }`}
 | ||||||
|  |                   /> | ||||||
|  |                 ))} | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           )} | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </section> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | @ -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<Props> = ({ 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 ( | ||||||
|  |     <section className="py-16"> | ||||||
|  |       <div className="px-6 lg:px-8"> | ||||||
|  |         <div className="max-w-7xl mx-auto"> | ||||||
|  |           <div className="flex items-center justify-between mb-8"> | ||||||
|  |             <h2 className="text-3xl font-bold bg-gradient-to-r from-white to-gray-300 bg-clip-text text-transparent"> | ||||||
|  |               Podobne filmy | ||||||
|  |             </h2> | ||||||
|  | 
 | ||||||
|  |             {totalPages > 1 && ( | ||||||
|  |               <div className="flex gap-2"> | ||||||
|  |                 <button | ||||||
|  |                   onClick={prevPage} | ||||||
|  |                   className="p-3 rounded-full bg-white/10 hover:bg-white/20 text-white transition-all duration-300 border border-white/20 hover:border-purple-400/50" | ||||||
|  |                 > | ||||||
|  |                   <FaChevronLeft size={16} /> | ||||||
|  |                 </button> | ||||||
|  |                 <button | ||||||
|  |                   onClick={nextPage} | ||||||
|  |                   className="p-3 rounded-full bg-white/10 hover:bg-white/20 text-white transition-all duration-300 border border-white/20 hover:border-purple-400/50" | ||||||
|  |                 > | ||||||
|  |                   <FaChevronRight size={16} /> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             )} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"> | ||||||
|  |             {currentMovies.map((movie) => ( | ||||||
|  |               <MovieCard | ||||||
|  |                 key={movie.id} | ||||||
|  |                 layout="aurora" | ||||||
|  |                 id={movie.id} | ||||||
|  |                 title={movie.title} | ||||||
|  |                 overview={movie.overview} | ||||||
|  |                 poster_path={movie.poster_path} | ||||||
|  |                 release_date={movie.release_date} | ||||||
|  |                 vote_average={movie.vote_average} | ||||||
|  |                 popularity={movie.popularity} | ||||||
|  |                 adult={movie.adult} | ||||||
|  |                 backdrop_path={movie.backdrop_path} | ||||||
|  |                 genre_ids={movie.genre_ids.join(",")} | ||||||
|  |                 original_language={movie.original_language} | ||||||
|  |                 original_title={movie.original_title} | ||||||
|  |                 video={movie.video} | ||||||
|  |                 vote_count={movie.vote_count} | ||||||
|  |                 seen={false} | ||||||
|  |                 favorite={false} | ||||||
|  |               /> | ||||||
|  |             ))} | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           {totalPages > 1 && ( | ||||||
|  |             <div className="flex justify-center mt-8"> | ||||||
|  |               <div className="flex gap-2"> | ||||||
|  |                 {Array.from({ length: totalPages }, (_, i) => ( | ||||||
|  |                   <button | ||||||
|  |                     key={i} | ||||||
|  |                     onClick={() => setCurrentPage(i)} | ||||||
|  |                     className={`w-3 h-3 rounded-full transition-all duration-300 ${ | ||||||
|  |                       currentPage === i | ||||||
|  |                         ? "bg-gradient-to-r from-purple-500 to-pink-500 scale-110" | ||||||
|  |                         : "bg-white/30 hover:bg-white/50" | ||||||
|  |                     }`}
 | ||||||
|  |                   /> | ||||||
|  |                 ))} | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           )} | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </section> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
		Loading…
	
		Reference in New Issue