Files
neomovies/src/app/movie/[id]/MovieContent.tsx
Foxix ebf23e4246 Update 103 files
- /public/file.svg
- /public/globe.svg
- /public/next.svg
- /public/vercel.svg
- /public/window.svg
- /public/google.svg
- /public/logo.png
- /src/eslint.config.mjs
- /src/api.ts
- /src/middleware.ts
- /src/app/favicon.ico
- /src/app/globals.css
- /src/app/layout.tsx
- /src/app/page.tsx
- /src/app/providers.tsx
- /src/app/not-found.tsx
- /src/app/error.tsx
- /src/app/metadata.ts
- /src/app/styles.tsx
- /src/app/api/auth/[...nextauth]/route.ts
- /src/app/api/auth/register/route.ts
- /src/app/api/auth/verify/route.ts
- /src/app/api/auth/check-verification/route.ts
- /src/app/api/auth/resend-code/route.ts
- /src/app/api/movies/search/route.ts
- /src/app/api/movies/sync/route.ts
- /src/app/api/admin/send-verification/route.ts
- /src/app/api/admin/verify-code/route.ts
- /src/app/api/admin/movies/route.ts
- /src/app/api/admin/movies/toggle-visibility/route.ts
- /src/app/api/admin/create/route.ts
- /src/app/api/admin/users/toggle-admin/route.ts
- /src/app/api/admin/toggle-admin/route.ts
- /src/app/login/page.tsx
- /src/app/login/LoginClient.tsx
- /src/app/verify/page.tsx
- /src/app/verify/VerificationClient.tsx
- /src/app/profile/page.tsx
- /src/app/movie/[id]/page.tsx
- /src/app/movie/[id]/MoviePage.tsx
- /src/app/movie/[id]/MovieContent.tsx
- /src/app/settings/page.tsx
- /src/app/tv/[id]/page.tsx
- /src/app/tv/[id]/TVShowPage.tsx
- /src/app/tv/[id]/TVShowContent.tsx
- /src/app/admin/login/page.tsx
- /src/app/admin/login/AdminLoginClient.tsx
- /src/lib/db.ts
- /src/lib/jwt.ts
- /src/lib/registry.tsx
- /src/lib/api.ts
- /src/lib/mongodb.ts
- /src/lib/mailer.ts
- /src/lib/auth.ts
- /src/lib/utils.ts
- /src/lib/email.ts
- /src/lib/movieSync.ts
- /src/models/User.ts
- /src/models/index.ts
- /src/models/Movie.ts
- /src/types/auth.ts
- /src/types/movie.ts
- /src/components/MovieCard.tsx
- /src/components/Notification.tsx
- /src/components/Pagination.tsx
- /src/components/GoogleIcon.tsx
- /src/components/StyleProvider.tsx
- /src/components/Providers.tsx
- /src/components/VerificationCodeInput.tsx
- /src/components/GlassCard.tsx
- /src/components/AppLayout.tsx
- /src/components/SearchModal.tsx
- /src/components/DarkReaderFix.tsx
- /src/components/ClientLayout.tsx
- /src/components/MenuItem.tsx
- /src/components/MoviePlayer.tsx
- /src/components/PageLayout.tsx
- /src/components/SettingsContent.tsx
- /src/components/Navbar.tsx
- /src/components/LayoutContent.tsx
- /src/components/SearchResults.tsx
- /src/components/Icons/Icons.tsx
- /src/components/Icons/HeartIcon.tsx
- /src/components/Icons/PlayIcon.tsx
- /src/components/admin/MovieSearch.tsx
- /src/hooks/useUser.ts
- /src/hooks/useMovies.ts
- /src/hooks/useSettings.ts
- /src/hooks/useSearch.ts
- /src/styles/GlobalStyles.ts
- /src/styles/GlobalStyles.tsx
- /src/providers/AuthProvider.tsx
- /src/data/movies.ts
- /types/next-auth.d.ts
- /middleware.ts
- /next.config.js
- /next-env.d.ts
- /package.json
- /postcss.config.mjs
- /README.md
- /tailwind.config.ts
- /tsconfig.json
- /package-lock.json
2024-12-23 18:42:18 +00:00

208 lines
4.8 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 { useEffect, useState, Suspense } from 'react';
import styled from 'styled-components';
import { moviesAPI } from '@/lib/api';
import type { MovieDetails } from '@/lib/api';
import { useSettings } from '@/hooks/useSettings';
import MoviePlayer from '@/components/MoviePlayer';
declare global {
interface Window {
kbox: any;
}
}
const Container = styled.div`
width: 100%;
min-height: 100vh;
padding: 0 24px;
`;
const Content = styled.div`
width: 100%;
max-width: 1200px;
margin: 0 auto;
`;
const MovieInfo = styled.div`
display: flex;
gap: 30px;
margin-bottom: 1rem;
@media (max-width: 768px) {
flex-direction: column;
}
`;
const PosterContainer = styled.div`
flex-shrink: 0;
`;
const Poster = styled.img`
width: 300px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
@media (max-width: 768px) {
width: 100%;
max-width: 300px;
margin: 0 auto;
}
`;
const Details = styled.div`
flex: 1;
`;
const Title = styled.h1`
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 1rem;
color: white;
`;
const Info = styled.div`
display: flex;
gap: 1rem;
flex-wrap: wrap;
margin-bottom: 1rem;
`;
const InfoItem = styled.span`
color: rgba(255, 255, 255, 0.7);
font-size: 0.9rem;
`;
const GenreList = styled.div`
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-bottom: 1rem;
`;
const Genre = styled.span`
background: rgba(255, 255, 255, 0.1);
padding: 0.25rem 0.75rem;
border-radius: 1rem;
font-size: 0.9rem;
color: rgba(255, 255, 255, 0.8);
`;
const Tagline = styled.div`
font-style: italic;
color: rgba(255, 255, 255, 0.6);
margin-bottom: 1rem;
`;
const Overview = styled.p`
color: rgba(255, 255, 255, 0.8);
line-height: 1.6;
`;
const PlayerSection = styled.div`
margin-top: 2rem;
`;
const LoadingContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
min-height: 400px;
color: rgba(255, 255, 255, 0.7);
`;
const ErrorContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
min-height: 400px;
color: #ff4444;
`;
import { useParams } from 'next/navigation';
export default function MovieContent() {
const { id: movieId } = useParams();
const { settings } = useSettings();
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [movie, setMovie] = useState<MovieDetails | null>(null);
const [imdbId, setImdbId] = useState<string | null>(null);
useEffect(() => {
const fetchMovie = async () => {
if (!movieId) return;
try {
setLoading(true);
const response = await moviesAPI.getMovie(movieId);
setMovie(response.data);
const newImdbId = await moviesAPI.getImdbId(movieId);
if (!newImdbId) {
setError('IMDb ID не найден');
return;
}
setImdbId(newImdbId);
setError(null);
} catch (err) {
console.error('Error fetching movie:', err);
setError('Ошибка при загрузке фильма');
} finally {
setLoading(false);
}
};
fetchMovie();
}, [movieId]);
if (loading) return <LoadingContainer>Загрузка...</LoadingContainer>;
if (error) return <ErrorContainer>{error}</ErrorContainer>;
if (!movie || !imdbId) return null;
return (
<Container>
<Content>
<MovieInfo>
<PosterContainer>
<Poster
src={movie.poster_path ? `https://image.tmdb.org/t/p/w500${movie.poster_path}` : '/placeholder.jpg'}
alt={movie.title}
/>
</PosterContainer>
<Details>
<Title>{movie.title}</Title>
<Info>
<InfoItem>Рейтинг: {movie.vote_average.toFixed(1)}</InfoItem>
<InfoItem>Длительность: {movie.runtime} мин.</InfoItem>
<InfoItem>Дата выхода: {new Date(movie.release_date).toLocaleDateString('ru-RU')}</InfoItem>
</Info>
<GenreList>
{movie.genres.map(genre => (
<Genre key={genre.id}>{genre.name}</Genre>
))}
</GenreList>
{movie.tagline && <Tagline>{movie.tagline}</Tagline>}
<Overview>{movie.overview}</Overview>
</Details>
</MovieInfo>
<PlayerSection>
<Suspense fallback={<LoadingContainer>Загрузка плеера...</LoadingContainer>}>
<MoviePlayer
id={movie.id.toString()}
title={movie.title}
poster={movie.backdrop_path ? `https://image.tmdb.org/t/p/w1280${movie.backdrop_path}` : undefined}
imdbId={imdbId}
/>
</Suspense>
</PlayerSection>
</Content>
</Container>
);
}