feat(frontend): add full crew page for movies/shows

This commit is contained in:
sct
2020-12-22 00:37:26 +09:00
parent 12127a7763
commit 604ba2a92f
8 changed files with 206 additions and 3 deletions

View File

@@ -42,11 +42,11 @@ const MovieCast: React.FC = () => {
{intl.formatMessage(messages.fullcast)} {intl.formatMessage(messages.fullcast)}
</Header> </Header>
<ul className="grid grid-cols-2 gap-6 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-7 2xl:grid-cols-8"> <ul className="grid grid-cols-2 gap-6 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-7 2xl:grid-cols-8">
{data?.credits.cast.map((person) => { {data?.credits.cast.map((person, index) => {
return ( return (
<li <li
key={person.id} key={`cast-${person.id}-${index}`}
className="col-span-1 flex flex-col text-center items-center" className="flex flex-col items-center col-span-1 text-center"
> >
<PersonCard <PersonCard
name={person.name} name={person.name}

View File

@@ -0,0 +1,66 @@
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { useContext } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
import { MovieDetails } from '../../../../server/models/Movie';
import { LanguageContext } from '../../../context/LanguageContext';
import Error from '../../../pages/_error';
import Header from '../../Common/Header';
import LoadingSpinner from '../../Common/LoadingSpinner';
import PersonCard from '../../PersonCard';
const messages = defineMessages({
fullcrew: 'Full Crew',
});
const MovieCrew: React.FC = () => {
const router = useRouter();
const intl = useIntl();
const { locale } = useContext(LanguageContext);
const { data, error } = useSWR<MovieDetails>(
`/api/v1/movie/${router.query.movieId}?language=${locale}`
);
if (!data && !error) {
return <LoadingSpinner />;
}
if (!data) {
return <Error statusCode={404} />;
}
return (
<>
<Header
subtext={
<Link href={`/movie/${data.id}`}>
<a className="hover:underline">{data.title}</a>
</Link>
}
>
{intl.formatMessage(messages.fullcrew)}
</Header>
<ul className="grid grid-cols-2 gap-6 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-7 2xl:grid-cols-8">
{data?.credits.crew.map((person, index) => {
return (
<li
key={`crew-${person.id}-${index}`}
className="flex flex-col items-center col-span-1 text-center"
>
<PersonCard
name={person.name}
personId={person.id}
subName={person.job}
profilePath={person.profilePath}
canExpand
/>
</li>
);
})}
</ul>
</>
);
};
export default MovieCrew;

View File

@@ -68,6 +68,7 @@ const messages = defineMessages({
approve: 'Approve', approve: 'Approve',
decline: 'Decline', decline: 'Decline',
studio: 'Studio', studio: 'Studio',
viewfullcrew: 'View Full Crew',
}); });
interface MovieDetailsProps { interface MovieDetailsProps {
@@ -412,6 +413,29 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</li> </li>
))} ))}
</ul> </ul>
{sortedCrew.length > 0 && (
<div className="flex justify-end mt-4">
<Link href={`/movie/${data.id}/crew`}>
<a className="flex items-center text-gray-400 transition duration-300 hover:text-gray-100">
<span>{intl.formatMessage(messages.viewfullcrew)}</span>
<svg
className="inline-block w-5 h-5 ml-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</a>
</Link>
</div>
)}
</div> </div>
<div className="w-full mt-8 md:w-80 md:mt-0"> <div className="w-full mt-8 md:w-80 md:mt-0">
<div className="bg-gray-900 border border-gray-800 rounded-lg shadow"> <div className="bg-gray-900 border border-gray-800 rounded-lg shadow">

View File

@@ -0,0 +1,66 @@
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { useContext } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
import type { TvDetails } from '../../../../server/models/Tv';
import { LanguageContext } from '../../../context/LanguageContext';
import Error from '../../../pages/_error';
import Header from '../../Common/Header';
import LoadingSpinner from '../../Common/LoadingSpinner';
import PersonCard from '../../PersonCard';
const messages = defineMessages({
fullseriescrew: 'Full Series Crew',
});
const TvCrew: React.FC = () => {
const router = useRouter();
const intl = useIntl();
const { locale } = useContext(LanguageContext);
const { data, error } = useSWR<TvDetails>(
`/api/v1/tv/${router.query.tvId}?language=${locale}`
);
if (!data && !error) {
return <LoadingSpinner />;
}
if (!data) {
return <Error statusCode={404} />;
}
return (
<>
<Header
subtext={
<Link href={`/tv/${data.id}`}>
<a className="hover:underline">{data.name}</a>
</Link>
}
>
{intl.formatMessage(messages.fullseriescrew)}
</Header>
<ul className="grid grid-cols-2 gap-6 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-7 2xl:grid-cols-8">
{data?.credits.crew.map((person, index) => {
return (
<li
key={`crew-${person.id}-${index}`}
className="flex flex-col items-center col-span-1 text-center"
>
<PersonCard
name={person.name}
personId={person.id}
subName={person.job}
profilePath={person.profilePath}
canExpand
/>
</li>
);
})}
</ul>
</>
);
};
export default TvCrew;

View File

@@ -63,6 +63,7 @@ const messages = defineMessages({
showtype: 'Show Type', showtype: 'Show Type',
anime: 'Anime', anime: 'Anime',
network: 'Network', network: 'Network',
viewfullcrew: 'View Full Crew',
}); });
interface TvDetailsProps { interface TvDetailsProps {
@@ -436,6 +437,29 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
</li> </li>
))} ))}
</ul> </ul>
{sortedCrew.length > 0 && (
<div className="flex justify-end mt-4">
<Link href={`/tv/${data.id}/crew`}>
<a className="flex items-center text-gray-400 transition duration-300 hover:text-gray-100">
<span>{intl.formatMessage(messages.viewfullcrew)}</span>
<svg
className="inline-block w-5 h-5 ml-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</a>
</Link>
</div>
)}
</div> </div>
<div className="w-full mt-8 md:w-80 md:mt-0"> <div className="w-full mt-8 md:w-80 md:mt-0">
<div className="bg-gray-900 border border-gray-800 rounded-lg shadow"> <div className="bg-gray-900 border border-gray-800 rounded-lg shadow">

View File

@@ -19,6 +19,7 @@
"components.Layout.alphawarning": "This is ALPHA software. Almost everything is bound to be nearly broken and/or unstable. Please report issues to the Overseerr GitHub!", "components.Layout.alphawarning": "This is ALPHA software. Almost everything is bound to be nearly broken and/or unstable. Please report issues to the Overseerr GitHub!",
"components.Login.signinplex": "Sign in to continue", "components.Login.signinplex": "Sign in to continue",
"components.MovieDetails.MovieCast.fullcast": "Full Cast", "components.MovieDetails.MovieCast.fullcast": "Full Cast",
"components.MovieDetails.MovieCrew.fullcrew": "Full Crew",
"components.MovieDetails.approve": "Approve", "components.MovieDetails.approve": "Approve",
"components.MovieDetails.available": "Available", "components.MovieDetails.available": "Available",
"components.MovieDetails.budget": "Budget", "components.MovieDetails.budget": "Budget",
@@ -46,9 +47,11 @@
"components.MovieDetails.studio": "Studio", "components.MovieDetails.studio": "Studio",
"components.MovieDetails.unavailable": "Unavailable", "components.MovieDetails.unavailable": "Unavailable",
"components.MovieDetails.userrating": "User Rating", "components.MovieDetails.userrating": "User Rating",
"components.MovieDetails.viewfullcrew": "View Full Crew",
"components.MovieDetails.viewrequest": "View Request", "components.MovieDetails.viewrequest": "View Request",
"components.PersonDetails.appearsin": "Appears in", "components.PersonDetails.appearsin": "Appears in",
"components.PersonDetails.ascharacter": "as {character}", "components.PersonDetails.ascharacter": "as {character}",
"components.PersonDetails.crewmember": "Crew Member",
"components.PersonDetails.nobiography": "No biography available.", "components.PersonDetails.nobiography": "No biography available.",
"components.PlexLoginButton.loading": "Loading…", "components.PlexLoginButton.loading": "Loading…",
"components.PlexLoginButton.loggingin": "Logging in…", "components.PlexLoginButton.loggingin": "Logging in…",
@@ -277,6 +280,7 @@
"components.TitleCard.movie": "Movie", "components.TitleCard.movie": "Movie",
"components.TitleCard.tvshow": "Series", "components.TitleCard.tvshow": "Series",
"components.TvDetails.TvCast.fullseriescast": "Full Series Cast", "components.TvDetails.TvCast.fullseriescast": "Full Series Cast",
"components.TvDetails.TvCrew.fullseriescrew": "Full Series Crew",
"components.TvDetails.anime": "Anime", "components.TvDetails.anime": "Anime",
"components.TvDetails.approve": "Approve", "components.TvDetails.approve": "Approve",
"components.TvDetails.approverequests": "Approve {requestCount} {requestCount, plural, one {Request} other {Requests}}", "components.TvDetails.approverequests": "Approve {requestCount} {requestCount, plural, one {Request} other {Requests}}",
@@ -305,6 +309,7 @@
"components.TvDetails.status": "Status", "components.TvDetails.status": "Status",
"components.TvDetails.unavailable": "Unavailable", "components.TvDetails.unavailable": "Unavailable",
"components.TvDetails.userrating": "User Rating", "components.TvDetails.userrating": "User Rating",
"components.TvDetails.viewfullcrew": "View Full Crew",
"components.UserEdit.admin": "Admin", "components.UserEdit.admin": "Admin",
"components.UserEdit.adminDescription": "Full administrator access. Bypasses all permission checks.", "components.UserEdit.adminDescription": "Full administrator access. Bypasses all permission checks.",
"components.UserEdit.autoapprove": "Auto Approve", "components.UserEdit.autoapprove": "Auto Approve",

View File

@@ -0,0 +1,9 @@
import { NextPage } from 'next';
import React from 'react';
import MovieCrew from '../../../components/MovieDetails/MovieCrew';
const MovieCrewPage: NextPage = () => {
return <MovieCrew />;
};
export default MovieCrewPage;

View File

@@ -0,0 +1,9 @@
import { NextPage } from 'next';
import React from 'react';
import TvCrew from '../../../components/TvDetails/TvCrew';
const TvCrewPage: NextPage = () => {
return <TvCrew />;
};
export default TvCrewPage;