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:
parent
af4689d726
commit
68fb45d6ef
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"semi": true,
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true,
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
import { GenreList } from "@/components/molecules/GenreList";
|
||||
import { MovieList } from "@/components/molecules/MovieList";
|
||||
import { TrackedMovies } from "@/components/molecules/TrackedMovies";
|
||||
import { GenreList } from '@/components/molecules/GenreList';
|
||||
import { MovieList } from '@/components/molecules/MovieList';
|
||||
import { RandomMovie } from '@/components/molecules/RandomMovie';
|
||||
import { TrackedMovies } from '@/components/molecules/TrackedMovies';
|
||||
|
||||
export default async function Home() {
|
||||
return (
|
||||
<>
|
||||
<TrackedMovies />
|
||||
<MovieList heading="Moja lista" />
|
||||
<RandomMovie heading="Ciężko wybrać?" />
|
||||
<GenreList heading="Odkrywaj nowe filmy według gatunku" />
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
};
|
||||
73
todo.md
73
todo.md
|
|
@ -1,36 +1,51 @@
|
|||
#
|
||||
UI/UX Improvements
|
||||
Dark/Light Mode Toggle - Obecnie tylko ciemny motyw
|
||||
Responsywny design na urządzenia mobilne - Niektóre komponenty mogą wymagać poprawy
|
||||
Loading states - Dodać skeletony zamiast spinnerów
|
||||
Infinite scroll - Zamiast paginacji dla lepszego UX
|
||||
Gesture support - Swipe na mobilnych dla akcji (dodaj/usuń film)
|
||||
|
||||
## ✅ `TODO.md` – Etapy rozwoju aplikacji
|
||||
Zarządzanie filmami
|
||||
Własne notatki do filmów - Pole w bazie danych już wspomniane w README
|
||||
Tagi/kategorie użytkownika - Własne etykiety
|
||||
Oceny użytkownika - Osobne od TMDB
|
||||
Data obejrzenia - Kiedy użytkownik obejrzał film
|
||||
Lista "Do obejrzenia" - Oddzielna od "Obejrzane"
|
||||
Planowanie seansów - Kalendarz z datami
|
||||
Eksport/import listy - JSON/CSV backup
|
||||
|
||||
```md
|
||||
# TODO – MovieBox
|
||||
Funkcje społecznościowe
|
||||
Udostępnianie list - Link do publicznej listy
|
||||
Rekomendacje na podstawie gustu - ML/AI sugestie
|
||||
Porównanie list z znajomymi - Wspólne filmy
|
||||
|
||||
## 🔧 Faza 1 – MVP (funkcjonalna wersja lokalna)
|
||||
Dodatkowe dane i integracje
|
||||
Informacje o aktorach - Rozszerzone profile (już częściowo jest)
|
||||
Gdzie obejrzeć - Streaming platforms API
|
||||
Zwiastuny - YouTube API integration
|
||||
Recenzje użytkowników - Własne mini-forum
|
||||
Galeria zdjęć z filmu - Więcej materiałów wizualnych
|
||||
|
||||
- [ ] Integracja z TMDB API (wyszukiwanie filmów)
|
||||
- [ ] Utworzenie bazy danych (SQLite + Drizzle)
|
||||
- [ ] Modele: Movie, WatchlistEntry
|
||||
- [ ] Dodanie filmu do watchlisty (z podglądem szczegółów)
|
||||
- [ ] Lista “Do obejrzenia” i “Obejrzane”
|
||||
- [ ] Możliwość dodania tagu lub notatki do filmu
|
||||
- [ ] UI (Tailwind + ShadCN) – responsywna siatka filmów
|
||||
Performance i techniczne
|
||||
PWA - Offline support, push notifications o premierach
|
||||
Lepsze caching - Redis/SWR optimizations
|
||||
Lazy loading - Obrazy i komponenty
|
||||
Search indexing - Full-text search w bazie
|
||||
API rate limiting - Lepsze zarządzanie requestami do TMDB
|
||||
|
||||
## 🌐 Faza 2 – Rozszerzenie
|
||||
Statystyki i analytics
|
||||
Dashboard statystyk - Filmy obejrzane/miesiąc, ulubione gatunki
|
||||
Streak tracking - Dni z rzędu oglądania filmów
|
||||
Cele filmowe - X filmów do obejrzenia w roku
|
||||
Porównanie z poprzednimi latami - Trendy
|
||||
|
||||
- [ ] Podgląd dat premier z TMDB
|
||||
- [ ] Filtrowanie według daty premiery
|
||||
- [ ] Sortowanie / filtrowanie po tagach/statusie
|
||||
Powiadomienia
|
||||
Email notifications - O premierach z listy
|
||||
Push notifications - PWA alerts
|
||||
Reminder system - Przypomnienia o filmach do obejrzenia
|
||||
|
||||
## 🔐 Faza 3 – Rozszerzenia prywatne
|
||||
|
||||
- [ ] Dodanie Auth.js (logowanie)
|
||||
- [ ] Migracja bazy do PostgreSQL
|
||||
- [ ] Eksport listy filmów (np. JSON)
|
||||
- [ ] Backup na GitHub (np. GitHub Actions)
|
||||
|
||||
## 💡 Pomysły na później
|
||||
|
||||
- [ ] System rekomendacji (podobne filmy)
|
||||
- [ ] Powiadomienia o premierach
|
||||
- [ ] Integracja z Letterboxd
|
||||
```
|
||||
Baza danych i backend
|
||||
Migracja na PostgreSQL - Jak wspomniano w README
|
||||
User authentication - Currently brak systemu użytkowników
|
||||
API endpoints - Własne REST API
|
||||
Backup system - Automatyczne kopie zapasowe
|
||||
|
|
|
|||
Loading…
Reference in New Issue