Refactor MovieCard component to introduce a new "minimal" layout option: update layout prop to support "minimal" design, modify default layout to "minimal", and enhance rendering logic for improved user experience across movie sections.
This commit is contained in:
parent
f88b7ede7d
commit
3865de1c56
|
|
@ -45,7 +45,7 @@ export default async function Home() {
|
||||||
<h2 className="text-3xl font-bold text-white mb-8">Teraz w kinach</h2>
|
<h2 className="text-3xl font-bold text-white mb-8">Teraz w kinach</h2>
|
||||||
<Carousel>
|
<Carousel>
|
||||||
{nowPlayingMovies.map((movie) => (
|
{nowPlayingMovies.map((movie) => (
|
||||||
<MovieCard key={movie.id} {...movie} layout="zeus" simpleToggle />
|
<MovieCard key={movie.id} {...movie} simpleToggle />
|
||||||
))}
|
))}
|
||||||
</Carousel>
|
</Carousel>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -56,7 +56,7 @@ export default async function Home() {
|
||||||
</h2>
|
</h2>
|
||||||
<Carousel>
|
<Carousel>
|
||||||
{upcomingMovies.map((movie) => (
|
{upcomingMovies.map((movie) => (
|
||||||
<MovieCard key={movie.id} {...movie} layout="zeus" simpleToggle />
|
<MovieCard key={movie.id} {...movie} simpleToggle />
|
||||||
))}
|
))}
|
||||||
</Carousel>
|
</Carousel>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -67,7 +67,7 @@ export default async function Home() {
|
||||||
</h2>
|
</h2>
|
||||||
<Carousel>
|
<Carousel>
|
||||||
{popularMovies.map((movie) => (
|
{popularMovies.map((movie) => (
|
||||||
<MovieCard key={movie.id} {...movie} layout="zeus" simpleToggle />
|
<MovieCard key={movie.id} {...movie} simpleToggle />
|
||||||
))}
|
))}
|
||||||
</Carousel>
|
</Carousel>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -76,7 +76,7 @@ export default async function Home() {
|
||||||
<h2 className="text-3xl font-bold text-white mb-8">Trendy dnia</h2>
|
<h2 className="text-3xl font-bold text-white mb-8">Trendy dnia</h2>
|
||||||
<Carousel>
|
<Carousel>
|
||||||
{trendingMovies.map((movie) => (
|
{trendingMovies.map((movie) => (
|
||||||
<MovieCard key={movie.id} {...movie} layout="zeus" simpleToggle />
|
<MovieCard key={movie.id} {...movie} simpleToggle />
|
||||||
))}
|
))}
|
||||||
</Carousel>
|
</Carousel>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { FaFire } from "react-icons/fa";
|
||||||
import { RiCalendarCheckLine, RiCalendarScheduleLine } from "react-icons/ri";
|
import { RiCalendarCheckLine, RiCalendarScheduleLine } from "react-icons/ri";
|
||||||
|
|
||||||
type Props = Movie & {
|
type Props = Movie & {
|
||||||
layout?: "default" | "zeus";
|
layout?: "default" | "zeus" | "minimal";
|
||||||
showDayCounter?: boolean;
|
showDayCounter?: boolean;
|
||||||
simpleToggle?: boolean;
|
simpleToggle?: boolean;
|
||||||
};
|
};
|
||||||
|
|
@ -20,7 +20,7 @@ const buttonClass =
|
||||||
"p-4 text-sm transition-colors cursor-pointer text-center group/toggle";
|
"p-4 text-sm transition-colors cursor-pointer text-center group/toggle";
|
||||||
|
|
||||||
export const MovieCard: FC<Props> = ({
|
export const MovieCard: FC<Props> = ({
|
||||||
layout = "default",
|
layout = "minimal",
|
||||||
showDayCounter = true,
|
showDayCounter = true,
|
||||||
simpleToggle = false,
|
simpleToggle = false,
|
||||||
...movie
|
...movie
|
||||||
|
|
@ -75,6 +75,115 @@ export const MovieCard: FC<Props> = ({
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Minimal modern theme.
|
||||||
|
if (layout === "minimal") {
|
||||||
|
return (
|
||||||
|
<article className="group relative w-full h-[420px] bg-white/5 border border-white/10 rounded-xl overflow-hidden backdrop-blur-sm transition-all duration-300 hover:bg-white/10 hover:border-white/20 hover:shadow-lg hover:shadow-black/20">
|
||||||
|
<figure className="relative h-[280px] overflow-hidden">
|
||||||
|
<img
|
||||||
|
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
|
||||||
|
src={`http://image.tmdb.org/t/p/w342${poster_path}`}
|
||||||
|
alt={title}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Rating badge */}
|
||||||
|
{!!vote_average && (
|
||||||
|
<div className="absolute top-3 right-3 bg-black/60 backdrop-blur-sm px-2 pr-3 pb-1 rounded-full">
|
||||||
|
<span className="text-xs font-medium text-yellow-400">
|
||||||
|
★ {vote_average.toFixed(1)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Action overlay */}
|
||||||
|
<div className="absolute inset-0 bg-black/70 backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-all duration-300 flex items-center justify-center">
|
||||||
|
{!alreadyInStore ? (
|
||||||
|
<button
|
||||||
|
onClick={handleAdd}
|
||||||
|
className="bg-white text-black px-4 py-2 rounded-lg font-medium text-sm transition-all duration-200 hover:bg-gray-100 hover:scale-105"
|
||||||
|
>
|
||||||
|
Add to List
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{isReleased && (
|
||||||
|
<button
|
||||||
|
onClick={handleSeen}
|
||||||
|
className={`p-2 rounded-lg transition-all duration-200 hover:scale-110 ${
|
||||||
|
seen
|
||||||
|
? "bg-green-500 text-white"
|
||||||
|
: "bg-white/20 text-white hover:bg-white/30"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{seen ? <RxEyeOpen size={20} /> : <RxEyeClosed size={20} />}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
onClick={handleFavorite}
|
||||||
|
className={`p-2 rounded-lg transition-all duration-200 hover:scale-110 ${
|
||||||
|
favorite
|
||||||
|
? "bg-red-500 text-white"
|
||||||
|
: "bg-white/20 text-white hover:bg-white/30"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{favorite ? (
|
||||||
|
<MdFavorite size={20} />
|
||||||
|
) : (
|
||||||
|
<MdFavoriteBorder size={20} />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleRemove}
|
||||||
|
className="p-2 rounded-lg bg-white/20 text-white hover:bg-red-500 transition-all duration-200 hover:scale-110"
|
||||||
|
>
|
||||||
|
<IoMdRemoveCircleOutline size={20} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
{/* Content section */}
|
||||||
|
<div className="p-4 flex flex-col justify-between">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-lg leading-tight line-clamp-2 mb-2 transition-colors duration-200 group-hover:text-white/90">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
<div className="text-sm text-gray-400 leading-relaxed">
|
||||||
|
<ReadMore text={overview} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between mt-3 pt-3 border-t border-white/10">
|
||||||
|
<span className="text-xs text-gray-500 font-medium">
|
||||||
|
{releaseDate.toLocaleDateString("pl-PL", {
|
||||||
|
day: "numeric",
|
||||||
|
month: "long",
|
||||||
|
year: "numeric",
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
{alreadyInStore && (
|
||||||
|
<div className="flex gap-1">
|
||||||
|
{seen && (
|
||||||
|
<div
|
||||||
|
className="w-2 h-2 bg-green-400 rounded-full"
|
||||||
|
title="Watched"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{favorite && (
|
||||||
|
<div
|
||||||
|
className="w-2 h-2 bg-red-400 rounded-full"
|
||||||
|
title="Favorite"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (layout === "zeus") {
|
if (layout === "zeus") {
|
||||||
return (
|
return (
|
||||||
<article className="flex flex-col w-full shadow-lg rounded-t-lg overflow-hidden bg-black/50 shadow-white/5">
|
<article className="flex flex-col w-full shadow-lg rounded-t-lg overflow-hidden bg-black/50 shadow-white/5">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue