Multi-file games lists, clicking a game leads to mod search for that game, search redirects, pagination optimizations #38
@ -38,3 +38,101 @@ export const Pagination = React.memo(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PaginationWithPageNumbersProps = {
|
||||||
|
currentPage: number
|
||||||
|
totalPages: number
|
||||||
|
handlePageChange: (page: number) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PaginationWithPageNumbers = ({
|
||||||
|
currentPage,
|
||||||
|
totalPages,
|
||||||
|
handlePageChange
|
||||||
|
}: PaginationWithPageNumbersProps) => {
|
||||||
|
// Function to render the pagination controls with page numbers
|
||||||
|
const renderPagination = () => {
|
||||||
|
const pagesToShow = 5 // Number of page numbers to show around the current page
|
||||||
|
const pageNumbers: (number | string)[] = [] // Array to store page numbers and ellipses
|
||||||
|
|
||||||
|
// Case when the total number of pages is less than or equal to the limit
|
||||||
|
if (totalPages <= pagesToShow + 2) {
|
||||||
|
for (let i = 1; i <= totalPages; i++) {
|
||||||
|
pageNumbers.push(i) // Add all pages to the pagination
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Add the first page (always visible)
|
||||||
|
pageNumbers.push(1)
|
||||||
|
|
||||||
|
// Calculate the range of pages to show around the current page
|
||||||
|
const startPage = Math.max(2, currentPage - Math.floor(pagesToShow / 2))
|
||||||
|
const endPage = Math.min(
|
||||||
|
totalPages - 1,
|
||||||
|
currentPage + Math.floor(pagesToShow / 2)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add ellipsis if there are pages between the first page and the startPage
|
||||||
|
if (startPage > 2) pageNumbers.push('...')
|
||||||
|
|
||||||
|
// Add the pages around the current page
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
pageNumbers.push(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add ellipsis if there are pages between the endPage and the last page
|
||||||
|
if (endPage < totalPages - 1) pageNumbers.push('...')
|
||||||
|
|
||||||
|
// Add the last page (always visible)
|
||||||
|
pageNumbers.push(totalPages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map over the array and render each page number or ellipsis
|
||||||
|
return pageNumbers.map((page, index) => {
|
||||||
|
if (typeof page === 'number') {
|
||||||
|
// For actual page numbers, render clickable boxes
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`PaginationMainInsideBox ${
|
||||||
|
currentPage === page ? 'PMIBActive' : '' // Highlight the current page
|
||||||
|
}`}
|
||||||
|
onClick={() => handlePageChange(page)} // Navigate to the selected page
|
||||||
|
>
|
||||||
|
<p>{page}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// For ellipses, render non-clickable dots
|
||||||
|
return (
|
||||||
|
<p key={index} className='PaginationMainInsideBox PMIBDots'>
|
||||||
|
...
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='IBMSecMain'>
|
||||||
|
<div className='PaginationMain'>
|
||||||
|
<div className='PaginationMainInside'>
|
||||||
|
<div
|
||||||
|
className='PaginationMainInsideBox PaginationMainInsideBoxArrows'
|
||||||
|
onClick={() => handlePageChange(currentPage - 1)}
|
||||||
|
>
|
||||||
|
<i className='fas fa-chevron-left'></i>
|
||||||
|
</div>
|
||||||
|
<div className='PaginationMainInsideBoxGroup'>
|
||||||
|
{renderPagination()}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className='PaginationMainInsideBox PaginationMainInsideBoxArrows'
|
||||||
|
onClick={() => handlePageChange(currentPage + 1)}
|
||||||
|
>
|
||||||
|
<i className='fas fa-chevron-right'></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -1,9 +1,29 @@
|
|||||||
import '../styles/pagination.css'
|
import { PaginationWithPageNumbers } from 'components/Pagination'
|
||||||
import '../styles/styles.css'
|
import { MAX_GAMES_PER_PAGE } from 'constants.ts'
|
||||||
import '../styles/search.css'
|
import { useGames } from 'hooks'
|
||||||
|
import { useState } from 'react'
|
||||||
import { GameCard } from '../components/GameCard'
|
import { GameCard } from '../components/GameCard'
|
||||||
|
import '../styles/pagination.css'
|
||||||
|
import '../styles/search.css'
|
||||||
|
import '../styles/styles.css'
|
||||||
|
|
||||||
export const GamesPage = () => {
|
export const GamesPage = () => {
|
||||||
|
const games = useGames()
|
||||||
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
|
|
||||||
|
// Pagination logic
|
||||||
|
const totalGames = games.length
|
||||||
|
const totalPages = Math.ceil(totalGames / MAX_GAMES_PER_PAGE)
|
||||||
|
const startIndex = (currentPage - 1) * MAX_GAMES_PER_PAGE
|
||||||
|
const endIndex = startIndex + MAX_GAMES_PER_PAGE
|
||||||
|
const currentGames = games.slice(startIndex, endIndex)
|
||||||
|
|
||||||
|
const handlePageChange = (page: number) => {
|
||||||
|
if (page >= 1 && page <= totalPages) {
|
||||||
|
setCurrentPage(page)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='InnerBodyMain'>
|
<div className='InnerBodyMain'>
|
||||||
<div className='ContainerMain'>
|
<div className='ContainerMain'>
|
||||||
@ -11,7 +31,7 @@ export const GamesPage = () => {
|
|||||||
<div className='IBMSecMain'>
|
<div className='IBMSecMain'>
|
||||||
<div className='SearchMainWrapper'>
|
<div className='SearchMainWrapper'>
|
||||||
<div className='IBMSMTitleMain'>
|
<div className='IBMSMTitleMain'>
|
||||||
<h2 className='IBMSMTitleMainHeading'>Games (WIP)</h2>
|
<h2 className='IBMSMTitleMainHeading'>Games</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className='SearchMain'>
|
<div className='SearchMain'>
|
||||||
<div className='SearchMainInside'>
|
<div className='SearchMainInside'>
|
||||||
@ -35,61 +55,20 @@ export const GamesPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className='IBMSecMain IBMSMListWrapper'>
|
<div className='IBMSecMain IBMSMListWrapper'>
|
||||||
<div className='IBMSMList IBMSMListFeaturedAlt'>
|
<div className='IBMSMList IBMSMListFeaturedAlt'>
|
||||||
<GameCard
|
{currentGames.map((game) => (
|
||||||
title='This is a game title, the best game title'
|
<GameCard
|
||||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
key={game['Game Name']}
|
||||||
/>
|
title={game['Game Name']}
|
||||||
<GameCard
|
imageUrl={game['Boxart image']}
|
||||||
title='This is a game title, the best game title'
|
/>
|
||||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
))}
|
||||||
/>
|
|
||||||
<GameCard
|
|
||||||
title='This is a game title, the best game title'
|
|
||||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
|
||||||
/>
|
|
||||||
<GameCard
|
|
||||||
title='This is a game title, the best game title'
|
|
||||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
|
||||||
/>
|
|
||||||
<GameCard
|
|
||||||
title='This is a game title, the best game title'
|
|
||||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='IBMSecMain'>
|
|
||||||
<div className='PaginationMain'>
|
|
||||||
<div className='PaginationMainInside'>
|
|
||||||
<a
|
|
||||||
className='PaginationMainInsideBox PaginationMainInsideBoxArrows'
|
|
||||||
href='#'
|
|
||||||
>
|
|
||||||
<i className='fas fa-chevron-left'></i>
|
|
||||||
</a>
|
|
||||||
<div className='PaginationMainInsideBoxGroup'>
|
|
||||||
<a className='PaginationMainInsideBox PMIBActive' href='#'>
|
|
||||||
<p>1</p>{' '}
|
|
||||||
</a>
|
|
||||||
<a className='PaginationMainInsideBox' href='#'>
|
|
||||||
<p>2</p>{' '}
|
|
||||||
</a>
|
|
||||||
<a className='PaginationMainInsideBox' href='#'>
|
|
||||||
<p>3</p>
|
|
||||||
</a>
|
|
||||||
<p className='PaginationMainInsideBox PMIBDots'>...</p>
|
|
||||||
<a className='PaginationMainInsideBox' href='#'>
|
|
||||||
<p>8</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
className='PaginationMainInsideBox PaginationMainInsideBoxArrows'
|
|
||||||
href='#'
|
|
||||||
>
|
|
||||||
<i className='fas fa-chevron-right'></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<PaginationWithPageNumbers
|
||||||
|
currentPage={currentPage}
|
||||||
|
totalPages={totalPages}
|
||||||
|
handlePageChange={handlePageChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user