import React, { useState, useContext } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; import { useRouter } from 'next/router'; import Button from '../Common/Button'; import type { TvResult } from '../../../server/models/Search'; import Link from 'next/link'; import Slider from '../Slider'; import TitleCard from '../TitleCard'; import PersonCard from '../PersonCard'; import { LanguageContext } from '../../context/LanguageContext'; import LoadingSpinner from '../Common/LoadingSpinner'; import { useUser, Permission } from '../../hooks/useUser'; import { TvDetails as TvDetailsType } from '../../../server/models/Tv'; import { MediaStatus } from '../../../server/constants/media'; import RequestModal from '../RequestModal'; import Badge from '../Common/Badge'; import ButtonWithDropdown from '../Common/ButtonWithDropdown'; import axios from 'axios'; import SlideOver from '../Common/SlideOver'; import RequestBlock from '../RequestBlock'; import Error from '../../pages/_error'; import TmdbLogo from '../../assets/tmdb_logo.svg'; import RTFresh from '../../assets/rt_fresh.svg'; import RTRotten from '../../assets/rt_rotten.svg'; import RTAudFresh from '../../assets/rt_aud_fresh.svg'; import RTAudRotten from '../../assets/rt_aud_rotten.svg'; import type { RTRating } from '../../../server/api/rottentomatoes'; const messages = defineMessages({ userrating: 'User Rating', status: 'Status', originallanguage: 'Original Language', overview: 'Overview', cast: 'Cast', recommendations: 'Recommendations', similar: 'Similar Series', cancelrequest: 'Cancel Request', available: 'Available', unavailable: 'Unavailable', request: 'Request', requestmore: 'Request More', pending: 'Pending', overviewunavailable: 'Overview unavailable', approverequests: 'Approve {requestCount} {requestCount, plural, one {Request} other {Requests}}', declinerequests: 'Decline {requestCount} {requestCount, plural, one {Request} other {Requests}}', }); interface TvDetailsProps { tv?: TvDetailsType; } interface SearchResult { page: number; totalResults: number; totalPages: number; results: TvResult[]; } enum MediaRequestStatus { PENDING = 1, APPROVED, DECLINED, AVAILABLE, } const TvDetails: React.FC = ({ tv }) => { const { hasPermission } = useUser(); const router = useRouter(); const intl = useIntl(); const { locale } = useContext(LanguageContext); const [showRequestModal, setShowRequestModal] = useState(false); const [showManager, setShowManager] = useState(false); const { data, error, revalidate } = useSWR( `/api/v1/tv/${router.query.tvId}?language=${locale}`, { initialData: tv, } ); const { data: recommended, error: recommendedError } = useSWR( `/api/v1/tv/${router.query.tvId}/recommendations?language=${locale}` ); const { data: similar, error: similarError } = useSWR( `/api/v1/tv/${router.query.tvId}/similar?language=${locale}` ); const { data: ratingData } = useSWR( `/api/v1/tv/${router.query.tvId}/ratings` ); if (!data && !error) { return ; } if (!data) { return ; } const activeRequests = data.mediaInfo?.requests?.filter( (request) => request.status === MediaRequestStatus.PENDING ); const modifyRequests = async (type: 'approve' | 'decline'): Promise => { if (!activeRequests) { return; } await Promise.all( activeRequests.map(async (request) => { return axios.get(`/api/v1/request/${request.id}/${type}`); }) ); revalidate(); }; return (
{ revalidate(); setShowRequestModal(false); }} onCancel={() => setShowRequestModal(false)} /> setShowManager(false)} subText={data.name} >

Requests

    {data.mediaInfo?.requests?.map((request) => (
  • revalidate()} />
  • ))} {(data.mediaInfo?.requests ?? []).length === 0 && (
  • No requests
  • )}
{data.mediaInfo?.status === MediaStatus.AVAILABLE && ( Available )} {data.mediaInfo?.status === MediaStatus.PARTIALLY_AVAILABLE && ( Partially Available )} {data.mediaInfo?.status === MediaStatus.PROCESSING && ( Unavailable )} {data.mediaInfo?.status === MediaStatus.PENDING && ( Pending )}

{data.name}{' '} ({data.firstAirDate.slice(0, 4)})

{data.genres.map((g) => g.name).join(', ')}
{(!data.mediaInfo || data.mediaInfo.status === MediaStatus.UNKNOWN) && ( )} {data.mediaInfo && data.mediaInfo.status !== MediaStatus.UNKNOWN && ( } text={ <> } onClick={() => setShowRequestModal(true)} > {hasPermission(Permission.MANAGE_REQUESTS) && activeRequests && activeRequests.length > 0 && ( <> modifyRequests('approve')} > modifyRequests('decline')} > )} )} {hasPermission(Permission.MANAGE_REQUESTS) && ( )}

{data.overview ? data.overview : intl.formatMessage(messages.overviewunavailable)}

{(data.voteCount > 0 || ratingData) && (
{ratingData?.criticsRating && ( <> {ratingData.criticsRating === 'Rotten' ? ( ) : ( )} {ratingData.criticsScore}% )} {ratingData?.audienceRating && ( <> {ratingData.audienceRating === 'Spilled' ? ( ) : ( )} {ratingData.audienceScore}% )} {data.voteCount > 0 && ( <> {data.voteAverage}/10 )}
)}
{data.status}
{data.originalLanguage}
( ))} /> ( ))} /> ( ))} />
); }; export default TvDetails;