mirror of
https://gitlab.com/foxixus/neomovies.git
synced 2025-10-28 01:48:50 +05:00
Измения в АПИ
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { api } from '@/lib/api';
|
||||
import { neoApi } from '@/lib/neoApi';
|
||||
import { AxiosError } from 'axios';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import styled from 'styled-components';
|
||||
@@ -92,12 +92,12 @@ export default function AdminLoginClient() {
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const response = await api.post('/auth/login', {
|
||||
const response = await neoApi.post('/api/v1/auth/login', {
|
||||
email,
|
||||
password,
|
||||
});
|
||||
|
||||
const { token, user } = response.data;
|
||||
const { token, user } = response.data.data || response.data;
|
||||
|
||||
if (user?.role !== 'admin') {
|
||||
setError('У вас нет прав администратора.');
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { headers } from 'next/headers';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const headersList = headers();
|
||||
const response = await fetch(
|
||||
`https://neomovies-api.vercel.app/movies/${params.id}/external-ids`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Создаем новый Response с нужными заголовками
|
||||
return new NextResponse(JSON.stringify(data), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching external IDs:', error);
|
||||
return new NextResponse(
|
||||
JSON.stringify({ error: 'Failed to fetch external IDs' }),
|
||||
{
|
||||
status: 500,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import axios from 'axios';
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: 'https://api.themoviedb.org/3',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_TMDB_ACCESS_TOKEN}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
const id = params.id;
|
||||
|
||||
try {
|
||||
const response = await api.get(`/movie/${id}`, {
|
||||
params: {
|
||||
language: 'ru-RU',
|
||||
append_to_response: 'credits,videos,similar'
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(response.data);
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching movie details:', error);
|
||||
return NextResponse.json(
|
||||
{ error: error.message || 'Failed to fetch movie details' },
|
||||
{ status: error.response?.status || 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import axios from 'axios';
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: 'https://api.themoviedb.org/3',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_TMDB_ACCESS_TOKEN}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const page = searchParams.get('page') || '1';
|
||||
|
||||
try {
|
||||
const response = await api.get('/discover/movie', {
|
||||
params: {
|
||||
page,
|
||||
language: 'ru-RU',
|
||||
'vote_count.gte': 100,
|
||||
'vote_average.gte': 1,
|
||||
sort_by: 'popularity.desc',
|
||||
include_adult: false,
|
||||
'primary_release_date.lte': new Date().toISOString().split('T')[0]
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(response.data);
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching popular movies:', error);
|
||||
return NextResponse.json(
|
||||
{ error: error.message || 'Failed to fetch movies' },
|
||||
{ status: error.response?.status || 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { searchAPI } from '@/lib/neoApi';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const query = searchParams.get('query');
|
||||
const page = searchParams.get('page') || '1';
|
||||
|
||||
if (!query) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Query parameter is required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// Используем обновленный multiSearch, который теперь запрашивает и фильмы, и сериалы параллельно
|
||||
const response = await searchAPI.multiSearch(query, parseInt(page));
|
||||
|
||||
return NextResponse.json(response.data);
|
||||
} catch (error: any) {
|
||||
console.error('Error searching:', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Failed to search',
|
||||
details: error.message || 'Unknown error'
|
||||
},
|
||||
{ status: error.response?.status || 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { syncMovies } from '@/lib/movieSync';
|
||||
|
||||
export async function POST() {
|
||||
try {
|
||||
const movies = await syncMovies();
|
||||
return NextResponse.json({ success: true, movies });
|
||||
} catch (error) {
|
||||
console.error('Error syncing movies:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to sync movies' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const page = searchParams.get('page') || '1';
|
||||
|
||||
const response = await fetch(
|
||||
`https://api.themoviedb.org/3/movie/top_rated?page=${page}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.TMDB_ACCESS_TOKEN}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const page = searchParams.get('page') || '1';
|
||||
|
||||
const response = await fetch(
|
||||
`https://api.themoviedb.org/3/movie/upcoming?page=${page}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.TMDB_ACCESS_TOKEN}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
return NextResponse.json(data);
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useState, useEffect, useMemo } from 'react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { categoriesAPI, Movie, TVShow } from '@/lib/api';
|
||||
import { categoriesAPI, Movie } from '@/lib/neoApi';
|
||||
import MovieCard from '@/components/MovieCard';
|
||||
import { ArrowLeft, Loader2 } from 'lucide-react';
|
||||
|
||||
@@ -60,10 +60,10 @@ function CategoryPage() {
|
||||
response = await categoriesAPI.getTVShowsByCategory(categoryId, page);
|
||||
const hasTvShows = response.data.results.length > 0;
|
||||
if (page === 1) setTvShowsAvailable(hasTvShows);
|
||||
const transformedShows = response.data.results.map((show: TVShow) => ({
|
||||
const transformedShows = response.data.results.map((show: any) => ({
|
||||
...show,
|
||||
title: show.name,
|
||||
release_date: show.first_air_date,
|
||||
title: show.name || show.title,
|
||||
release_date: show.first_air_date || show.release_date,
|
||||
}));
|
||||
setItems(transformedShows);
|
||||
setTotalPages(response.data.total_pages);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { categoriesAPI } from '@/lib/api';
|
||||
import { Category } from '@/lib/api';
|
||||
import { categoriesAPI, Category } from '@/lib/neoApi';
|
||||
import CategoryCard from '@/components/CategoryCard';
|
||||
|
||||
interface CategoryWithBackground extends Category {
|
||||
@@ -14,14 +13,12 @@ function CategoriesPage() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// Загрузка категорий и фоновых изображений для них
|
||||
useEffect(() => {
|
||||
async function fetchCategoriesAndBackgrounds() {
|
||||
setError(null);
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
// Получаем список категорий
|
||||
const categoriesResponse = await categoriesAPI.getCategories();
|
||||
|
||||
if (!categoriesResponse.data.categories || categoriesResponse.data.categories.length === 0) {
|
||||
@@ -30,14 +27,11 @@ function CategoriesPage() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Добавляем фоновые изображения для каждой категории
|
||||
const categoriesWithBackgrounds: CategoryWithBackground[] = await Promise.all(
|
||||
categoriesResponse.data.categories.map(async (category: Category) => {
|
||||
try {
|
||||
// Сначала пробуем получить фильм для фона
|
||||
const moviesResponse = await categoriesAPI.getMoviesByCategory(category.id, 1);
|
||||
|
||||
// Проверяем, есть ли фильмы в данной категории
|
||||
if (moviesResponse.data.results && moviesResponse.data.results.length > 0) {
|
||||
const backgroundUrl = moviesResponse.data.results[0].backdrop_path ||
|
||||
moviesResponse.data.results[0].poster_path;
|
||||
@@ -47,7 +41,6 @@ function CategoriesPage() {
|
||||
backgroundUrl
|
||||
};
|
||||
} else {
|
||||
// Если фильмов нет, пробуем получить сериалы
|
||||
const tvResponse = await categoriesAPI.getTVShowsByCategory(category.id, 1);
|
||||
|
||||
if (tvResponse.data.results && tvResponse.data.results.length > 0) {
|
||||
@@ -61,14 +54,13 @@ function CategoriesPage() {
|
||||
}
|
||||
}
|
||||
|
||||
// Если ни фильмов, ни сериалов не найдено
|
||||
return {
|
||||
...category,
|
||||
backgroundUrl: undefined
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Error fetching background for category ${category.id}:`, error);
|
||||
return category; // Возвращаем категорию без фона в случае ошибки
|
||||
return category;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@@ -49,3 +49,11 @@ body {
|
||||
[data-nextjs-toast-wrapper] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Utility classes */
|
||||
.line-clamp-2 {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ 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 type { MovieDetails } from '@/lib/neoApi';
|
||||
import MoviePlayer from '@/components/MoviePlayer';
|
||||
import TorrentSelector from '@/components/TorrentSelector';
|
||||
import FavoriteButton from '@/components/FavoriteButton';
|
||||
@@ -20,23 +20,25 @@ interface MovieContentProps {
|
||||
|
||||
export default function MovieContent({ movieId, initialMovie }: MovieContentProps) {
|
||||
const [movie] = useState<MovieDetails>(initialMovie);
|
||||
const [externalIds, setExternalIds] = useState<any>(null);
|
||||
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 () => {
|
||||
const fetchExternalIds = async () => {
|
||||
try {
|
||||
const { data } = await moviesAPI.getMovie(movieId);
|
||||
const data = await moviesAPI.getExternalIds(movieId);
|
||||
setExternalIds(data);
|
||||
if (data?.imdb_id) {
|
||||
setImdbId(data.imdb_id);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching IMDb ID:', err);
|
||||
console.error('Error fetching external ids:', err);
|
||||
}
|
||||
};
|
||||
fetchImdbId();
|
||||
fetchExternalIds();
|
||||
}, [movieId]);
|
||||
|
||||
const showControls = () => {
|
||||
@@ -182,6 +184,9 @@ export default function MovieContent({ movieId, initialMovie }: MovieContentProp
|
||||
<TorrentSelector
|
||||
imdbId={imdbId}
|
||||
type="movie"
|
||||
title={movie.title}
|
||||
originalTitle={movie.original_title}
|
||||
year={movie.release_date?.split('-')[0]}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import PageLayout from '@/components/PageLayout';
|
||||
import MovieContent from './MovieContent';
|
||||
import type { MovieDetails } from '@/lib/api';
|
||||
import type { MovieDetails } from '@/lib/neoApi';
|
||||
|
||||
interface MoviePageProps {
|
||||
movieId: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Metadata } from 'next';
|
||||
import { moviesAPI } from '@/lib/api';
|
||||
import { moviesAPI } from '@/lib/neoApi';
|
||||
import MoviePage from '@/app/movie/[id]/MoviePage';
|
||||
|
||||
interface PageProps {
|
||||
@@ -8,19 +8,13 @@ interface PageProps {
|
||||
};
|
||||
}
|
||||
|
||||
// Генерация метаданных для страницы
|
||||
export async function generateMetadata(props: Promise<PageProps>): Promise<Metadata> {
|
||||
const { params } = await props;
|
||||
// В Next.js 14, нужно сначала получить данные фильма,
|
||||
// а затем использовать их для метаданных
|
||||
try {
|
||||
// Получаем id для использования в запросе
|
||||
const movieId = params.id;
|
||||
|
||||
// Запрашиваем данные фильма
|
||||
const { data: movie } = await moviesAPI.getMovie(movieId);
|
||||
|
||||
// Создаем метаданные на основе полученных данных
|
||||
return {
|
||||
title: `${movie.title} - NeoMovies`,
|
||||
description: movie.overview,
|
||||
@@ -33,7 +27,6 @@ export async function generateMetadata(props: Promise<PageProps>): Promise<Metad
|
||||
}
|
||||
}
|
||||
|
||||
// Получение данных для страницы
|
||||
async function getData(id: string) {
|
||||
try {
|
||||
const { data: movie } = await moviesAPI.getMovie(id);
|
||||
|
||||
@@ -49,9 +49,9 @@ export default function HomePage() {
|
||||
Популярные
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('now_playing')}
|
||||
onClick={() => setActiveTab('now-playing')}
|
||||
className={`${
|
||||
activeTab === 'now_playing'
|
||||
activeTab === 'now-playing'
|
||||
? 'border-red-500 text-red-600'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-500'
|
||||
} whitespace-nowrap border-b-2 px-1 py-4 text-sm font-medium`}
|
||||
@@ -59,15 +59,25 @@ export default function HomePage() {
|
||||
Новинки
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('top_rated')}
|
||||
onClick={() => setActiveTab('top-rated')}
|
||||
className={`${
|
||||
activeTab === 'top_rated'
|
||||
activeTab === 'top-rated'
|
||||
? 'border-red-500 text-red-600'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-500'
|
||||
} whitespace-nowrap border-b-2 px-1 py-4 text-sm font-medium`}
|
||||
>
|
||||
Топ рейтинга
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('upcoming')}
|
||||
className={`${
|
||||
activeTab === 'upcoming'
|
||||
? 'border-red-500 text-red-600'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:border-gray-500'
|
||||
} whitespace-nowrap border-b-2 px-1 py-4 text-sm font-medium`}
|
||||
>
|
||||
Скоро
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,30 +2,24 @@
|
||||
|
||||
import { useState, useEffect, FormEvent } from 'react';
|
||||
import { useSearchParams, useRouter } from 'next/navigation';
|
||||
import { Movie, TVShow, moviesAPI, tvAPI } from '@/lib/api';
|
||||
import { searchAPI } from '@/lib/neoApi';
|
||||
import type { Movie } from '@/lib/neoApi';
|
||||
import MovieCard from '@/components/MovieCard';
|
||||
|
||||
export default function SearchClient() {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const [query, setQuery] = useState(searchParams.get('q') || '');
|
||||
const [results, setResults] = useState<(Movie | TVShow)[]>([]);
|
||||
const [results, setResults] = useState<Movie[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const currentQuery = searchParams.get('q');
|
||||
if (currentQuery) {
|
||||
setLoading(true);
|
||||
Promise.all([
|
||||
moviesAPI.searchMovies(currentQuery),
|
||||
tvAPI.searchShows(currentQuery),
|
||||
])
|
||||
.then(([movieResults, tvResults]) => {
|
||||
const combined = [
|
||||
...(movieResults.data.results || []),
|
||||
...(tvResults.data.results || []),
|
||||
];
|
||||
setResults(combined.sort((a, b) => b.vote_count - a.vote_count));
|
||||
searchAPI.multiSearch(currentQuery)
|
||||
.then((response) => {
|
||||
setResults(response.data.results || []);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Search failed:', error);
|
||||
@@ -56,7 +50,7 @@ export default function SearchClient() {
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-4">
|
||||
{results.map((item) => (
|
||||
<MovieCard
|
||||
key={`${item.id}-${'title' in item ? 'movie' : 'tv'}`}
|
||||
key={`${item.id}-${item.media_type || 'movie'}`}
|
||||
movie={item}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { tvAPI } from '@/lib/api';
|
||||
import { tvShowsAPI } from '@/lib/neoApi';
|
||||
import { getImageUrl } from '@/lib/neoApi';
|
||||
import type { TVShowDetails } from '@/lib/api';
|
||||
import type { TVShowDetails } from '@/lib/neoApi';
|
||||
import MoviePlayer from '@/components/MoviePlayer';
|
||||
import TorrentSelector from '@/components/TorrentSelector';
|
||||
import FavoriteButton from '@/components/FavoriteButton';
|
||||
@@ -20,29 +20,28 @@ interface TVContentProps {
|
||||
|
||||
export default function TVContent({ showId, initialShow }: TVContentProps) {
|
||||
const [show] = useState<TVShowDetails>(initialShow);
|
||||
const [externalIds, setExternalIds] = useState<any>(null);
|
||||
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 () => {
|
||||
const fetchExternalIds = async () => {
|
||||
try {
|
||||
// Используем dedicated эндпоинт для получения IMDb ID
|
||||
const { data } = await tvAPI.getImdbId(showId);
|
||||
const data = await tvShowsAPI.getExternalIds(showId);
|
||||
setExternalIds(data);
|
||||
if (data?.imdb_id) {
|
||||
setImdbId(data.imdb_id);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching IMDb ID:', err);
|
||||
console.error('Error fetching external ids:', err);
|
||||
}
|
||||
};
|
||||
|
||||
// Проверяем, есть ли ID в initialShow, чтобы избежать лишнего запроса
|
||||
if (initialShow.external_ids?.imdb_id) {
|
||||
setImdbId(initialShow.external_ids.imdb_id);
|
||||
} else {
|
||||
fetchImdbId();
|
||||
fetchExternalIds();
|
||||
}
|
||||
}, [showId, initialShow.external_ids]);
|
||||
|
||||
@@ -185,7 +184,9 @@ export default function TVContent({ showId, initialShow }: TVContentProps) {
|
||||
<TorrentSelector
|
||||
imdbId={imdbId}
|
||||
type="tv"
|
||||
totalSeasons={show.number_of_seasons}
|
||||
title={show.name}
|
||||
originalTitle={show.original_name}
|
||||
year={show.first_air_date?.split('-')[0]}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import PageLayout from '@/components/PageLayout';
|
||||
import TVContent from '@/app/tv/[id]/TVContent';
|
||||
import type { TVShowDetails } from '@/lib/api';
|
||||
import type { TVShowDetails } from '@/lib/neoApi';
|
||||
|
||||
interface TVPageProps {
|
||||
showId: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Metadata } from 'next';
|
||||
import { tvAPI } from '@/lib/api';
|
||||
import { tvShowsAPI } from '@/lib/neoApi';
|
||||
import TVPage from '@/app/tv/[id]/TVPage';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
@@ -10,12 +10,11 @@ interface PageProps {
|
||||
};
|
||||
}
|
||||
|
||||
// Генерация метаданных для страницы
|
||||
export async function generateMetadata(props: Promise<PageProps>): Promise<Metadata> {
|
||||
const { params } = await props;
|
||||
try {
|
||||
const showId = params.id;
|
||||
const { data: show } = await tvAPI.getShow(showId);
|
||||
const { data: show } = await tvShowsAPI.getTVShow(showId);
|
||||
|
||||
return {
|
||||
title: `${show.name} - NeoMovies`,
|
||||
@@ -29,10 +28,9 @@ export async function generateMetadata(props: Promise<PageProps>): Promise<Metad
|
||||
}
|
||||
}
|
||||
|
||||
// Получение данных для страницы
|
||||
async function getData(id: string) {
|
||||
try {
|
||||
const { data: show } = await tvAPI.getShow(id);
|
||||
const { data: show } = await tvShowsAPI.getTVShow(id);
|
||||
return { id, show };
|
||||
} catch (error) {
|
||||
throw new Error('Failed to fetch TV show');
|
||||
|
||||
Reference in New Issue
Block a user