mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat: add keywords to movie/series detail pages (#3204)
This commit is contained in:
@@ -242,7 +242,7 @@ class TheMovieDb extends ExternalAPI {
|
|||||||
params: {
|
params: {
|
||||||
language,
|
language,
|
||||||
append_to_response:
|
append_to_response:
|
||||||
'credits,external_ids,videos,release_dates,watch/providers',
|
'credits,external_ids,videos,keywords,release_dates,watch/providers',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
43200
|
43200
|
||||||
|
@@ -171,6 +171,9 @@ export interface TmdbMovieDetails {
|
|||||||
id: number;
|
id: number;
|
||||||
results?: { [iso_3166_1: string]: TmdbWatchProviders };
|
results?: { [iso_3166_1: string]: TmdbWatchProviders };
|
||||||
};
|
};
|
||||||
|
keywords: {
|
||||||
|
keywords: TmdbKeyword[];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TmdbVideo {
|
export interface TmdbVideo {
|
||||||
|
@@ -9,6 +9,7 @@ import type {
|
|||||||
Crew,
|
Crew,
|
||||||
ExternalIds,
|
ExternalIds,
|
||||||
Genre,
|
Genre,
|
||||||
|
Keyword,
|
||||||
ProductionCompany,
|
ProductionCompany,
|
||||||
WatchProviders,
|
WatchProviders,
|
||||||
} from './common';
|
} from './common';
|
||||||
@@ -83,6 +84,7 @@ export interface MovieDetails {
|
|||||||
externalIds: ExternalIds;
|
externalIds: ExternalIds;
|
||||||
plexUrl?: string;
|
plexUrl?: string;
|
||||||
watchProviders?: WatchProviders[];
|
watchProviders?: WatchProviders[];
|
||||||
|
keywords: Keyword[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mapProductionCompany = (
|
export const mapProductionCompany = (
|
||||||
@@ -142,4 +144,8 @@ export const mapMovieDetails = (
|
|||||||
externalIds: mapExternalIds(movie.external_ids),
|
externalIds: mapExternalIds(movie.external_ids),
|
||||||
mediaInfo: media,
|
mediaInfo: media,
|
||||||
watchProviders: mapWatchProviders(movie['watch/providers']?.results ?? {}),
|
watchProviders: mapWatchProviders(movie['watch/providers']?.results ?? {}),
|
||||||
|
keywords: movie.keywords.keywords.map((keyword) => ({
|
||||||
|
id: keyword.id,
|
||||||
|
name: keyword.name,
|
||||||
|
})),
|
||||||
});
|
});
|
||||||
|
16
src/components/Common/Tag/index.tsx
Normal file
16
src/components/Common/Tag/index.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { TagIcon } from '@heroicons/react/24/outline';
|
||||||
|
|
||||||
|
type TagProps = {
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Tag = ({ content }: TagProps) => {
|
||||||
|
return (
|
||||||
|
<div className="inline-flex cursor-pointer items-center rounded-full bg-gray-800 px-2 py-1 text-sm text-gray-200 ring-1 ring-gray-600 transition hover:bg-gray-700">
|
||||||
|
<TagIcon className="mr-1 h-4 w-4" />
|
||||||
|
<span>{content}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tag;
|
@@ -9,6 +9,7 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner';
|
|||||||
import PageTitle from '@app/components/Common/PageTitle';
|
import PageTitle from '@app/components/Common/PageTitle';
|
||||||
import type { PlayButtonLink } from '@app/components/Common/PlayButton';
|
import type { PlayButtonLink } from '@app/components/Common/PlayButton';
|
||||||
import PlayButton from '@app/components/Common/PlayButton';
|
import PlayButton from '@app/components/Common/PlayButton';
|
||||||
|
import Tag from '@app/components/Common/Tag';
|
||||||
import Tooltip from '@app/components/Common/Tooltip';
|
import Tooltip from '@app/components/Common/Tooltip';
|
||||||
import ExternalLinkBlock from '@app/components/ExternalLinkBlock';
|
import ExternalLinkBlock from '@app/components/ExternalLinkBlock';
|
||||||
import IssueModal from '@app/components/IssueModal';
|
import IssueModal from '@app/components/IssueModal';
|
||||||
@@ -453,6 +454,20 @@ const MovieDetails = ({ movie }: MovieDetailsProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{data.keywords.length > 0 && (
|
||||||
|
<div className="mt-6">
|
||||||
|
{data.keywords.map((keyword) => (
|
||||||
|
<Link
|
||||||
|
href={`/discover/movies/keyword?keywords=${keyword.id}`}
|
||||||
|
key={`keyword-id-${keyword.id}`}
|
||||||
|
>
|
||||||
|
<a className="mb-2 mr-2 inline-flex last:mr-0">
|
||||||
|
<Tag content={keyword.name} />
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="media-overview-right">
|
<div className="media-overview-right">
|
||||||
{data.collection && (
|
{data.collection && (
|
||||||
|
@@ -11,6 +11,7 @@ import PageTitle from '@app/components/Common/PageTitle';
|
|||||||
import type { PlayButtonLink } from '@app/components/Common/PlayButton';
|
import type { PlayButtonLink } from '@app/components/Common/PlayButton';
|
||||||
import PlayButton from '@app/components/Common/PlayButton';
|
import PlayButton from '@app/components/Common/PlayButton';
|
||||||
import StatusBadgeMini from '@app/components/Common/StatusBadgeMini';
|
import StatusBadgeMini from '@app/components/Common/StatusBadgeMini';
|
||||||
|
import Tag from '@app/components/Common/Tag';
|
||||||
import Tooltip from '@app/components/Common/Tooltip';
|
import Tooltip from '@app/components/Common/Tooltip';
|
||||||
import ExternalLinkBlock from '@app/components/ExternalLinkBlock';
|
import ExternalLinkBlock from '@app/components/ExternalLinkBlock';
|
||||||
import IssueModal from '@app/components/IssueModal';
|
import IssueModal from '@app/components/IssueModal';
|
||||||
@@ -482,6 +483,20 @@ const TvDetails = ({ tv }: TvDetailsProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{data.keywords.length > 0 && (
|
||||||
|
<div className="mt-6">
|
||||||
|
{data.keywords.map((keyword) => (
|
||||||
|
<Link
|
||||||
|
href={`/discover/movies/keyword?keywords=${keyword.id}`}
|
||||||
|
key={`keyword-id-${keyword.id}`}
|
||||||
|
>
|
||||||
|
<a className="mb-2 mr-2 inline-flex last:mr-0">
|
||||||
|
<Tag content={keyword.name} />
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<h2 className="py-4">{intl.formatMessage(messages.seasonstitle)}</h2>
|
<h2 className="py-4">{intl.formatMessage(messages.seasonstitle)}</h2>
|
||||||
<div className="flex w-full flex-col space-y-2">
|
<div className="flex w-full flex-col space-y-2">
|
||||||
{data.seasons
|
{data.seasons
|
||||||
|
Reference in New Issue
Block a user