diff --git a/server/api/themoviedb/interfaces.ts b/server/api/themoviedb/interfaces.ts index f626a16de..c3b02b6cf 100644 --- a/server/api/themoviedb/interfaces.ts +++ b/server/api/themoviedb/interfaces.ts @@ -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[]; diff --git a/server/models/Person.ts b/server/models/Person.ts index 522a8e5e9..14925edb6 100644 --- a/server/models/Person.ts +++ b/server/models/Person.ts @@ -8,6 +8,7 @@ import Media from '../entity/Media'; export interface PersonDetail { id: number; name: string; + birthday: string; deathday: string; knownForDepartment: string; alsoKnownAs?: string[]; @@ -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, diff --git a/src/components/PersonDetails/index.tsx b/src/components/PersonDetails/index.tsx index 81f7985c7..7ed2ac14e 100644 --- a/src/components/PersonDetails/index.tsx +++ b/src/components/PersonDetails/index.tsx @@ -16,10 +16,13 @@ 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 = () => { @@ -27,7 +30,7 @@ const PersonDetails: React.FC = () => { const { locale } = useContext(LanguageContext); const router = useRouter(); const { data, error } = useSWR( - `/api/v1/person/${router.query.personId}` + `/api/v1/person/${router.query.personId}?language=${locale}` ); const [showBio, setShowBio] = useState(false); @@ -82,6 +85,41 @@ const PersonDetails: React.FC = () => { return ; } + 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 && ( @@ -179,9 +217,13 @@ const PersonDetails: React.FC = () => { /> )} -
+
{data.profilePath && ( -
+
{ />
)} -
-

{data.name}

-
- {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */} -
setShowBio((show) => !show)} - role="button" - tabIndex={-1} - > - - } - > -
- {data.biography - ? data.biography - : intl.formatMessage(messages.nobiography)} -
-
-
+
+

{data.name}

+
+
{personAttributes.join(' | ')}
+ {(data.alsoKnownAs ?? []).length > 0 && ( +
+ {intl.formatMessage(messages.alsoknownas, { + names: (data.alsoKnownAs ?? []).join( + intl.formatMessage(messages.namedelimiter) + ), + })} +
+ )}
+ {data.biography && ( +
+ {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */} +
setShowBio((show) => !show)} + role="button" + tabIndex={-1} + > + + } + > +

{data.biography}

+
+
+
+ )}
{data.knownForDepartment === 'Acting' ? [cast, crew] : [crew, cast]} diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 9b92a366e..d5c4623a2 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -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",