Pagination for videos
This commit is contained in:
parent
1db24083cb
commit
572cbb57d5
src
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 AppLayout from "components/AppLayout";
|
||||||
|
import PageSelector from "components/PageSelector";
|
||||||
import PanelHeader from "components/PanelComponents/PanelHeader";
|
import PanelHeader from "components/PanelComponents/PanelHeader";
|
||||||
import ReturnButton, {
|
import ReturnButton, {
|
||||||
ReturnButtonType,
|
ReturnButtonType,
|
||||||
@ -12,6 +13,8 @@ import { GetVideosPreviewQuery } from "graphql/generated";
|
|||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import { prettyDate } from "queries/helpers";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
videos: Exclude<GetVideosPreviewQuery["videos"], null | undefined>["data"];
|
videos: Exclude<GetVideosPreviewQuery["videos"], null | undefined>["data"];
|
||||||
@ -19,6 +22,29 @@ interface Props extends AppStaticProps {
|
|||||||
|
|
||||||
export default function Videos(props: Props): JSX.Element {
|
export default function Videos(props: Props): JSX.Element {
|
||||||
const { langui, videos } = props;
|
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 = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
<ReturnButton
|
<ReturnButton
|
||||||
@ -39,11 +65,29 @@ export default function Videos(props: Props): JSX.Element {
|
|||||||
|
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
<ContentPanel width={ContentPanelWidthSizes.large}>
|
<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">
|
<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) => (
|
{paginatedVideos[page].map((video) => (
|
||||||
<>{video.attributes && <VideoPreview video={video.attributes} />}</>
|
<>
|
||||||
|
{video.attributes && (
|
||||||
|
<VideoPreview key={video.id} video={video.attributes} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<PageSelector
|
||||||
|
maxPage={Math.floor(videos.length / itemPerPage)}
|
||||||
|
page={page}
|
||||||
|
setPage={setPage}
|
||||||
|
className="mt-12"
|
||||||
|
/>
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user