Skip to content

Commit 5b44072

Browse files
committed
feat(trending): add filter options
Added new filter options on the trending page to allow users to sort content by mediaType and select trending-scope.
1 parent 5978587 commit 5b44072

File tree

5 files changed

+149
-4
lines changed

5 files changed

+149
-4
lines changed

seerr-api.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5844,6 +5844,23 @@ paths:
58445844
schema:
58455845
type: string
58465846
example: en
5847+
- in: query
5848+
name: mediaType
5849+
schema:
5850+
type: string
5851+
enum:
5852+
- all
5853+
- movie
5854+
- tv
5855+
default: all
5856+
- in: query
5857+
name: timeWindow
5858+
schema:
5859+
type: string
5860+
enum:
5861+
- day
5862+
- week
5863+
default: day
58475864
responses:
58485865
'200':
58495866
description: Results

server/api/themoviedb/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,16 +715,19 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
715715
public getMovieTrending = async ({
716716
page = 1,
717717
timeWindow = 'day',
718+
language = this.locale,
718719
}: {
719720
page?: number;
720721
timeWindow?: 'day' | 'week';
722+
language?: string;
721723
} = {}): Promise<TmdbSearchMovieResponse> => {
722724
try {
723725
const data = await this.get<TmdbSearchMovieResponse>(
724726
`/trending/movie/${timeWindow}`,
725727
{
726728
params: {
727729
page,
730+
language,
728731
},
729732
}
730733
);
@@ -738,16 +741,19 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
738741
public getTvTrending = async ({
739742
page = 1,
740743
timeWindow = 'day',
744+
language = this.locale,
741745
}: {
742746
page?: number;
743747
timeWindow?: 'day' | 'week';
748+
language?: string;
744749
} = {}): Promise<TmdbSearchTvResponse> => {
745750
try {
746751
const data = await this.get<TmdbSearchTvResponse>(
747752
`/trending/tv/${timeWindow}`,
748753
{
749754
params: {
750755
page,
756+
language,
751757
},
752758
}
753759
);

server/routes/discover.ts

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,72 @@ discoverRoutes.get('/trending', async (req, res, next) => {
673673
const tmdb = createTmdbWithRegionLanguage(req.user);
674674

675675
try {
676+
const mediaType = (req.query.mediaType as 'all' | 'movie' | 'tv') ?? 'all';
677+
const timeWindow =
678+
(req.query.timeWindow as 'day' | 'week') === 'week' ? 'week' : 'day';
679+
const language = (req.query.language as string) ?? req.locale;
680+
const page = Number(req.query.page);
681+
682+
if (mediaType === 'movie') {
683+
const data = await tmdb.getMovieTrending({
684+
page,
685+
language,
686+
timeWindow,
687+
});
688+
689+
const media = await Media.getRelatedMedia(
690+
req.user,
691+
data.results.map((result) => result.id)
692+
);
693+
694+
return res.status(200).json({
695+
page: data.page,
696+
totalPages: data.total_pages,
697+
totalResults: data.total_results,
698+
results: data.results.map((result) =>
699+
mapMovieResult(
700+
result,
701+
media.find(
702+
(med) =>
703+
med.tmdbId === result.id && med.mediaType === MediaType.MOVIE
704+
)
705+
)
706+
),
707+
});
708+
}
709+
710+
if (mediaType === 'tv') {
711+
const data = await tmdb.getTvTrending({
712+
page,
713+
language,
714+
timeWindow,
715+
});
716+
717+
const media = await Media.getRelatedMedia(
718+
req.user,
719+
data.results.map((result) => result.id)
720+
);
721+
722+
return res.status(200).json({
723+
page: data.page,
724+
totalPages: data.total_pages,
725+
totalResults: data.total_results,
726+
results: data.results.map((result) =>
727+
mapTvResult(
728+
result,
729+
media.find(
730+
(med) =>
731+
med.tmdbId === result.id && med.mediaType === MediaType.TV
732+
)
733+
)
734+
),
735+
});
736+
}
737+
676738
const data = await tmdb.getAllTrending({
677-
page: Number(req.query.page),
678-
language: (req.query.language as string) ?? req.locale,
739+
page,
740+
language,
741+
timeWindow,
679742
});
680743

681744
const media = await Media.getRelatedMedia(

src/components/Discover/Trending.tsx

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,32 @@ import Header from '@app/components/Common/Header';
22
import ListView from '@app/components/Common/ListView';
33
import PageTitle from '@app/components/Common/PageTitle';
44
import useDiscover from '@app/hooks/useDiscover';
5+
import globalMessages from '@app/i18n/globalMessages';
56
import Error from '@app/pages/_error';
67
import defineMessages from '@app/utils/defineMessages';
8+
import { CircleStackIcon, FunnelIcon } from '@heroicons/react/24/solid';
79
import type {
810
MovieResult,
911
PersonResult,
1012
TvResult,
1113
} from '@server/models/Search';
14+
import { useState } from 'react';
1215
import { useIntl } from 'react-intl';
1316

1417
const messages = defineMessages('components.Discover', {
1518
trending: 'Trending',
19+
timeWindowDay: 'Daily',
20+
timeWindowWeek: 'Weekly',
1621
});
1722

23+
type MediaType = 'all' | 'movie' | 'tv';
24+
25+
type TimeWindow = 'day' | 'week';
26+
1827
const Trending = () => {
1928
const intl = useIntl();
29+
const [currentMediaType, setCurrentMediaType] = useState<MediaType>('all');
30+
const [currentTimeWindow, setCurrentTimeWindow] = useState<TimeWindow>('day');
2031
const {
2132
isLoadingInitialData,
2233
isEmpty,
@@ -26,7 +37,8 @@ const Trending = () => {
2637
fetchMore,
2738
error,
2839
} = useDiscover<MovieResult | TvResult | PersonResult>(
29-
'/api/v1/discover/trending'
40+
'/api/v1/discover/trending',
41+
{ mediaType: currentMediaType, timeWindow: currentTimeWindow }
3042
);
3143

3244
if (error) {
@@ -36,8 +48,53 @@ const Trending = () => {
3648
return (
3749
<>
3850
<PageTitle title={intl.formatMessage(messages.trending)} />
39-
<div className="mt-1 mb-5">
51+
<div className="mt-1 mb-5 flex flex-col justify-between lg:flex-row lg:items-end">
4052
<Header>{intl.formatMessage(messages.trending)}</Header>
53+
<div className="mt-2 flex flex-grow flex-col sm:flex-row lg:flex-grow-0">
54+
<div className="mb-2 flex flex-grow sm:mb-0 sm:mr-2 lg:flex-grow-0">
55+
<span className="inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100">
56+
<CircleStackIcon className="h-6 w-6" />
57+
</span>
58+
<select
59+
id="mediaType"
60+
name="mediaType"
61+
onChange={(e) => setCurrentMediaType(e.target.value as MediaType)}
62+
value={currentMediaType}
63+
className="rounded-r-only"
64+
>
65+
<option value="all">
66+
{intl.formatMessage(globalMessages.all)}
67+
</option>
68+
<option value="movie">
69+
{intl.formatMessage(globalMessages.movies)}
70+
</option>
71+
<option value="tv">
72+
{intl.formatMessage(globalMessages.tvshows)}
73+
</option>
74+
</select>
75+
</div>
76+
<div className="mb-2 flex flex-grow sm:mb-0 sm:mr-2 lg:flex-grow-0">
77+
<span className="inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100">
78+
<FunnelIcon className="h-6 w-6" />
79+
</span>
80+
<select
81+
id="timeWindow"
82+
name="timeWindow"
83+
onChange={(e) =>
84+
setCurrentTimeWindow(e.target.value as TimeWindow)
85+
}
86+
value={currentTimeWindow}
87+
className="rounded-r-only"
88+
>
89+
<option value="day">
90+
{intl.formatMessage(messages.timeWindowDay)}
91+
</option>
92+
<option value="week">
93+
{intl.formatMessage(messages.timeWindowWeek)}
94+
</option>
95+
</select>
96+
</div>
97+
</div>
4198
</div>
4299
<ListView
43100
items={titles}

src/i18n/locale/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@
123123
"components.Discover.resetwarning": "Reset all sliders to default. This will also delete any custom sliders!",
124124
"components.Discover.stopediting": "Stop Editing",
125125
"components.Discover.studios": "Studios",
126+
"components.Discover.timeWindowDay": "Daily",
127+
"components.Discover.timeWindowWeek": "Weekly",
126128
"components.Discover.tmdbmoviegenre": "TMDB Movie Genre",
127129
"components.Discover.tmdbmoviekeyword": "TMDB Movie Keyword",
128130
"components.Discover.tmdbmoviestreamingservices": "TMDB Movie Streaming Services",

0 commit comments

Comments
 (0)