mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2026-01-03 21:37:42 -05:00
feat: add discover customization (#3182)
This commit is contained in:
68
src/components/Discover/DiscoverMovieKeyword/index.tsx
Normal file
68
src/components/Discover/DiscoverMovieKeyword/index.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import Header from '@app/components/Common/Header';
|
||||
import ListView from '@app/components/Common/ListView';
|
||||
import PageTitle from '@app/components/Common/PageTitle';
|
||||
import useDiscover from '@app/hooks/useDiscover';
|
||||
import { encodeURIExtraParams } from '@app/hooks/useSearchInput';
|
||||
import globalMessages from '@app/i18n/globalMessages';
|
||||
import Error from '@app/pages/_error';
|
||||
import type { TmdbKeyword } from '@server/api/themoviedb/interfaces';
|
||||
import type { MovieResult } from '@server/models/Search';
|
||||
import { useRouter } from 'next/router';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
const messages = defineMessages({
|
||||
keywordMovies: '{keywordTitle} Movies',
|
||||
});
|
||||
|
||||
const DiscoverMovieKeyword = () => {
|
||||
const router = useRouter();
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
isLoadingInitialData,
|
||||
isEmpty,
|
||||
isLoadingMore,
|
||||
isReachingEnd,
|
||||
titles,
|
||||
fetchMore,
|
||||
error,
|
||||
firstResultData,
|
||||
} = useDiscover<MovieResult, { keywords: TmdbKeyword[] }>(
|
||||
`/api/v1/discover/movies`,
|
||||
{
|
||||
keywords: encodeURIExtraParams(router.query.keywords as string),
|
||||
}
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return <Error statusCode={500} />;
|
||||
}
|
||||
|
||||
const title = isLoadingInitialData
|
||||
? intl.formatMessage(globalMessages.loading)
|
||||
: intl.formatMessage(messages.keywordMovies, {
|
||||
keywordTitle: firstResultData?.keywords
|
||||
.map((k) => `${k.name[0].toUpperCase()}${k.name.substring(1)}`)
|
||||
.join(', '),
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={title} />
|
||||
<div className="mt-1 mb-5">
|
||||
<Header>{title}</Header>
|
||||
</div>
|
||||
<ListView
|
||||
items={titles}
|
||||
isEmpty={isEmpty}
|
||||
isLoading={
|
||||
isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0)
|
||||
}
|
||||
isReachingEnd={isReachingEnd}
|
||||
onScrollBottom={fetchMore}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DiscoverMovieKeyword;
|
||||
68
src/components/Discover/DiscoverTvKeyword/index.tsx
Normal file
68
src/components/Discover/DiscoverTvKeyword/index.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import Header from '@app/components/Common/Header';
|
||||
import ListView from '@app/components/Common/ListView';
|
||||
import PageTitle from '@app/components/Common/PageTitle';
|
||||
import useDiscover from '@app/hooks/useDiscover';
|
||||
import { encodeURIExtraParams } from '@app/hooks/useSearchInput';
|
||||
import globalMessages from '@app/i18n/globalMessages';
|
||||
import Error from '@app/pages/_error';
|
||||
import type { TmdbKeyword } from '@server/api/themoviedb/interfaces';
|
||||
import type { TvResult } from '@server/models/Search';
|
||||
import { useRouter } from 'next/router';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
const messages = defineMessages({
|
||||
keywordSeries: '{keywordTitle} Series',
|
||||
});
|
||||
|
||||
const DiscoverTvKeyword = () => {
|
||||
const router = useRouter();
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
isLoadingInitialData,
|
||||
isEmpty,
|
||||
isLoadingMore,
|
||||
isReachingEnd,
|
||||
titles,
|
||||
fetchMore,
|
||||
error,
|
||||
firstResultData,
|
||||
} = useDiscover<TvResult, { keywords: TmdbKeyword[] }>(
|
||||
`/api/v1/discover/tv`,
|
||||
{
|
||||
keywords: encodeURIExtraParams(router.query.keywords as string),
|
||||
}
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return <Error statusCode={500} />;
|
||||
}
|
||||
|
||||
const title = isLoadingInitialData
|
||||
? intl.formatMessage(globalMessages.loading)
|
||||
: intl.formatMessage(messages.keywordSeries, {
|
||||
keywordTitle: firstResultData?.keywords
|
||||
.map((k) => `${k.name[0].toUpperCase()}${k.name.substring(1)}`)
|
||||
.join(', '),
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={title} />
|
||||
<div className="mt-1 mb-5">
|
||||
<Header>{title}</Header>
|
||||
</div>
|
||||
<ListView
|
||||
items={titles}
|
||||
isEmpty={isEmpty}
|
||||
isLoading={
|
||||
isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0)
|
||||
}
|
||||
isReachingEnd={isReachingEnd}
|
||||
onScrollBottom={fetchMore}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DiscoverTvKeyword;
|
||||
79
src/components/Discover/PlexWatchlistSlider/index.tsx
Normal file
79
src/components/Discover/PlexWatchlistSlider/index.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import Slider from '@app/components/Slider';
|
||||
import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
|
||||
import { UserType, useUser } from '@app/hooks/useUser';
|
||||
import { ArrowCircleRightIcon } from '@heroicons/react/outline';
|
||||
import type { WatchlistItem } from '@server/interfaces/api/discoverInterfaces';
|
||||
import Link from 'next/link';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import useSWR from 'swr';
|
||||
|
||||
const messages = defineMessages({
|
||||
plexwatchlist: 'Your Plex Watchlist',
|
||||
emptywatchlist:
|
||||
'Media added to your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> will appear here.',
|
||||
});
|
||||
|
||||
const PlexWatchlistSlider = () => {
|
||||
const intl = useIntl();
|
||||
const { user } = useUser();
|
||||
|
||||
const { data: watchlistItems, error: watchlistError } = useSWR<{
|
||||
page: number;
|
||||
totalPages: number;
|
||||
totalResults: number;
|
||||
results: WatchlistItem[];
|
||||
}>(user?.userType === UserType.PLEX ? '/api/v1/discover/watchlist' : null, {
|
||||
revalidateOnMount: true,
|
||||
});
|
||||
|
||||
if (
|
||||
user?.userType !== UserType.PLEX ||
|
||||
(watchlistItems &&
|
||||
watchlistItems.results.length === 0 &&
|
||||
!user?.settings?.watchlistSyncMovies &&
|
||||
!user?.settings?.watchlistSyncTv) ||
|
||||
watchlistError
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="slider-header">
|
||||
<Link href="/discover/watchlist">
|
||||
<a className="slider-title">
|
||||
<span>{intl.formatMessage(messages.plexwatchlist)}</span>
|
||||
<ArrowCircleRightIcon />
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<Slider
|
||||
sliderKey="watchlist"
|
||||
isLoading={!watchlistItems}
|
||||
isEmpty={!!watchlistItems && watchlistItems.results.length === 0}
|
||||
emptyMessage={intl.formatMessage(messages.emptywatchlist, {
|
||||
PlexWatchlistSupportLink: (msg: React.ReactNode) => (
|
||||
<a
|
||||
href="https://support.plex.tv/articles/universal-watchlist/"
|
||||
className="text-white transition duration-300 hover:underline"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{msg}
|
||||
</a>
|
||||
),
|
||||
})}
|
||||
items={watchlistItems?.results.map((item) => (
|
||||
<TmdbTitleCard
|
||||
id={item.tmdbId}
|
||||
key={`watchlist-slider-item-${item.ratingKey}`}
|
||||
tmdbId={item.tmdbId}
|
||||
type={item.mediaType}
|
||||
/>
|
||||
))}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlexWatchlistSlider;
|
||||
49
src/components/Discover/RecentRequestsSlider/index.tsx
Normal file
49
src/components/Discover/RecentRequestsSlider/index.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { sliderTitles } from '@app/components/Discover/constants';
|
||||
import RequestCard from '@app/components/RequestCard';
|
||||
import Slider from '@app/components/Slider';
|
||||
import { ArrowCircleRightIcon } from '@heroicons/react/outline';
|
||||
import type { RequestResultsResponse } from '@server/interfaces/api/requestInterfaces';
|
||||
import Link from 'next/link';
|
||||
import { useIntl } from 'react-intl';
|
||||
import useSWR from 'swr';
|
||||
|
||||
const RecentRequestsSlider = () => {
|
||||
const intl = useIntl();
|
||||
const { data: requests, error: requestError } =
|
||||
useSWR<RequestResultsResponse>(
|
||||
'/api/v1/request?filter=all&take=10&sort=modified&skip=0',
|
||||
{
|
||||
revalidateOnMount: true,
|
||||
}
|
||||
);
|
||||
|
||||
if (requests && requests.results.length === 0 && !requestError) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="slider-header">
|
||||
<Link href="/requests?filter=all">
|
||||
<a className="slider-title">
|
||||
<span>{intl.formatMessage(sliderTitles.recentrequests)}</span>
|
||||
<ArrowCircleRightIcon />
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<Slider
|
||||
sliderKey="requests"
|
||||
isLoading={!requests}
|
||||
items={(requests?.results ?? []).map((request) => (
|
||||
<RequestCard
|
||||
key={`request-slider-item-${request.id}`}
|
||||
request={request}
|
||||
/>
|
||||
))}
|
||||
placeholder={<RequestCard.Placeholder />}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RecentRequestsSlider;
|
||||
53
src/components/Discover/RecentlyAddedSlider/index.tsx
Normal file
53
src/components/Discover/RecentlyAddedSlider/index.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import Slider from '@app/components/Slider';
|
||||
import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
|
||||
import { Permission, useUser } from '@app/hooks/useUser';
|
||||
import type { MediaResultsResponse } from '@server/interfaces/api/mediaInterfaces';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import useSWR from 'swr';
|
||||
|
||||
const messages = defineMessages({
|
||||
recentlyAdded: 'Recently Added',
|
||||
});
|
||||
|
||||
const RecentlyAddedSlider = () => {
|
||||
const intl = useIntl();
|
||||
const { hasPermission } = useUser();
|
||||
const { data: media, error: mediaError } = useSWR<MediaResultsResponse>(
|
||||
'/api/v1/media?filter=allavailable&take=20&sort=mediaAdded',
|
||||
{ revalidateOnMount: true }
|
||||
);
|
||||
|
||||
if (
|
||||
(media && !media.results.length && !mediaError) ||
|
||||
!hasPermission([Permission.MANAGE_REQUESTS, Permission.RECENT_VIEW], {
|
||||
type: 'or',
|
||||
})
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="slider-header">
|
||||
<div className="slider-title">
|
||||
<span>{intl.formatMessage(messages.recentlyAdded)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<Slider
|
||||
sliderKey="media"
|
||||
isLoading={!media}
|
||||
items={(media?.results ?? []).map((item) => (
|
||||
<TmdbTitleCard
|
||||
key={`media-slider-item-${item.id}`}
|
||||
id={item.id}
|
||||
tmdbId={item.tmdbId}
|
||||
tvdbId={item.tvdbId}
|
||||
type={item.mediaType}
|
||||
/>
|
||||
))}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RecentlyAddedSlider;
|
||||
@@ -1,3 +1,5 @@
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
type AvailableColors =
|
||||
| 'black'
|
||||
| 'red'
|
||||
@@ -61,3 +63,25 @@ export const genreColorMap: Record<number, [string, string]> = {
|
||||
10767: colorTones.lightgreen, // Talk
|
||||
10768: colorTones.darkred, // War & Politics
|
||||
};
|
||||
|
||||
export const sliderTitles = defineMessages({
|
||||
recentrequests: 'Recent Requests',
|
||||
popularmovies: 'Popular Movies',
|
||||
populartv: 'Popular Series',
|
||||
upcomingtv: 'Upcoming Series',
|
||||
recentlyAdded: 'Recently Added',
|
||||
upcoming: 'Upcoming Movies',
|
||||
trending: 'Trending',
|
||||
plexwatchlist: 'Your Plex Watchlist',
|
||||
moviegenres: 'Movie Genres',
|
||||
tvgenres: 'Series Genres',
|
||||
studios: 'Studios',
|
||||
networks: 'Networks',
|
||||
tmdbmoviekeyword: 'TMDB Movie Keyword',
|
||||
tmdbtvkeyword: 'TMDB Series Keyword',
|
||||
tmdbmoviegenre: 'TMDB Movie Genre',
|
||||
tmdbtvgenre: 'TMDB Series Genre',
|
||||
tmdbnetwork: 'TMDB Network',
|
||||
tmdbstudio: 'TMDB Studio',
|
||||
tmdbsearch: 'TMDB Search',
|
||||
});
|
||||
|
||||
@@ -1,189 +1,180 @@
|
||||
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
|
||||
import PageTitle from '@app/components/Common/PageTitle';
|
||||
import { sliderTitles } from '@app/components/Discover/constants';
|
||||
import MovieGenreSlider from '@app/components/Discover/MovieGenreSlider';
|
||||
import NetworkSlider from '@app/components/Discover/NetworkSlider';
|
||||
import PlexWatchlistSlider from '@app/components/Discover/PlexWatchlistSlider';
|
||||
import RecentlyAddedSlider from '@app/components/Discover/RecentlyAddedSlider';
|
||||
import RecentRequestsSlider from '@app/components/Discover/RecentRequestsSlider';
|
||||
import StudioSlider from '@app/components/Discover/StudioSlider';
|
||||
import TvGenreSlider from '@app/components/Discover/TvGenreSlider';
|
||||
import MediaSlider from '@app/components/MediaSlider';
|
||||
import RequestCard from '@app/components/RequestCard';
|
||||
import Slider from '@app/components/Slider';
|
||||
import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
|
||||
import { Permission, UserType, useUser } from '@app/hooks/useUser';
|
||||
import { ArrowCircleRightIcon } from '@heroicons/react/outline';
|
||||
import type { WatchlistItem } from '@server/interfaces/api/discoverInterfaces';
|
||||
import type { MediaResultsResponse } from '@server/interfaces/api/mediaInterfaces';
|
||||
import type { RequestResultsResponse } from '@server/interfaces/api/requestInterfaces';
|
||||
import Link from 'next/link';
|
||||
import { encodeURIExtraParams } from '@app/hooks/useSearchInput';
|
||||
import { DiscoverSliderType } from '@server/constants/discover';
|
||||
import type DiscoverSlider from '@server/entity/DiscoverSlider';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import useSWR from 'swr';
|
||||
|
||||
const messages = defineMessages({
|
||||
discover: 'Discover',
|
||||
recentrequests: 'Recent Requests',
|
||||
popularmovies: 'Popular Movies',
|
||||
populartv: 'Popular Series',
|
||||
upcomingtv: 'Upcoming Series',
|
||||
recentlyAdded: 'Recently Added',
|
||||
upcoming: 'Upcoming Movies',
|
||||
trending: 'Trending',
|
||||
plexwatchlist: 'Your Plex Watchlist',
|
||||
emptywatchlist:
|
||||
'Media added to your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> will appear here.',
|
||||
});
|
||||
|
||||
const Discover = () => {
|
||||
const intl = useIntl();
|
||||
const { user, hasPermission } = useUser();
|
||||
|
||||
const { data: media, error: mediaError } = useSWR<MediaResultsResponse>(
|
||||
'/api/v1/media?filter=allavailable&take=20&sort=mediaAdded',
|
||||
{ revalidateOnMount: true }
|
||||
const { data: discoverData, error: discoverError } = useSWR<DiscoverSlider[]>(
|
||||
'/api/v1/settings/discover'
|
||||
);
|
||||
|
||||
const { data: requests, error: requestError } =
|
||||
useSWR<RequestResultsResponse>(
|
||||
'/api/v1/request?filter=all&take=10&sort=modified&skip=0',
|
||||
{
|
||||
revalidateOnMount: true,
|
||||
}
|
||||
);
|
||||
|
||||
const { data: watchlistItems, error: watchlistError } = useSWR<{
|
||||
page: number;
|
||||
totalPages: number;
|
||||
totalResults: number;
|
||||
results: WatchlistItem[];
|
||||
}>(user?.userType === UserType.PLEX ? '/api/v1/discover/watchlist' : null, {
|
||||
revalidateOnMount: true,
|
||||
});
|
||||
if (!discoverData && !discoverError) {
|
||||
return <LoadingSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={intl.formatMessage(messages.discover)} />
|
||||
{(!media || !!media.results.length) &&
|
||||
!mediaError &&
|
||||
hasPermission([Permission.MANAGE_REQUESTS, Permission.RECENT_VIEW], {
|
||||
type: 'or',
|
||||
}) && (
|
||||
<>
|
||||
<div className="slider-header">
|
||||
<div className="slider-title">
|
||||
<span>{intl.formatMessage(messages.recentlyAdded)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<Slider
|
||||
sliderKey="media"
|
||||
isLoading={!media}
|
||||
items={(media?.results ?? []).map((item) => (
|
||||
<TmdbTitleCard
|
||||
key={`media-slider-item-${item.id}`}
|
||||
id={item.id}
|
||||
tmdbId={item.tmdbId}
|
||||
tvdbId={item.tvdbId}
|
||||
type={item.mediaType}
|
||||
/>
|
||||
))}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{(!requests || !!requests.results.length) && !requestError && (
|
||||
<>
|
||||
<div className="slider-header">
|
||||
<Link href="/requests?filter=all">
|
||||
<a className="slider-title">
|
||||
<span>{intl.formatMessage(messages.recentrequests)}</span>
|
||||
<ArrowCircleRightIcon />
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<Slider
|
||||
sliderKey="requests"
|
||||
isLoading={!requests}
|
||||
items={(requests?.results ?? []).map((request) => (
|
||||
<RequestCard
|
||||
key={`request-slider-item-${request.id}`}
|
||||
request={request}
|
||||
{discoverData?.map((slider) => {
|
||||
if (!slider.enabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (slider.type) {
|
||||
case DiscoverSliderType.RECENTLY_ADDED:
|
||||
return <RecentlyAddedSlider />;
|
||||
case DiscoverSliderType.RECENT_REQUESTS:
|
||||
return <RecentRequestsSlider />;
|
||||
case DiscoverSliderType.PLEX_WATCHLIST:
|
||||
return <PlexWatchlistSlider />;
|
||||
case DiscoverSliderType.TRENDING:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey="trending"
|
||||
title={intl.formatMessage(sliderTitles.trending)}
|
||||
url="/api/v1/discover/trending"
|
||||
linkUrl="/discover/trending"
|
||||
/>
|
||||
))}
|
||||
placeholder={<RequestCard.Placeholder />}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{user?.userType === UserType.PLEX &&
|
||||
(!watchlistItems ||
|
||||
!!watchlistItems.results.length ||
|
||||
user.settings?.watchlistSyncMovies ||
|
||||
user.settings?.watchlistSyncTv) &&
|
||||
!watchlistError && (
|
||||
<>
|
||||
<div className="slider-header">
|
||||
<Link href="/discover/watchlist">
|
||||
<a className="slider-title">
|
||||
<span>{intl.formatMessage(messages.plexwatchlist)}</span>
|
||||
<ArrowCircleRightIcon />
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<Slider
|
||||
sliderKey="watchlist"
|
||||
isLoading={!watchlistItems}
|
||||
isEmpty={!!watchlistItems && watchlistItems.results.length === 0}
|
||||
emptyMessage={intl.formatMessage(messages.emptywatchlist, {
|
||||
PlexWatchlistSupportLink: (msg: React.ReactNode) => (
|
||||
<a
|
||||
href="https://support.plex.tv/articles/universal-watchlist/"
|
||||
className="text-white transition duration-300 hover:underline"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{msg}
|
||||
</a>
|
||||
),
|
||||
})}
|
||||
items={watchlistItems?.results.map((item) => (
|
||||
<TmdbTitleCard
|
||||
id={item.tmdbId}
|
||||
key={`watchlist-slider-item-${item.ratingKey}`}
|
||||
tmdbId={item.tmdbId}
|
||||
type={item.mediaType}
|
||||
/>
|
||||
))}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<MediaSlider
|
||||
sliderKey="trending"
|
||||
title={intl.formatMessage(messages.trending)}
|
||||
url="/api/v1/discover/trending"
|
||||
linkUrl="/discover/trending"
|
||||
/>
|
||||
<MediaSlider
|
||||
sliderKey="popular-movies"
|
||||
title={intl.formatMessage(messages.popularmovies)}
|
||||
url="/api/v1/discover/movies"
|
||||
linkUrl="/discover/movies"
|
||||
/>
|
||||
<MovieGenreSlider />
|
||||
<MediaSlider
|
||||
sliderKey="upcoming"
|
||||
title={intl.formatMessage(messages.upcoming)}
|
||||
linkUrl="/discover/movies/upcoming"
|
||||
url="/api/v1/discover/movies/upcoming"
|
||||
/>
|
||||
<StudioSlider />
|
||||
<MediaSlider
|
||||
sliderKey="popular-tv"
|
||||
title={intl.formatMessage(messages.populartv)}
|
||||
url="/api/v1/discover/tv"
|
||||
linkUrl="/discover/tv"
|
||||
/>
|
||||
<TvGenreSlider />
|
||||
<MediaSlider
|
||||
sliderKey="upcoming-tv"
|
||||
title={intl.formatMessage(messages.upcomingtv)}
|
||||
url="/api/v1/discover/tv/upcoming"
|
||||
linkUrl="/discover/tv/upcoming"
|
||||
/>
|
||||
<NetworkSlider />
|
||||
);
|
||||
case DiscoverSliderType.POPULAR_MOVIES:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey="popular-movies"
|
||||
title={intl.formatMessage(sliderTitles.popularmovies)}
|
||||
url="/api/v1/discover/movies"
|
||||
linkUrl="/discover/movies"
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.MOVIE_GENRES:
|
||||
return <MovieGenreSlider />;
|
||||
case DiscoverSliderType.UPCOMING_MOVIES:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey="upcoming"
|
||||
title={intl.formatMessage(sliderTitles.upcoming)}
|
||||
linkUrl="/discover/movies/upcoming"
|
||||
url="/api/v1/discover/movies/upcoming"
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.STUDIOS:
|
||||
return <StudioSlider />;
|
||||
case DiscoverSliderType.POPULAR_TV:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey="popular-tv"
|
||||
title={intl.formatMessage(sliderTitles.populartv)}
|
||||
url="/api/v1/discover/tv"
|
||||
linkUrl="/discover/tv"
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.TV_GENRES:
|
||||
return <TvGenreSlider />;
|
||||
case DiscoverSliderType.UPCOMING_TV:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey="upcoming-tv"
|
||||
title={intl.formatMessage(sliderTitles.upcomingtv)}
|
||||
url="/api/v1/discover/tv/upcoming"
|
||||
linkUrl="/discover/tv/upcoming"
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.NETWORKS:
|
||||
return <NetworkSlider />;
|
||||
case DiscoverSliderType.TMDB_MOVIE_KEYWORD:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey={`custom-slider-${slider.id}`}
|
||||
title={slider.title ?? ''}
|
||||
url="/api/v1/discover/movies"
|
||||
extraParams={
|
||||
slider.data
|
||||
? `keywords=${encodeURIExtraParams(slider.data)}`
|
||||
: ''
|
||||
}
|
||||
linkUrl={`/discover/movies/keyword?keywords=${slider.data}`}
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.TMDB_TV_KEYWORD:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey={`custom-slider-${slider.id}`}
|
||||
title={slider.title ?? ''}
|
||||
url="/api/v1/discover/tv"
|
||||
extraParams={
|
||||
slider.data
|
||||
? `keywords=${encodeURIExtraParams(slider.data)}`
|
||||
: ''
|
||||
}
|
||||
linkUrl={`/discover/tv/keyword?keywords=${slider.data}`}
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.TMDB_MOVIE_GENRE:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey={`custom-slider-${slider.id}`}
|
||||
title={slider.title ?? ''}
|
||||
url={`/api/v1/discover/movies/genre/${slider.data}`}
|
||||
linkUrl={`/discover/movies/genre/${slider.data}`}
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.TMDB_TV_GENRE:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey={`custom-slider-${slider.id}`}
|
||||
title={slider.title ?? ''}
|
||||
url={`/api/v1/discover/tv/genre/${slider.data}`}
|
||||
linkUrl={`/discover/tv/genre/${slider.data}`}
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.TMDB_STUDIO:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey={`custom-slider-${slider.id}`}
|
||||
title={slider.title ?? ''}
|
||||
url={`/api/v1/discover/movies/studio/${slider.data}`}
|
||||
linkUrl={`/discover/movies/studio/${slider.data}`}
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.TMDB_NETWORK:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey={`custom-slider-${slider.id}`}
|
||||
title={slider.title ?? ''}
|
||||
url={`/api/v1/discover/tv/network/${slider.data}`}
|
||||
linkUrl={`/discover/tv/network/${slider.data}`}
|
||||
/>
|
||||
);
|
||||
case DiscoverSliderType.TMDB_SEARCH:
|
||||
return (
|
||||
<MediaSlider
|
||||
sliderKey={`custom-slider-${slider.id}`}
|
||||
title={slider.title ?? ''}
|
||||
url="/api/v1/search"
|
||||
extraParams={`query=${slider.data}`}
|
||||
linkUrl={`/search?query=${slider.data}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user