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
	 DrMint
						DrMint