Enhance MovieCard component with new "aurora" layout: introduce a visually stunning design with gradient backgrounds, improved card interactions, and additional status indicators. Update MovieList to utilize the new layout for a more engaging user experience.
This commit is contained in:
parent
3865de1c56
commit
1e7d7891d0
|
|
@ -10,7 +10,7 @@ export default async function SearchPage({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className="container">
|
<section className="container">
|
||||||
<h1 className="text-2xl">
|
<h1 className="text-2xl mt-6">
|
||||||
Wyszukiwanie: <strong>{s}</strong>
|
Wyszukiwanie: <strong>{s}</strong>
|
||||||
</h1>
|
</h1>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { FC } from "react";
|
import { FC, useState } from "react";
|
||||||
import { ReadMore } from "../ReadMore";
|
import { ReadMore } from "../ReadMore";
|
||||||
import { addMovie, deleteMovie, updateMovie } from "@/lib/db";
|
import { addMovie, deleteMovie, updateMovie } from "@/lib/db";
|
||||||
import { useGlobalStore } from "@/app/store/globalStore";
|
import { useGlobalStore } from "@/app/store/globalStore";
|
||||||
|
|
@ -7,11 +7,11 @@ import { MdFavorite, MdFavoriteBorder, MdOutlinePostAdd } from "react-icons/md";
|
||||||
import { RxEyeClosed, RxEyeOpen } from "react-icons/rx";
|
import { RxEyeClosed, RxEyeOpen } from "react-icons/rx";
|
||||||
import { IoMdRemoveCircleOutline } from "react-icons/io";
|
import { IoMdRemoveCircleOutline } from "react-icons/io";
|
||||||
import { Movie } from "@/types/global";
|
import { Movie } from "@/types/global";
|
||||||
import { FaFire } from "react-icons/fa";
|
import { FaAngleUp, FaArrowUp, FaFire, FaTrash } 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" | "minimal";
|
layout?: "default" | "zeus" | "minimal" | "aurora";
|
||||||
showDayCounter?: boolean;
|
showDayCounter?: boolean;
|
||||||
simpleToggle?: boolean;
|
simpleToggle?: boolean;
|
||||||
};
|
};
|
||||||
|
|
@ -25,6 +25,7 @@ export const MovieCard: FC<Props> = ({
|
||||||
simpleToggle = false,
|
simpleToggle = false,
|
||||||
...movie
|
...movie
|
||||||
}) => {
|
}) => {
|
||||||
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
const {
|
const {
|
||||||
movies,
|
movies,
|
||||||
addMovie: addMovieToStore,
|
addMovie: addMovieToStore,
|
||||||
|
|
@ -75,6 +76,198 @@ export const MovieCard: FC<Props> = ({
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Aurora theme - creative and visually stunning.
|
||||||
|
if (layout === "aurora") {
|
||||||
|
const scoreColor =
|
||||||
|
vote_average >= 8
|
||||||
|
? "from-emerald-400 to-teal-400"
|
||||||
|
: vote_average >= 6
|
||||||
|
? "from-yellow-400 to-orange-400"
|
||||||
|
: "from-red-400 to-pink-400";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<article
|
||||||
|
className="group relative w-full overflow-hidden rounded-2xl"
|
||||||
|
onMouseLeave={() => setIsExpanded(false)}
|
||||||
|
>
|
||||||
|
{/* Aurora background effect */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-br from-purple-900/20 via-blue-900/20 to-teal-900/20 opacity-60"></div>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-tr from-pink-500/10 via-transparent to-cyan-500/10 opacity-0 group-hover:opacity-100 transition-opacity duration-1000"></div>
|
||||||
|
|
||||||
|
{/* Main card container */}
|
||||||
|
<div className="grid relative h-full bg-gradient-to-br from-slate-800/90 to-slate-900/90 backdrop-blur-xl border border-slate-700/50 shadow-2xl shadow-purple-500/10 group-hover:shadow-purple-500/20 transition-all duration-500">
|
||||||
|
{/* Image section with sophisticated overlay */}
|
||||||
|
<figure
|
||||||
|
className="relative overflow-hidden"
|
||||||
|
style={{
|
||||||
|
aspectRatio: "342/513",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="w-full h-full object-cover transition-all duration-700 group-hover:scale-110 group-hover:brightness-110"
|
||||||
|
src={`http://image.tmdb.org/t/p/w342${poster_path}`}
|
||||||
|
alt={title}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Gradient overlays for depth */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-t from-slate-900 via-slate-900/20 to-transparent"></div>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-purple-600/20 via-transparent to-cyan-600/20 opacity-0 group-hover:opacity-100 transition-opacity duration-700"></div>
|
||||||
|
|
||||||
|
{/* Floating rating badge */}
|
||||||
|
{!!vote_average && (
|
||||||
|
<div className="absolute top-4 right-4 transform rotate-3 group-hover:rotate-0 transition-transform duration-300">
|
||||||
|
<div
|
||||||
|
className={`bg-gradient-to-r ${scoreColor} p-3 rounded-xl shadow-lg backdrop-blur-sm`}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2 text-white font-bold">
|
||||||
|
<span className="text-xl">★</span>
|
||||||
|
<span className="text-lg">{vote_average.toFixed(1)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Popularity indicator */}
|
||||||
|
<div className="absolute top-4 left-4 bg-black/60 backdrop-blur-sm px-3 py-2 rounded-xl border border-white/20">
|
||||||
|
<div className="flex items-center gap-2 text-orange-400">
|
||||||
|
<FaFire className="animate-pulse" />
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{Math.round(popularity)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* x Days left to release */}
|
||||||
|
{(!isReleased || daysSinceRelease < 35) && (
|
||||||
|
<div className="absolute bottom-4 right-4 flex justify-center">
|
||||||
|
<div className="text-white bg-black/60 backdrop-blur-sm px-3 py-2 rounded-xl border border-white/20">
|
||||||
|
<span className="text-xs font-medium">
|
||||||
|
{isReleased &&
|
||||||
|
daysSinceRelease < 35 &&
|
||||||
|
`od ${daysSinceRelease} dni`}
|
||||||
|
{!isReleased && `za ${daysSinceRelease} dni`}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Status indicators */}
|
||||||
|
{alreadyInStore && (
|
||||||
|
<div className="absolute bottom-4 left-4 flex gap-2">
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
seen ? "bg-emerald-500/90" : "bg-white/20"
|
||||||
|
} backdrop-blur-sm p-2 rounded-full animate-pulse cursor-pointer`}
|
||||||
|
onClick={handleSeen}
|
||||||
|
>
|
||||||
|
<RxEyeOpen size={16} className="text-white" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
favorite ? "bg-rose-500/90" : "bg-white/20"
|
||||||
|
} backdrop-blur-sm p-2 rounded-full animate-pulse cursor-pointer`}
|
||||||
|
onClick={handleFavorite}
|
||||||
|
>
|
||||||
|
<MdFavorite size={16} className="text-white" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`bg-white/20 backdrop-blur-sm p-2 rounded-full animate-pulse cursor-pointer`}
|
||||||
|
onClick={handleRemove}
|
||||||
|
>
|
||||||
|
<FaTrash size={16} className="text-white" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Magical action overlay */}
|
||||||
|
{!alreadyInStore && (
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-purple-900/40 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-500 flex items-center justify-center">
|
||||||
|
<button
|
||||||
|
onClick={handleAdd}
|
||||||
|
className="relative overflow-hidden bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-500 hover:to-pink-500 text-white px-8 py-4 rounded-2xl font-semibold text-lg shadow-2xl transform hover:scale-105 transition-all duration-300 group/btn"
|
||||||
|
>
|
||||||
|
<span className="relative z-10">Dodaj do listy</span>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-white/20 to-transparent opacity-0 group-hover/btn:opacity-100 transition-opacity duration-300"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
{/* Content section with glowing effects */}
|
||||||
|
<div className="relative p-6 flex flex-col justify-between">
|
||||||
|
{/* Subtle glow effect */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-t from-purple-500/5 to-transparent pointer-events-none"></div>
|
||||||
|
|
||||||
|
<div className="relative z-10">
|
||||||
|
<h3 className="font-bold text-xl leading-tight mb-3 text-transparent bg-clip-text bg-gradient-to-r from-white to-gray-300 group-hover:from-purple-200 group-hover:to-cyan-200 transition-all duration-500">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
<p
|
||||||
|
className="text-sm text-gray-400 line-clamp-2 leading-relaxed opacity-80 group-hover:opacity-100 transition-opacity duration-300 hover:text-secondary cursor-pointer"
|
||||||
|
onClick={() => setIsExpanded(!isExpanded)}
|
||||||
|
>
|
||||||
|
{overview}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom section with enhanced styling */}
|
||||||
|
<div className="relative z-10 flex items-center justify-between pt-4 mt-4 border-t border-gradient-to-r border-slate-700/50">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div
|
||||||
|
className={`flex items-center gap-1 text-sm ${
|
||||||
|
isReleased ? "text-emerald-400" : "text-amber-400"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isReleased ? (
|
||||||
|
<RiCalendarCheckLine />
|
||||||
|
) : (
|
||||||
|
<RiCalendarScheduleLine />
|
||||||
|
)}
|
||||||
|
<span className="font-medium">
|
||||||
|
{releaseDate.toLocaleDateString("pl-PL", {
|
||||||
|
day: "numeric",
|
||||||
|
month: "short",
|
||||||
|
year: "numeric",
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{alreadyInStore && (
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{seen && (
|
||||||
|
<div
|
||||||
|
className="w-3 h-3 bg-gradient-to-r from-emerald-400 to-teal-400 rounded-full shadow-lg shadow-emerald-400/50 animate-pulse"
|
||||||
|
title="Watched"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{favorite && (
|
||||||
|
<div
|
||||||
|
className="w-3 h-3 bg-gradient-to-r from-rose-400 to-pink-400 rounded-full shadow-lg shadow-rose-400/50 animate-pulse"
|
||||||
|
title="Favorite"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Decorative border glow */}
|
||||||
|
<div className="absolute inset-0 rounded-2xl border border-transparent bg-gradient-to-r from-purple-500/20 via-transparent to-cyan-500/20 opacity-0 group-hover:opacity-100 transition-opacity duration-700 pointer-events-none"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isExpanded && (
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 p-4 bg-black bg-gradient-to-t from-purple-500/30 to-secondary/30 cursor-pointer"
|
||||||
|
onClick={() => setIsExpanded(false)}
|
||||||
|
>
|
||||||
|
<p>{overview}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Minimal modern theme.
|
// Minimal modern theme.
|
||||||
if (layout === "minimal") {
|
if (layout === "minimal") {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ export const MovieList: FC<Props> = ({
|
||||||
ref={parent}
|
ref={parent}
|
||||||
>
|
>
|
||||||
{sortedMovies.map((movie) => (
|
{sortedMovies.map((movie) => (
|
||||||
<MovieCard key={movie.id} layout="zeus" {...movie} />
|
<MovieCard key={movie.id} layout="aurora" {...movie} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue