feat: upcoming/trending list views and larger title cards

This commit is contained in:
sct
2020-11-17 09:18:45 +00:00
parent 185ac2648f
commit 94eaaf96b4
17 changed files with 457 additions and 219 deletions

View File

@@ -4,9 +4,10 @@ import type { MovieResult } from '../../../server/models/Search';
import ListView from '../Common/ListView';
import { LanguageContext } from '../../context/LanguageContext';
import { defineMessages, FormattedMessage } from 'react-intl';
import Header from '../Common/Header';
const messages = defineMessages({
discovermovies: 'Discover Movies',
discovermovies: 'Popular Movies',
});
interface SearchResult {
@@ -55,13 +56,9 @@ const DiscoverMovies: React.FC = () => {
return (
<>
<div className="md:flex md:items-center md:justify-between mb-8 mt-6">
<div className="flex-1 min-w-0">
<h2 className="text-xl leading-7 text-white sm:text-2xl sm:leading-9 sm:truncate">
<FormattedMessage {...messages.discovermovies} />
</h2>
</div>
</div>
<Header>
<FormattedMessage {...messages.discovermovies} />
</Header>
<ListView
items={titles}
isEmpty={isEmpty}

View File

@@ -1,12 +1,13 @@
import React, { useContext } from 'react';
import { useSWRInfinite } from 'swr';
import { TvResult } from '../../../server/models/Search';
import type { TvResult } from '../../../server/models/Search';
import ListView from '../Common/ListView';
import { defineMessages, FormattedMessage } from 'react-intl';
import { LanguageContext } from '../../context/LanguageContext';
import Header from '../Common/Header';
const messages = defineMessages({
discovertv: 'Discover Series',
discovertv: 'Popular Series',
});
interface SearchResult {
@@ -52,13 +53,9 @@ const DiscoverTv: React.FC = () => {
return (
<>
<div className="md:flex md:items-center md:justify-between mb-8 mt-6">
<div className="flex-1 min-w-0">
<h2 className="text-xl leading-7 text-white sm:text-2xl sm:leading-9 sm:truncate">
<FormattedMessage {...messages.discovertv} />
</h2>
</div>
</div>
<Header>
<FormattedMessage {...messages.discovertv} />
</Header>
<ListView
items={titles}
isEmpty={isEmpty}

View File

@@ -0,0 +1,81 @@
import React, { useContext } from 'react';
import { useSWRInfinite } from 'swr';
import type {
MovieResult,
TvResult,
PersonResult,
} from '../../../server/models/Search';
import ListView from '../Common/ListView';
import { LanguageContext } from '../../context/LanguageContext';
import { defineMessages, FormattedMessage } from 'react-intl';
import Header from '../Common/Header';
const messages = defineMessages({
trending: 'Trending',
});
interface SearchResult {
page: number;
totalResults: number;
totalPages: number;
results: (MovieResult | TvResult | PersonResult)[];
}
const Trending: React.FC = () => {
const { locale } = useContext(LanguageContext);
const { data, error, size, setSize } = useSWRInfinite<SearchResult>(
(pageIndex: number, previousPageData: SearchResult | null) => {
if (previousPageData && pageIndex + 1 > previousPageData.totalPages) {
return null;
}
return `/api/v1/discover/trending?page=${
pageIndex + 1
}&language=${locale}`;
},
{
initialSize: 3,
}
);
const isLoadingInitialData = !data && !error;
const isLoadingMore =
isLoadingInitialData ||
(size > 0 && data && typeof data[size - 1] === 'undefined');
const fetchMore = () => {
setSize(size + 1);
};
if (error) {
return <div>{error}</div>;
}
const titles = data?.reduce(
(a, v) => [...a, ...v.results],
[] as (MovieResult | TvResult | PersonResult)[]
);
const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
isEmpty || (data && data[data.length - 1]?.results.length < 20);
return (
<>
<Header>
<FormattedMessage {...messages.trending} />
</Header>
<ListView
items={titles}
isEmpty={isEmpty}
isLoading={
isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0)
}
isReachingEnd={isReachingEnd}
onScrollBottom={fetchMore}
/>
</>
);
};
export default Trending;

View File

@@ -0,0 +1,77 @@
import React, { useContext } from 'react';
import { useSWRInfinite } from 'swr';
import type { MovieResult } from '../../../server/models/Search';
import ListView from '../Common/ListView';
import { LanguageContext } from '../../context/LanguageContext';
import { defineMessages, FormattedMessage } from 'react-intl';
import Header from '../Common/Header';
const messages = defineMessages({
upcomingmovies: 'Upcoming Movies',
});
interface SearchResult {
page: number;
totalResults: number;
totalPages: number;
results: MovieResult[];
}
const UpcomingMovies: React.FC = () => {
const { locale } = useContext(LanguageContext);
const { data, error, size, setSize } = useSWRInfinite<SearchResult>(
(pageIndex: number, previousPageData: SearchResult | null) => {
if (previousPageData && pageIndex + 1 > previousPageData.totalPages) {
return null;
}
return `/api/v1/discover/movies/upcoming?page=${
pageIndex + 1
}&language=${locale}`;
},
{
initialSize: 3,
}
);
const isLoadingInitialData = !data && !error;
const isLoadingMore =
isLoadingInitialData ||
(size > 0 && data && typeof data[size - 1] === 'undefined');
const fetchMore = () => {
setSize(size + 1);
};
if (error) {
return <div>{error}</div>;
}
const titles = data?.reduce(
(a, v) => [...a, ...v.results],
[] as MovieResult[]
);
const isEmpty = !isLoadingInitialData && titles?.length === 0;
const isReachingEnd =
isEmpty || (data && data[data.length - 1]?.results.length < 20);
return (
<>
<Header>
<FormattedMessage {...messages.upcomingmovies} />
</Header>
<ListView
items={titles}
isEmpty={isEmpty}
isLoading={
isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0)
}
isReachingEnd={isReachingEnd}
onScrollBottom={fetchMore}
/>
</>
);
};
export default UpcomingMovies;

View File

@@ -77,27 +77,11 @@ const Discover: React.FC = () => {
<>
<div className="md:flex md:items-center md:justify-between mb-4 mt-6">
<div className="flex-1 min-w-0">
<Link href="/recent">
<a className="inline-flex text-xl leading-7 text-cool-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate items-center">
<span>
<FormattedMessage {...messages.recentlyAdded} />
</span>
<svg
className="w-6 h-6 ml-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</a>
</Link>
<div className="inline-flex text-xl leading-7 text-cool-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate items-center">
<span>
<FormattedMessage {...messages.recentlyAdded} />
</span>
</div>
</div>
</div>
<Slider