Pagination for videos
This commit is contained in:
parent
1db24083cb
commit
572cbb57d5
39
src/components/PageSelector.tsx
Normal file
39
src/components/PageSelector.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import Button from "./Button";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
maxPage: number;
|
||||
page: number;
|
||||
setPage: Dispatch<SetStateAction<number>>;
|
||||
};
|
||||
|
||||
export default function PageSelector(props: Props): JSX.Element {
|
||||
const { page, setPage, maxPage } = props;
|
||||
|
||||
return (
|
||||
<div className={`flex place-content-center flex-row ${props.className}`}>
|
||||
<Button className="rounded-r-none">
|
||||
<span
|
||||
onClick={() => {
|
||||
if (page > 0) setPage(page - 1);
|
||||
}}
|
||||
className="material-icons"
|
||||
>
|
||||
navigate_before
|
||||
</span>
|
||||
</Button>
|
||||
<Button className="rounded-none border-x-0">{page + 1}</Button>
|
||||
<Button className="rounded-l-none">
|
||||
<span
|
||||
onClick={() => {
|
||||
if (page < maxPage) setPage(page + 1);
|
||||
}}
|
||||
className="material-icons"
|
||||
>
|
||||
navigate_next
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import AppLayout from "components/AppLayout";
|
||||
import PageSelector from "components/PageSelector";
|
||||
import PanelHeader from "components/PanelComponents/PanelHeader";
|
||||
import ReturnButton, {
|
||||
ReturnButtonType,
|
||||
@ -12,6 +13,8 @@ import { GetVideosPreviewQuery } from "graphql/generated";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import { GetStaticPropsContext } from "next";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import { prettyDate } from "queries/helpers";
|
||||
import { useState } from "react";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
videos: Exclude<GetVideosPreviewQuery["videos"], null | undefined>["data"];
|
||||
@ -19,6 +22,29 @@ interface Props extends AppStaticProps {
|
||||
|
||||
export default function Videos(props: Props): JSX.Element {
|
||||
const { langui, videos } = props;
|
||||
|
||||
videos
|
||||
.sort((a, b) => {
|
||||
const dateA = a.attributes?.published_date
|
||||
? prettyDate(a.attributes.published_date)
|
||||
: "9999";
|
||||
const dateB = b.attributes?.published_date
|
||||
? prettyDate(b.attributes.published_date)
|
||||
: "9999";
|
||||
return dateA.localeCompare(dateB);
|
||||
})
|
||||
.reverse();
|
||||
|
||||
const itemPerPage = 50;
|
||||
const paginatedVideos: Props["videos"][] = [];
|
||||
for (let index = 0; itemPerPage * index < videos.length; index += 1) {
|
||||
paginatedVideos.push(
|
||||
videos.slice(index * itemPerPage, (index + 1) * itemPerPage)
|
||||
);
|
||||
}
|
||||
|
||||
const [page, setPage] = useState(0);
|
||||
|
||||
const subPanel = (
|
||||
<SubPanel>
|
||||
<ReturnButton
|
||||
@ -39,11 +65,29 @@ export default function Videos(props: Props): JSX.Element {
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.large}>
|
||||
<PageSelector
|
||||
maxPage={Math.floor(videos.length / itemPerPage)}
|
||||
page={page}
|
||||
setPage={setPage}
|
||||
className="mb-12"
|
||||
/>
|
||||
|
||||
<div className="grid gap-8 items-start mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0">
|
||||
{videos.map((video) => (
|
||||
<>{video.attributes && <VideoPreview video={video.attributes} />}</>
|
||||
{paginatedVideos[page].map((video) => (
|
||||
<>
|
||||
{video.attributes && (
|
||||
<VideoPreview key={video.id} video={video.attributes} />
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<PageSelector
|
||||
maxPage={Math.floor(videos.length / itemPerPage)}
|
||||
page={page}
|
||||
setPage={setPage}
|
||||
className="mt-12"
|
||||
/>
|
||||
</ContentPanel>
|
||||
);
|
||||
return (
|
||||
|
Loading…
x
Reference in New Issue
Block a user