degmods.com/src/pages/games.tsx

148 lines
5.3 KiB
TypeScript
Raw Normal View History

2024-09-18 21:41:55 +05:00
import { PaginationWithPageNumbers } from 'components/Pagination'
import { MAX_GAMES_PER_PAGE } from 'constants.ts'
import { useDidMount, useGames } from 'hooks'
import { useMemo, useRef, useState } from 'react'
2024-09-18 21:41:55 +05:00
import { GameCard } from '../components/GameCard'
2024-07-11 17:15:03 +05:00
import '../styles/pagination.css'
import '../styles/search.css'
2024-09-18 21:41:55 +05:00
import '../styles/styles.css'
import { createSearchParams, useNavigate } from 'react-router-dom'
import { appRoutes } from 'routes'
import { fetchMods } from 'utils'
2024-07-11 17:15:03 +05:00
export const GamesPage = () => {
const navigate = useNavigate()
const searchTermRef = useRef<HTMLInputElement>(null)
2024-09-18 21:41:55 +05:00
const games = useGames()
const [gamesWithMods, setGamesWithMods] = useState<string[]>([])
2024-09-18 21:41:55 +05:00
const [currentPage, setCurrentPage] = useState(1)
useDidMount(() => {
fetchMods({ limit: 100, source: window.location.host }).then((mods) => {
mods.sort((a, b) => b.published_at - a.published_at)
const gameNames = new Set<string>()
mods.map((mod) => gameNames.add(mod.game))
setGamesWithMods(Array.from(gameNames))
})
})
const sortedGames = useMemo(() => {
// Create a map for the order array, assigning each game name a rank based on its index.
const orderMap = new Map<string, number>()
gamesWithMods.forEach((gameName, index) => {
orderMap.set(gameName, index)
})
const gamesArray = [...games]
return gamesArray.sort((a, b) => {
const indexA = orderMap.get(a['Game Name'])
const indexB = orderMap.get(b['Game Name'])
// Games that are not in the order array should go after those that are in the array.
if (indexA !== undefined && indexB !== undefined) {
return indexA - indexB
} else if (indexA !== undefined) {
return -1 // a comes before b
} else if (indexB !== undefined) {
return 1 // b comes before a
} else {
return 0 // keep original order if neither is in the array
}
})
}, [games, gamesWithMods])
2024-09-18 21:41:55 +05:00
// Pagination logic
const totalGames = sortedGames.length
2024-09-18 21:41:55 +05:00
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 = sortedGames.slice(startIndex, endIndex)
2024-09-18 21:41:55 +05:00
const handlePageChange = (page: number) => {
if (page >= 1 && page <= totalPages) {
setCurrentPage(page)
}
}
const handleSearch = () => {
const value = searchTermRef.current?.value || '' // Access the input value from the ref
if (value !== '') {
const searchParams = createSearchParams({
searchTerm: value,
searching: 'Games'
})
navigate({ pathname: appRoutes.search, search: `?${searchParams}` })
}
}
// Handle "Enter" key press inside the input
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
handleSearch()
}
}
2024-07-11 17:15:03 +05:00
return (
<div className='InnerBodyMain'>
<div className='ContainerMain'>
<div className='IBMSecMainGroup IBMSecMainGroupAlt'>
<div className='IBMSecMain'>
<div className='SearchMainWrapper'>
<div className='IBMSMTitleMain'>
2024-09-18 21:41:55 +05:00
<h2 className='IBMSMTitleMainHeading'>Games</h2>
2024-07-11 17:15:03 +05:00
</div>
<div className='SearchMain'>
<div className='SearchMainInside'>
<div className='SearchMainInsideWrapper'>
<input
type='text'
className='SMIWInput'
ref={searchTermRef}
onKeyDown={handleKeyDown}
placeholder='Enter search term'
/>
<button
className='btn btnMain SMIWButton'
type='button'
onClick={handleSearch}
>
2024-07-11 17:15:03 +05:00
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 512 512'
width='1em'
height='1em'
fill='currentColor'
>
<path d='M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z'></path>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
<div className='IBMSecMain IBMSMListWrapper'>
<div className='IBMSMList IBMSMListFeaturedAlt'>
2024-09-18 21:41:55 +05:00
{currentGames.map((game) => (
<GameCard
key={game['Game Name']}
title={game['Game Name']}
imageUrl={game['Boxart image']}
/>
))}
2024-07-11 17:15:03 +05:00
</div>
</div>
2024-09-18 21:41:55 +05:00
<PaginationWithPageNumbers
currentPage={currentPage}
totalPages={totalPages}
handlePageChange={handlePageChange}
/>
2024-07-11 17:15:03 +05:00
</div>
</div>
</div>
)
}