Skip to content

Commit

Permalink
fix: fetch localized person details from TMDb (#1243)
Browse files Browse the repository at this point in the history
* fix: fetch localized person details from TMDb

* feat: include DOB, hometown, and alternate names on person detail pages

* fix: remove unnecessary ternary operator

* fix(ui): don't display AKA when empty
  • Loading branch information
TheCatLady committed Mar 22, 2021
1 parent aee43ce commit 1d7a938
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 27 deletions.
1 change: 1 addition & 0 deletions server/api/themoviedb/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ export interface TmdbKeyword {
export interface TmdbPersonDetail {
id: number;
name: string;
birthday: string;
deathday: string;
known_for_department: string;
also_known_as?: string[];
Expand Down
2 changes: 2 additions & 0 deletions server/models/Person.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Media from '../entity/Media';
export interface PersonDetail {
id: number;
name: string;
birthday: string;
deathday: string;
knownForDepartment: string;
alsoKnownAs?: string[];
Expand Down Expand Up @@ -64,6 +65,7 @@ export interface CombinedCredit {
export const mapPersonDetails = (person: TmdbPersonDetail): PersonDetail => ({
id: person.id,
name: person.name,
birthday: person.birthday,
deathday: person.deathday,
knownForDepartment: person.known_for_department,
alsoKnownAs: person.also_known_as,
Expand Down
104 changes: 78 additions & 26 deletions src/components/PersonDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@ import PageTitle from '../Common/PageTitle';
import TitleCard from '../TitleCard';

const messages = defineMessages({
birthdate: 'Born {birthdate}',
lifespan: '{birthdate} – {deathdate}',
alsoknownas: 'Also Known As: {names}',
namedelimiter: ', ',
appearsin: 'Appearances',
crewmember: 'Crew',
ascharacter: 'as {character}',
nobiography: 'No biography available.',
});

const PersonDetails: React.FC = () => {
const intl = useIntl();
const { locale } = useContext(LanguageContext);
const router = useRouter();
const { data, error } = useSWR<PersonDetail>(
`/api/v1/person/${router.query.personId}`
`/api/v1/person/${router.query.personId}?language=${locale}`
);
const [showBio, setShowBio] = useState(false);

Expand Down Expand Up @@ -82,6 +85,41 @@ const PersonDetails: React.FC = () => {
return <Error statusCode={404} />;
}

const personAttributes: string[] = [];

if (data.birthday) {
if (data.deathday) {
personAttributes.push(
intl.formatMessage(messages.lifespan, {
birthdate: intl.formatDate(data.birthday, {
year: 'numeric',
month: 'long',
day: 'numeric',
}),
deathdate: intl.formatDate(data.deathday, {
year: 'numeric',
month: 'long',
day: 'numeric',
}),
})
);
} else {
personAttributes.push(
intl.formatMessage(messages.birthdate, {
birthdate: intl.formatDate(data.birthday, {
year: 'numeric',
month: 'long',
day: 'numeric',
}),
})
);
}
}

if (data.placeOfBirth) {
personAttributes.push(data.placeOfBirth);
}

const isLoading = !combinedCredits && !errorCombinedCredits;

const cast = (sortedCast ?? []).length > 0 && (
Expand Down Expand Up @@ -179,9 +217,13 @@ const PersonDetails: React.FC = () => {
/>
</div>
)}
<div className="relative z-10 flex flex-col items-center mt-4 mb-8 md:flex-row md:items-start">
<div
className={`relative z-10 flex flex-col items-center mt-4 mb-8 lg:flex-row ${
data.biography ? 'lg:items-start' : ''
}`}
>
{data.profilePath && (
<div className="relative flex-shrink-0 mb-6 mr-0 overflow-hidden rounded-full w-36 h-36 md:w-44 md:h-44 md:mb-0 md:mr-6 ring-1 ring-gray-700">
<div className="relative flex-shrink-0 mb-6 mr-0 overflow-hidden rounded-full w-36 h-36 lg:w-44 lg:h-44 lg:mb-0 lg:mr-6 ring-1 ring-gray-700">
<CachedImage
src={`https://image.tmdb.org/t/p/w600_and_h900_bestv2${data.profilePath}`}
alt=""
Expand All @@ -190,30 +232,40 @@ const PersonDetails: React.FC = () => {
/>
</div>
)}
<div className="text-center text-gray-300 md:text-left">
<h1 className="mb-4 text-3xl text-white md:text-4xl">{data.name}</h1>
<div className="relative">
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}
<div
className="outline-none group ring-0"
onClick={() => setShowBio((show) => !show)}
role="button"
tabIndex={-1}
>
<TruncateMarkup
lines={showBio ? 200 : 6}
ellipsis={
<Ellipsis className="relative inline-block ml-2 -top-0.5 opacity-70 group-hover:opacity-100 transition duration-300" />
}
<div className="text-center text-gray-300 lg:text-left">
<h1 className="text-3xl text-white lg:text-4xl">{data.name}</h1>
<div className="mt-1 mb-2 space-y-1 text-xs text-white sm:text-sm lg:text-base">
<div>{personAttributes.join(' | ')}</div>
{(data.alsoKnownAs ?? []).length > 0 && (
<div>
{intl.formatMessage(messages.alsoknownas, {
names: (data.alsoKnownAs ?? []).join(
intl.formatMessage(messages.namedelimiter)
),
})}
</div>
)}
</div>
{data.biography && (
<div className="relative text-left">
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}
<div
className="outline-none group ring-0"
onClick={() => setShowBio((show) => !show)}
role="button"
tabIndex={-1}
>
<div>
{data.biography
? data.biography
: intl.formatMessage(messages.nobiography)}
</div>
</TruncateMarkup>
<TruncateMarkup
lines={showBio ? 200 : 6}
ellipsis={
<Ellipsis className="relative inline-block ml-2 -top-0.5 opacity-70 group-hover:opacity-100 transition duration-300" />
}
>
<p className="pt-2 text-sm lg:text-base">{data.biography}</p>
</TruncateMarkup>
</div>
</div>
</div>
)}
</div>
</div>
{data.knownForDepartment === 'Acting' ? [cast, crew] : [crew, cast]}
Expand Down
5 changes: 4 additions & 1 deletion src/i18n/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,13 @@
"components.PermissionEdit.viewrequestsDescription": "Grant permission to view other users' requests.",
"components.PermissionEdit.vote": "Vote",
"components.PermissionEdit.voteDescription": "Grant permission to vote on requests (voting not yet implemented).",
"components.PersonDetails.alsoknownas": "Also Known As: {names}",
"components.PersonDetails.appearsin": "Appearances",
"components.PersonDetails.ascharacter": "as {character}",
"components.PersonDetails.birthdate": "Born {birthdate}",
"components.PersonDetails.crewmember": "Crew",
"components.PersonDetails.nobiography": "No biography available.",
"components.PersonDetails.lifespan": "{birthdate} – {deathdate}",
"components.PersonDetails.namedelimiter": ", ",
"components.PlexLoginButton.loading": "Loading…",
"components.PlexLoginButton.signingin": "Signing in…",
"components.PlexLoginButton.signinwithplex": "Sign In",
Expand Down

0 comments on commit 1d7a938

Please sign in to comment.