-
-
Notifications
You must be signed in to change notification settings - Fork 407
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(frontend): discover tv/movies full page
Also adds ListView component for infinite scrolling pages
- Loading branch information
Showing
10 changed files
with
260 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React from 'react'; | ||
import { | ||
TvResult, | ||
MovieResult, | ||
PersonResult, | ||
} from '../../../../server/models/Search'; | ||
import TitleCard from '../../TitleCard'; | ||
import useVerticalScroll from '../../../hooks/useVerticalScroll'; | ||
|
||
interface ListViewProps { | ||
items?: (TvResult | MovieResult | PersonResult)[]; | ||
isEmpty?: boolean; | ||
isLoading?: boolean; | ||
onScrollBottom: () => void; | ||
} | ||
|
||
const ListView: React.FC<ListViewProps> = ({ | ||
items, | ||
isEmpty, | ||
isLoading, | ||
onScrollBottom, | ||
}) => { | ||
useVerticalScroll(onScrollBottom, !isLoading); | ||
return ( | ||
<> | ||
{isEmpty && ( | ||
<div className="w-full mt-64 text-2xl text-center text-cool-gray-400"> | ||
No Results | ||
</div> | ||
)} | ||
<ul className="grid grid-cols-2 gap-6 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5"> | ||
{items?.map((title) => { | ||
let titleCard: React.ReactNode; | ||
|
||
switch (title.mediaType) { | ||
case 'movie': | ||
titleCard = ( | ||
<TitleCard | ||
id={title.id} | ||
image={title.posterPath} | ||
status={title.request?.status} | ||
summary={title.overview} | ||
title={title.title} | ||
userScore={title.voteAverage} | ||
year={title.releaseDate} | ||
mediaType={title.mediaType} | ||
requestId={title.request?.id} | ||
/> | ||
); | ||
break; | ||
case 'tv': | ||
titleCard = ( | ||
<TitleCard | ||
id={title.id} | ||
image={title.posterPath} | ||
status={title.request?.status} | ||
summary={title.overview} | ||
title={title.name} | ||
userScore={title.voteAverage} | ||
year={title.firstAirDate} | ||
mediaType={title.mediaType} | ||
requestId={title.request?.id} | ||
/> | ||
); | ||
break; | ||
case 'person': | ||
titleCard = <div>{title.name}</div>; | ||
break; | ||
} | ||
|
||
return ( | ||
<li | ||
key={title.id} | ||
className="col-span-1 flex flex-col text-center items-center" | ||
> | ||
{titleCard} | ||
</li> | ||
); | ||
})} | ||
{isLoading && | ||
[...Array(10)].map((_item, i) => ( | ||
<li | ||
key={`placeholder-${i}`} | ||
className="col-span-1 flex flex-col text-center items-center" | ||
> | ||
<TitleCard.Placeholder /> | ||
</li> | ||
))} | ||
</ul> | ||
</> | ||
); | ||
}; | ||
|
||
export default ListView; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import React from 'react'; | ||
import { useSWRInfinite } from 'swr'; | ||
import { MovieResult } from '../../../server/models/Search'; | ||
import ListView from '../Common/ListView'; | ||
|
||
interface SearchResult { | ||
page: number; | ||
totalResults: number; | ||
totalPages: number; | ||
results: MovieResult[]; | ||
} | ||
|
||
const DiscoverMovies: React.FC = () => { | ||
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?page=${pageIndex + 1}`; | ||
}, | ||
{ | ||
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[] | ||
); | ||
|
||
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"> | ||
Discover Movies | ||
</h2> | ||
</div> | ||
</div> | ||
<ListView | ||
items={titles} | ||
isEmpty={!isLoadingInitialData && titles?.length === 0} | ||
isLoading={ | ||
isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0) | ||
} | ||
onScrollBottom={fetchMore} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
export default DiscoverMovies; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import React from 'react'; | ||
import { useSWRInfinite } from 'swr'; | ||
import { TvResult } from '../../../server/models/Search'; | ||
import ListView from '../Common/ListView'; | ||
|
||
interface SearchResult { | ||
page: number; | ||
totalResults: number; | ||
totalPages: number; | ||
results: TvResult[]; | ||
} | ||
|
||
const DiscoverTv: React.FC = () => { | ||
const { data, error, size, setSize } = useSWRInfinite<SearchResult>( | ||
(pageIndex: number, previousPageData: SearchResult | null) => { | ||
if (previousPageData && pageIndex + 1 > previousPageData.totalPages) { | ||
return null; | ||
} | ||
|
||
return `/api/v1/discover/tv?page=${pageIndex + 1}`; | ||
}, | ||
{ | ||
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 TvResult[]); | ||
|
||
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"> | ||
Discover Series | ||
</h2> | ||
</div> | ||
</div> | ||
<ListView | ||
items={titles} | ||
isEmpty={!isLoadingInitialData && titles?.length === 0} | ||
isLoading={ | ||
isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0) | ||
} | ||
onScrollBottom={fetchMore} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
export default DiscoverTv; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from 'react'; | ||
import { NextPage } from 'next'; | ||
import DiscoverMovies from '../../components/Discover/DiscoverMovies'; | ||
|
||
const DiscoverMoviesPage: NextPage = () => { | ||
return <DiscoverMovies />; | ||
}; | ||
|
||
export default DiscoverMoviesPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from 'react'; | ||
import { NextPage } from 'next'; | ||
import DiscoverTv from '../../components/Discover/DiscoverTv'; | ||
|
||
const DiscoverMoviesPage: NextPage = () => { | ||
return <DiscoverTv />; | ||
}; | ||
|
||
export default DiscoverMoviesPage; |