CampFireCritics/src/mobile/pages/MobileCatalog.jsx

185 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { pb } from '../../services/pocketbaseService';
import { getFileUrl } from '../../services/pocketbaseService';
import { FaStar, FaFilter } from 'react-icons/fa';
import SearchBar from '../../components/ui/SearchBar';
const MobileCatalog = () => {
const [media, setMedia] = useState([]);
const [loading, setLoading] = useState(true);
const [filters, setFilters] = useState({
type: '',
genre: '',
year: '',
sort: '-created'
});
const [showFilters, setShowFilters] = useState(false);
useEffect(() => {
fetchMedia();
}, [filters]);
const fetchMedia = async () => {
try {
setLoading(true);
const filter = [];
if (filters.type) {
filter.push(`type = "${filters.type}"`);
}
if (filters.genre) {
filter.push(`genres ?~ "${filters.genre}"`);
}
if (filters.year) {
filter.push(`year = ${filters.year}`);
}
const records = await pb.collection('media').getList(1, 50, {
sort: filters.sort,
filter: filter.join(' && ')
});
setMedia(records.items);
} catch (error) {
console.error('Error fetching media:', error);
} finally {
setLoading(false);
}
};
const handleFilterChange = (key, value) => {
setFilters(prev => ({
...prev,
[key]: value
}));
};
if (loading) {
return (
<div className="flex items-center justify-center min-h-screen">
<div className="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-campfire-amber"></div>
</div>
);
}
return (
<div className="min-h-screen bg-campfire-dark">
<div className="px-4 pt-4">
<SearchBar mobileMode={true} />
</div>
{/* Фильтры */}
<div className="px-4 py-4">
<div className="mb-6">
<button
onClick={() => setShowFilters(!showFilters)}
className="w-full flex items-center justify-center space-x-2 bg-campfire-dark/50 border border-campfire-ash/30 rounded-lg p-3 text-campfire-light"
>
<FaFilter />
<span>Фильтры</span>
</button>
{showFilters && (
<div className="mt-4 space-y-4 bg-campfire-dark/50 border border-campfire-ash/30 rounded-lg p-4">
<div>
<label className="block text-campfire-light mb-2">Тип</label>
<select
value={filters.type}
onChange={(e) => handleFilterChange('type', e.target.value)}
className="w-full bg-campfire-dark border border-campfire-ash/30 rounded-lg p-2 text-campfire-light"
>
<option value="">Все</option>
<option value="movie">Фильмы</option>
<option value="series">Сериалы</option>
<option value="game">Игры</option>
</select>
</div>
<div>
<label className="block text-campfire-light mb-2">Жанр</label>
<select
value={filters.genre}
onChange={(e) => handleFilterChange('genre', e.target.value)}
className="w-full bg-campfire-dark border border-campfire-ash/30 rounded-lg p-2 text-campfire-light"
>
<option value="">Все</option>
<option value="action">Боевик</option>
<option value="comedy">Комедия</option>
<option value="drama">Драма</option>
<option value="horror">Ужасы</option>
<option value="sci-fi">Фантастика</option>
</select>
</div>
<div>
<label className="block text-campfire-light mb-2">Год</label>
<select
value={filters.year}
onChange={(e) => handleFilterChange('year', e.target.value)}
className="w-full bg-campfire-dark border border-campfire-ash/30 rounded-lg p-2 text-campfire-light"
>
<option value="">Все</option>
{Array.from({ length: 24 }, (_, i) => 2024 - i).map(year => (
<option key={year} value={year}>{year}</option>
))}
</select>
</div>
<div>
<label className="block text-campfire-light mb-2">Сортировка</label>
<select
value={filters.sort}
onChange={(e) => handleFilterChange('sort', e.target.value)}
className="w-full bg-campfire-dark border border-campfire-ash/30 rounded-lg p-2 text-campfire-light"
>
<option value="-created">Сначала новые</option>
<option value="created">Сначала старые</option>
<option value="-average_rating">По рейтингу</option>
<option value="title">По названию</option>
</select>
</div>
</div>
)}
</div>
{/* Список медиа */}
<div className="space-y-4">
{media.map((item) => (
<Link
key={item.id}
to={`/media/${item.path}`}
className="block bg-campfire-dark/50 border border-campfire-ash/30 rounded-lg p-4"
>
<div className="flex items-center space-x-4">
<img
src={getFileUrl(item, 'poster')}
alt={item.title}
className="w-16 h-24 rounded-lg object-cover"
/>
<div className="flex-1">
<h3 className="text-campfire-light font-semibold mb-1">
{item.title}
</h3>
<div className="flex items-center space-x-2 text-sm">
<div className="flex items-center text-campfire-amber">
<FaStar className="mr-1" />
<span>{item.average_rating?.toFixed(1) || '0.0'}</span>
</div>
<span className="text-campfire-ash">
{item.review_count || 0} обзоров
</span>
</div>
<p className="text-campfire-ash text-sm mt-1">
{item.type === 'movie' ? 'Фильм' : item.type === 'series' ? 'Сериал' : 'Игра'} {item.year}
</p>
</div>
</div>
</Link>
))}
</div>
</div>
</div>
);
};
export default MobileCatalog;