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 '../styles/styles.css'
|
||||
import '../styles/search.css'
|
||||
import { PaginationWithPageNumbers } from 'components/Pagination'
|
||||
import { MAX_GAMES_PER_PAGE } from 'constants.ts'
|
||||
import { useGames } from 'hooks'
|
||||
import { useState } from 'react'
|
||||
import { GameCard } from '../components/GameCard'
|
||||
import '../styles/pagination.css'
|
||||
import '../styles/search.css'
|
||||
import '../styles/styles.css'
|
||||
|
||||
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 (
|
||||
<div className='InnerBodyMain'>
|
||||
<div className='ContainerMain'>
|
||||
@ -11,7 +31,7 @@ export const GamesPage = () => {
|
||||
<div className='IBMSecMain'>
|
||||
<div className='SearchMainWrapper'>
|
||||
<div className='IBMSMTitleMain'>
|
||||
<h2 className='IBMSMTitleMainHeading'>Games (WIP)</h2>
|
||||
<h2 className='IBMSMTitleMainHeading'>Games</h2>
|
||||
</div>
|
||||
<div className='SearchMain'>
|
||||
<div className='SearchMainInside'>
|
||||
@ -35,61 +55,20 @@ export const GamesPage = () => {
|
||||
</div>
|
||||
<div className='IBMSecMain IBMSMListWrapper'>
|
||||
<div className='IBMSMList IBMSMListFeaturedAlt'>
|
||||
{currentGames.map((game) => (
|
||||
<GameCard
|
||||
title='This is a game title, the best game title'
|
||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
key={game['Game Name']}
|
||||
title={game['Game Name']}
|
||||
imageUrl={game['Boxart image']}
|
||||
/>
|
||||
<GameCard
|
||||
title='This is a game title, the best game title'
|
||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<PaginationWithPageNumbers
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
handlePageChange={handlePageChange}
|
||||
/>
|
||||
<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>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user