feat: add RandomMovie component for enhanced user experience; implement movie filtering and random selection functionality, and update page layout to include new component
This commit is contained in:
137
src/components/molecules/RandomMovie/index.tsx
Normal file
137
src/components/molecules/RandomMovie/index.tsx
Normal file
@@ -0,0 +1,137 @@
|
||||
'use client';
|
||||
import { FC, useMemo, useState } from 'react';
|
||||
import { useGlobalStore } from '@/app/store/globalStore';
|
||||
import { Button } from '@/components/atoms/Button';
|
||||
import { FaDice } from 'react-icons/fa';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
import { Movie } from '@/types/global';
|
||||
|
||||
type StoreFilter = 'all' | 'not_seen' | 'released' | 'favorites' | 'to_watch';
|
||||
|
||||
type Props = {
|
||||
heading?: string;
|
||||
storeFilter?: StoreFilter;
|
||||
colors?: keyof typeof colorsMap;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const RandomMovie: FC<Props> = ({
|
||||
heading = 'Losowy film',
|
||||
storeFilter = 'not_seen',
|
||||
colors = 'purple',
|
||||
className = '',
|
||||
}) => {
|
||||
const { movies } = useGlobalStore();
|
||||
const [selectedMovie, setSelectedMovie] = useState<Movie | null>(null);
|
||||
|
||||
// Filter movies based on the selected store filter.
|
||||
const filteredMovies = useMemo(() => {
|
||||
const today = new Date();
|
||||
|
||||
return movies.filter(movie => {
|
||||
switch (storeFilter) {
|
||||
case 'not_seen':
|
||||
return !movie.seen;
|
||||
case 'released':
|
||||
return new Date(movie.release_date) < today;
|
||||
case 'favorites':
|
||||
return movie.favorite;
|
||||
case 'to_watch':
|
||||
return !movie.seen && new Date(movie.release_date) < today;
|
||||
case 'all':
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}, [movies, storeFilter]);
|
||||
|
||||
const handleRandomize = () => {
|
||||
if (filteredMovies.length === 0) return;
|
||||
|
||||
const randomIndex = Math.floor(Math.random() * filteredMovies.length);
|
||||
const randomMovie = filteredMovies[randomIndex];
|
||||
|
||||
setSelectedMovie(randomMovie);
|
||||
};
|
||||
|
||||
if (filteredMovies.length === 0) {
|
||||
return (
|
||||
<section className={`blocks ${className}`}>
|
||||
<div className="container">
|
||||
{heading && (
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className={`p-2 rounded-lg ${colorsMap[colors]}`}>
|
||||
<FaDice className="text-white" />
|
||||
</div>
|
||||
<h2
|
||||
className={`text-3xl font-bold ${colorsMap[colors]} bg-clip-text text-transparent`}
|
||||
>
|
||||
{heading}
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
<div className="text-center py-12">
|
||||
<p className="text-text/60 text-lg">Brak filmów w kategorii</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<section className={`blocks ${className}`}>
|
||||
<div className="container">
|
||||
{heading && (
|
||||
<div className="flex justify-center mb-6">
|
||||
<h2
|
||||
className={`text-3xl font-bold ${colorsMap[colors]} bg-clip-text text-transparent`}
|
||||
>
|
||||
{heading}
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="text-center mb-4">
|
||||
<p className="text-text/70 text-sm">
|
||||
Dostępnych {filteredMovies.length} filmów
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
size="small"
|
||||
theme="secondary"
|
||||
onClick={handleRandomize}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<FaDice />
|
||||
Losuj film
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{selectedMovie && (
|
||||
<div className="text-center mt-4">
|
||||
<h3 className="text-2xl font-bold">
|
||||
<Link href={`/film/${selectedMovie.id}`}>
|
||||
{selectedMovie.title}
|
||||
</Link>
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
const colorsMap = {
|
||||
white: 'bg-gradient-to-r from-white to-gray-300',
|
||||
yellow: 'bg-gradient-to-r from-yellow-400 to-orange-400',
|
||||
blue: 'bg-gradient-to-r from-blue-400 to-purple-400',
|
||||
green: 'bg-gradient-to-r from-green-400 to-teal-400',
|
||||
red: 'bg-gradient-to-r from-red-400 to-pink-400',
|
||||
purple: 'bg-gradient-to-r from-purple-400 to-pink-400',
|
||||
orange: 'bg-gradient-to-r from-orange-400 to-yellow-400',
|
||||
pink: 'bg-gradient-to-r from-pink-400 to-purple-400',
|
||||
teal: 'bg-gradient-to-r from-teal-400 to-green-400',
|
||||
gray: 'bg-gradient-to-r from-gray-400 to-gray-400',
|
||||
};
|
||||
Reference in New Issue
Block a user