From 587e8db15e9c19b4c58406e3e4215d8bf87d8762 Mon Sep 17 00:00:00 2001 From: sct Date: Sun, 17 Jan 2021 08:23:34 +0000 Subject: [PATCH] feat(frontend): add see more card to media sliders --- .../MediaSlider/ShowMoreCard/index.tsx | 104 ++++++++++++++++ src/components/MediaSlider/index.tsx | 114 +++++++++++------- 2 files changed, 177 insertions(+), 41 deletions(-) create mode 100644 src/components/MediaSlider/ShowMoreCard/index.tsx diff --git a/src/components/MediaSlider/ShowMoreCard/index.tsx b/src/components/MediaSlider/ShowMoreCard/index.tsx new file mode 100644 index 000000000..169675c03 --- /dev/null +++ b/src/components/MediaSlider/ShowMoreCard/index.tsx @@ -0,0 +1,104 @@ +import Link from 'next/link'; +import React, { useState } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +const messages = defineMessages({ + seemore: 'See More', +}); + +interface ShowMoreCardProps { + url: string; + posters: (string | undefined)[]; +} + +const ShowMoreCard: React.FC = ({ url, posters }) => { + const intl = useIntl(); + const [isHovered, setHovered] = useState(false); + return ( + + { + setHovered(true); + }} + onMouseLeave={() => setHovered(false)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + setHovered(true); + } + }} + role="link" + tabIndex={0} + > +
+
+
+
+ {posters[0] && ( +
+ +
+ )} + {posters[1] && ( +
+ +
+ )} + {posters[2] && ( +
+ +
+ )} + {posters[3] && ( +
+ +
+ )} +
+
+ + + +
+ {intl.formatMessage(messages.seemore)} +
+
+
+
+
+
+ + ); +}; + +export default ShowMoreCard; diff --git a/src/components/MediaSlider/index.tsx b/src/components/MediaSlider/index.tsx index 6640f5863..5df3f490c 100644 --- a/src/components/MediaSlider/index.tsx +++ b/src/components/MediaSlider/index.tsx @@ -1,6 +1,6 @@ import Link from 'next/link'; import React, { useContext } from 'react'; -import useSWR from 'swr'; +import { useSWRInfinite } from 'swr'; import type { MovieResult, PersonResult, @@ -10,6 +10,7 @@ import { LanguageContext } from '../../context/LanguageContext'; import PersonCard from '../PersonCard'; import Slider from '../Slider'; import TitleCard from '../TitleCard'; +import ShowMoreCard from './ShowMoreCard'; interface MixedResult { page: number; @@ -34,12 +35,80 @@ const MediaSlider: React.FC = ({ hideWhenEmpty = false, }) => { const { locale } = useContext(LanguageContext); - const { data, error } = useSWR(`${url}?language=${locale}`); + const { data, error } = useSWRInfinite( + (pageIndex: number, previousPageData: MixedResult | null) => { + if (previousPageData && pageIndex + 1 > previousPageData.totalPages) { + return null; + } - if (hideWhenEmpty && (data?.results ?? []).length === 0) { + return `${url}?page=${pageIndex + 1}&language=${locale}`; + }, + { + initialSize: 2, + } + ); + + if (hideWhenEmpty && (data?.[0].results ?? []).length === 0) { return null; } + const titles = (data ?? []).reduce( + (a, v) => [...a, ...v.results], + [] as (MovieResult | TvResult | PersonResult)[] + ); + + const finalTitles = titles.slice(0, 20).map((title) => { + switch (title.mediaType) { + case 'movie': + return ( + + ); + case 'tv': + return ( + + ); + case 'person': + return ( + + ); + } + }); + + if (linkUrl && titles.length > 20) { + finalTitles.push( + + title.mediaType !== 'person' ? title.posterPath : undefined + )} + /> + ); + } + return ( <>
@@ -75,44 +144,7 @@ const MediaSlider: React.FC = ({ sliderKey={sliderKey} isLoading={!data && !error} isEmpty={false} - items={data?.results.map((title) => { - switch (title.mediaType) { - case 'movie': - return ( - - ); - case 'tv': - return ( - - ); - case 'person': - return ( - - ); - } - })} + items={finalTitles} /> );