107 lines
3.5 KiB
JavaScript
107 lines
3.5 KiB
JavaScript
import React, { useEffect, useState } from 'react';
|
||
import { useParams } from 'react-router-dom';
|
||
import { getMediaById } from '../services/supabase';
|
||
import { useAuth } from '../contexts/AuthContext';
|
||
|
||
const MediaPage = () => {
|
||
const { id } = useParams();
|
||
const [media, setMedia] = useState(null);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState(null);
|
||
const { currentUser } = useAuth();
|
||
|
||
useEffect(() => {
|
||
const loadMedia = async () => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const data = await getMediaById(id);
|
||
setMedia(data);
|
||
} catch (err) {
|
||
console.error('Error loading media:', err);
|
||
setError('Не удалось загрузить информацию о медиа');
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
if (id) {
|
||
loadMedia();
|
||
}
|
||
}, [id]);
|
||
|
||
if (loading) {
|
||
return <div className="text-center">Загрузка...</div>;
|
||
}
|
||
|
||
if (error) {
|
||
return <div className="text-red-500">{error}</div>;
|
||
}
|
||
|
||
if (!media) {
|
||
return <div className="text-center">Медиа не найдено</div>;
|
||
}
|
||
|
||
return (
|
||
<div className="container mx-auto px-4 py-8">
|
||
<div className="bg-white rounded-lg shadow-lg overflow-hidden">
|
||
{/* Заголовок и основная информация */}
|
||
<div className="p-6">
|
||
<h1 className="text-3xl font-bold mb-4">{media.title}</h1>
|
||
<div className="flex flex-wrap gap-4 text-gray-600 mb-4">
|
||
<span>Тип: {media.type}</span>
|
||
{media.release_date && (
|
||
<span>Дата выхода: {new Date(media.release_date).toLocaleDateString()}</span>
|
||
)}
|
||
{media.rating && (
|
||
<span>Рейтинг: {media.rating.toFixed(1)}</span>
|
||
)}
|
||
</div>
|
||
{media.description && (
|
||
<p className="text-gray-700 mb-6">{media.description}</p>
|
||
)}
|
||
</div>
|
||
|
||
{/* Постер и дополнительная информация */}
|
||
{media.poster_url && (
|
||
<div className="p-6 border-t">
|
||
<img
|
||
src={media.poster_url}
|
||
alt={media.title}
|
||
className="max-w-sm mx-auto rounded-lg shadow-md"
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{/* Рецензии */}
|
||
<div className="p-6 border-t">
|
||
<h2 className="text-2xl font-bold mb-4">Рецензии</h2>
|
||
{media.reviews && media.reviews.length > 0 ? (
|
||
<div className="space-y-4">
|
||
{media.reviews.map((review) => (
|
||
<div key={review.id} className="bg-gray-50 p-4 rounded-lg">
|
||
<div className="flex items-center mb-2">
|
||
<span className="font-semibold">{review.user.username}</span>
|
||
{review.user.is_critic && (
|
||
<span className="ml-2 px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded-full">
|
||
Критик
|
||
</span>
|
||
)}
|
||
</div>
|
||
<p className="text-gray-700">{review.content}</p>
|
||
<div className="mt-2 text-sm text-gray-500">
|
||
{new Date(review.created_at).toLocaleDateString()}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
) : (
|
||
<p className="text-gray-500">Пока нет рецензий</p>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default MediaPage; |