Files
neomovies/src/app/movie/[id]/MovieContent.tsx
2025-07-08 13:41:04 +03:00

172 lines
6.1 KiB
TypeScript
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.

'use client';
import { useState, useEffect, useRef } from 'react';
import Image from 'next/image';
import { moviesAPI } from '@/lib/neoApi';
import { getImageUrl } from '@/lib/neoApi';
import type { MovieDetails } from '@/lib/api';
import MoviePlayer from '@/components/MoviePlayer';
import FavoriteButton from '@/components/FavoriteButton';
import { formatDate } from '@/lib/utils';
import { PlayCircle, ArrowLeft } from 'lucide-react';
interface MovieContentProps {
movieId: string;
initialMovie: MovieDetails;
}
export default function MovieContent({ movieId, initialMovie }: MovieContentProps) {
const [movie] = useState<MovieDetails>(initialMovie);
const [imdbId, setImdbId] = useState<string | null>(null);
const [isPlayerFullscreen, setIsPlayerFullscreen] = useState(false);
const [isControlsVisible, setIsControlsVisible] = useState(false);
const controlsTimeoutRef = useRef<NodeJS.Timeout | null>(null);
useEffect(() => {
const fetchImdbId = async () => {
try {
const { data } = await moviesAPI.getMovie(movieId);
if (data?.imdb_id) {
setImdbId(data.imdb_id);
}
} catch (err) {
console.error('Error fetching IMDb ID:', err);
}
};
fetchImdbId();
}, [movieId]);
const showControls = () => {
if (controlsTimeoutRef.current) {
clearTimeout(controlsTimeoutRef.current);
}
setIsControlsVisible(true);
controlsTimeoutRef.current = setTimeout(() => {
setIsControlsVisible(false);
}, 3000);
};
const handleOpenPlayer = () => {
setIsPlayerFullscreen(true);
showControls();
};
const handleClosePlayer = () => {
setIsPlayerFullscreen(false);
if (controlsTimeoutRef.current) {
clearTimeout(controlsTimeoutRef.current);
}
};
return (
<>
<div className="min-h-screen bg-background text-foreground px-4 py-6 md:px-6 lg:px-8">
<div className="w-full">
<div className="grid grid-cols-1 gap-8 md:grid-cols-3">
{/* Left Column: Poster */}
<div className="md:col-span-1">
<div className="sticky top-24 max-w-sm mx-auto md:max-w-none md:mx-0">
<div className="relative aspect-[2/3] w-full overflow-hidden rounded-lg shadow-lg">
<Image
src={getImageUrl(movie.poster_path, 'w500')}
alt={`Постер фильма ${movie.title}`}
fill
className="object-cover"
unoptimized
/>
</div>
</div>
</div>
{/* Middle Column: Details */}
<div className="md:col-span-2">
<h1 className="text-3xl font-bold tracking-tight sm:text-4xl">
{movie.title}
</h1>
{movie.tagline && (
<p className="mt-1 text-lg text-muted-foreground">{movie.tagline}</p>
)}
<div className="mt-4 flex flex-wrap items-center gap-x-4 gap-y-2">
<span className="font-medium">Рейтинг: {movie.vote_average.toFixed(1)}</span>
<span className="text-muted-foreground">|</span>
<span className="text-muted-foreground">{movie.runtime} мин.</span>
<span className="text-muted-foreground">|</span>
<span className="text-muted-foreground">{formatDate(movie.release_date)}</span>
</div>
<div className="mt-4 flex flex-wrap gap-2">
{movie.genres.map((genre) => (
<span key={genre.id} className="rounded-full bg-secondary text-secondary-foreground px-3 py-1 text-xs font-medium">
{genre.name}
</span>
))}
</div>
<div className="mt-6 space-y-4 text-base text-muted-foreground">
<p>{movie.overview}</p>
</div>
<div className="mt-8 flex items-center gap-4">
{/* Mobile-only Watch Button */}
{imdbId && (
<button
onClick={handleOpenPlayer}
className="md:hidden flex items-center justify-center gap-2 rounded-md bg-red-500 px-6 py-3 text-base font-semibold text-white shadow-sm hover:bg-red-600"
>
<PlayCircle size={20} />
<span>Смотреть</span>
</button>
)}
<FavoriteButton
mediaId={movie.id.toString()}
mediaType="movie"
title={movie.title}
posterPath={movie.poster_path}
className="!bg-secondary !text-secondary-foreground hover:!bg-secondary/80"
showText={true}
/>
</div>
{/* Desktop-only Embedded Player */}
{imdbId && (
<div id="movie-player" className="mt-10 hidden md:block rounded-lg bg-secondary/50 p-4 shadow-inner">
<MoviePlayer
id={movie.id.toString()}
title={movie.title}
poster={movie.poster_path || ''}
imdbId={imdbId}
/>
</div>
)}
</div>
</div>
</div>
</div>
{/* Fullscreen Player for Mobile */}
{isPlayerFullscreen && imdbId && (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black"
onMouseMove={showControls}
onClick={showControls}
>
<MoviePlayer
id={movie.id.toString()}
title={movie.title}
poster={movie.poster_path || ''}
imdbId={imdbId}
/>
<button
onClick={handleClosePlayer}
className={`absolute top-1/2 left-4 -translate-y-1/2 z-50 rounded-full bg-black/50 p-2 text-white transition-opacity duration-300 hover:bg-black/75 ${isControlsVisible ? 'opacity-100' : 'opacity-0'}`}
aria-label="Назад"
>
<ArrowLeft size={24} />
</button>
</div>
)}
</>
);
}