feat: add TrackedMovies component to display upcoming and currently showing films; introduce MovieRow for individual movie representation
This commit is contained in:
		
							parent
							
								
									7aafeb8343
								
							
						
					
					
						commit
						64bb4cd4e4
					
				|  | @ -1,8 +1,10 @@ | ||||||
| import { MovieList } from "@/components/molecules/MovieList"; | import { MovieList } from "@/components/molecules/MovieList"; | ||||||
|  | import { TrackedMovies } from "@/components/molecules/TrackedMovies"; | ||||||
| 
 | 
 | ||||||
| export default async function Home() { | export default async function Home() { | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|  |       <TrackedMovies /> | ||||||
|       <MovieList |       <MovieList | ||||||
|         heading="Nadchodzące" |         heading="Nadchodzące" | ||||||
|         filterUpcoming={1} |         filterUpcoming={1} | ||||||
|  |  | ||||||
|  | @ -0,0 +1,72 @@ | ||||||
|  | import { formatter } from "@/helpers/formater"; | ||||||
|  | import { Movie } from "@/types/global"; | ||||||
|  | import Link from "next/link"; | ||||||
|  | import { FC } from "react"; | ||||||
|  | import { FaCalendar, FaClock, FaStar } from "react-icons/fa"; | ||||||
|  | 
 | ||||||
|  | export const MovieRow: FC<{ movie: Movie; isUpcoming: boolean }> = ({ | ||||||
|  |   movie, | ||||||
|  |   isUpcoming, | ||||||
|  | }) => { | ||||||
|  |   const daysSinceRelease = Math.abs( | ||||||
|  |     Math.floor( | ||||||
|  |       (new Date().getTime() - new Date(movie.release_date).getTime()) / | ||||||
|  |         (1000 * 60 * 60 * 24) | ||||||
|  |     ) | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <Link | ||||||
|  |       href={`/film/${movie.id}`} | ||||||
|  |       className="flex items-center gap-4 p-3 rounded-lg bg-gray-800/30 hover:bg-gray-800/50 transition-colors group" | ||||||
|  |     > | ||||||
|  |       <div className="relative w-12 h-16 rounded overflow-hidden flex-shrink-0"> | ||||||
|  |         <img | ||||||
|  |           src={`https://image.tmdb.org/t/p/w154${movie.poster_path}`} | ||||||
|  |           alt={movie.title} | ||||||
|  |           className="object-cover inset-0" | ||||||
|  |           sizes="48px" | ||||||
|  |         /> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       <div className="flex-1 min-w-0"> | ||||||
|  |         <h3 className="text-white font-medium text-sm truncate group-hover:text-blue-400 transition-colors"> | ||||||
|  |           {movie.title} | ||||||
|  |         </h3> | ||||||
|  |         <div className="flex items-center gap-3 mt-1"> | ||||||
|  |           <div className="flex items-center gap-1 text-gray-400 text-xs"> | ||||||
|  |             {isUpcoming ? ( | ||||||
|  |               <FaCalendar className="w-3 h-3" /> | ||||||
|  |             ) : ( | ||||||
|  |               <FaClock className="w-3 h-3" /> | ||||||
|  |             )} | ||||||
|  |             <span>{formatter.formatDate(movie.release_date)}</span> | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           {!!movie.vote_average && ( | ||||||
|  |             <div className="flex items-center gap-1 text-yellow-400 text-xs"> | ||||||
|  |               <FaStar className="w-3 h-3 fill-current" /> | ||||||
|  |               <span>{movie.vote_average.toFixed(1)}</span> | ||||||
|  |             </div> | ||||||
|  |           )} | ||||||
|  | 
 | ||||||
|  |           {movie.favorite && ( | ||||||
|  |             <div className="w-2 h-2 bg-red-500 rounded-full" title="Ulubione" /> | ||||||
|  |           )} | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       <div | ||||||
|  |         className={`text-xs px-2 py-1 rounded-full font-medium ${ | ||||||
|  |           isUpcoming | ||||||
|  |             ? "bg-blue-500/20 text-blue-400" | ||||||
|  |             : "bg-green-500/20 text-green-400" | ||||||
|  |         }`}
 | ||||||
|  |       > | ||||||
|  |         {isUpcoming | ||||||
|  |           ? `za ${daysSinceRelease} dni` | ||||||
|  |           : `od ${daysSinceRelease} dni`} | ||||||
|  |       </div> | ||||||
|  |     </Link> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | @ -0,0 +1,84 @@ | ||||||
|  | "use client"; | ||||||
|  | import { FC } from "react"; | ||||||
|  | import { useGlobalStore } from "@/app/store/globalStore"; | ||||||
|  | import Link from "next/link"; | ||||||
|  | import { FaCalendar, FaClock, FaStar } from "react-icons/fa"; | ||||||
|  | import { MovieRow } from "@/components/atoms/MovieRow"; | ||||||
|  | 
 | ||||||
|  | export const TrackedMovies: FC = () => { | ||||||
|  |   const { movies } = useGlobalStore(); | ||||||
|  | 
 | ||||||
|  |   if (movies.length === 0) { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const today = new Date(); | ||||||
|  |   const upcoming = movies.filter( | ||||||
|  |     (movie) => new Date(movie.release_date) > today | ||||||
|  |   ); | ||||||
|  |   const inCinema = movies.filter((movie) => { | ||||||
|  |     const daysSinceRelease = Math.floor( | ||||||
|  |       (new Date().getTime() - new Date(movie.release_date).getTime()) / | ||||||
|  |         (1000 * 60 * 60 * 24) | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     return ( | ||||||
|  |       new Date(movie.release_date) <= today && | ||||||
|  |       daysSinceRelease <= 30 && | ||||||
|  |       !movie.seen | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   // Sort by release date.
 | ||||||
|  |   const sortedUpcoming = upcoming.sort( | ||||||
|  |     (a, b) => | ||||||
|  |       new Date(a.release_date).getTime() - new Date(b.release_date).getTime() | ||||||
|  |   ); | ||||||
|  |   const sortedInCinema = inCinema.sort( | ||||||
|  |     (a, b) => | ||||||
|  |       new Date(b.release_date).getTime() - new Date(a.release_date).getTime() | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <section className="bg-gray-900/50 border-b border-gray-800"> | ||||||
|  |       <div className="container py-6"> | ||||||
|  |         <div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> | ||||||
|  |           {/* Currently in cinemas. */} | ||||||
|  |           {sortedInCinema.length > 0 && ( | ||||||
|  |             <div> | ||||||
|  |               <h3 className="text-green-400 font-medium text-sm mb-3 flex items-center gap-2"> | ||||||
|  |                 <FaClock className="w-4 h-4" /> | ||||||
|  |                 Aktualnie w kinach ({sortedInCinema.length}) | ||||||
|  |               </h3> | ||||||
|  |               <div className="space-y-2"> | ||||||
|  |                 {sortedInCinema.map((movie) => ( | ||||||
|  |                   <MovieRow key={movie.id} movie={movie} isUpcoming={false} /> | ||||||
|  |                 ))} | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           )} | ||||||
|  |           {/* Upcoming premieres. */} | ||||||
|  |           {sortedUpcoming.length > 0 && ( | ||||||
|  |             <div> | ||||||
|  |               <h3 className="text-blue-400 font-medium text-sm mb-3 flex items-center gap-2"> | ||||||
|  |                 <FaCalendar className="w-4 h-4" /> | ||||||
|  |                 Nadchodzące premiery ({sortedUpcoming.length}) | ||||||
|  |               </h3> | ||||||
|  |               <div className="space-y-2"> | ||||||
|  |                 {sortedUpcoming.map((movie) => ( | ||||||
|  |                   <MovieRow key={movie.id} movie={movie} isUpcoming /> | ||||||
|  |                 ))} | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           )} | ||||||
|  |         </div> | ||||||
|  | 
 | ||||||
|  |         {sortedUpcoming.length === 0 && sortedInCinema.length === 0 && ( | ||||||
|  |           <p className="text-gray-400 text-sm text-center py-4"> | ||||||
|  |             Wszystkie śledzone filmy zostały już obejrzane | ||||||
|  |           </p> | ||||||
|  |         )} | ||||||
|  |       </div> | ||||||
|  |     </section> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
		Loading…
	
		Reference in New Issue