degmods.com/src/pages/game.tsx

157 lines
4.3 KiB
TypeScript
Raw Normal View History

import { LoadingSpinner } from 'components/LoadingSpinner'
import { ModCard } from 'components/ModCard'
2024-10-07 15:45:21 +05:00
import { ModFilter } from 'components/ModsFilter'
import { PaginationWithPageNumbers } from 'components/Pagination'
import { MAX_MODS_PER_PAGE, T_TAG_VALUE } from 'constants.ts'
import { RelayController } from 'controllers'
2024-10-07 15:45:21 +05:00
import {
useAppSelector,
useFilteredMods,
useMuteLists,
useNSFWList
} from 'hooks'
import { Filter, kinds } from 'nostr-tools'
import { Subscription } from 'nostr-tools/abstract-relay'
2024-10-07 15:45:21 +05:00
import { useEffect, useRef, useState } from 'react'
import { useParams } from 'react-router-dom'
import { toast } from 'react-toastify'
2024-10-07 15:45:21 +05:00
import {
FilterOptions,
ModDetails,
ModeratedFilter,
NSFWFilter,
SortBy
} from 'types'
import { extractModData, isModDataComplete, log, LogType } from 'utils'
export const GamePage = () => {
const params = useParams()
const { name: gameName } = params
const muteLists = useMuteLists()
2024-10-07 15:45:21 +05:00
const nsfwList = useNSFWList()
const [filterOptions, setFilterOptions] = useState<FilterOptions>({
2024-10-07 15:45:21 +05:00
sort: SortBy.Latest,
nsfw: NSFWFilter.Hide_NSFW,
source: window.location.host,
moderated: ModeratedFilter.Moderated
})
const [mods, setMods] = useState<ModDetails[]>([])
const hasEffectRun = useRef(false)
const [isSubscribing, setIsSubscribing] = useState(false)
const [currentPage, setCurrentPage] = useState(1)
const userState = useAppSelector((state) => state.user)
2024-10-07 15:45:21 +05:00
const filteredMods = useFilteredMods(
mods,
2024-10-07 15:45:21 +05:00
userState,
filterOptions,
nsfwList,
muteLists
2024-10-07 15:45:21 +05:00
)
// Pagination logic
const totalGames = filteredMods.length
const totalPages = Math.ceil(totalGames / MAX_MODS_PER_PAGE)
const startIndex = (currentPage - 1) * MAX_MODS_PER_PAGE
const endIndex = startIndex + MAX_MODS_PER_PAGE
const currentMods = filteredMods.slice(startIndex, endIndex)
const handlePageChange = (page: number) => {
if (page >= 1 && page <= totalPages) {
setCurrentPage(page)
}
}
useEffect(() => {
if (hasEffectRun.current) {
return
}
hasEffectRun.current = true // Set it so the effect doesn't run again
const filter: Filter = {
kinds: [kinds.ClassifiedListing],
'#t': [T_TAG_VALUE]
}
setIsSubscribing(true)
let subscriptions: Subscription[] = []
RelayController.getInstance()
.subscribeForEvents(filter, [], (event) => {
if (isModDataComplete(event)) {
const mod = extractModData(event)
if (mod.game === gameName) setMods((prev) => [...prev, mod])
}
})
.then((subs) => {
subscriptions = subs
})
.catch((err) => {
log(
true,
LogType.Error,
'An error occurred in subscribing to relays.',
err
)
toast.error(err.message || err)
})
.finally(() => {
setIsSubscribing(false)
})
// Cleanup function to stop all subscriptions
return () => {
subscriptions.forEach((sub) => sub.close()) // close each subscription
}
}, [gameName])
if (!gameName) return null
return (
<>
{isSubscribing && (
<LoadingSpinner desc='Subscribing to relays for mods' />
)}
<div className='InnerBodyMain'>
<div className='ContainerMain'>
<div className='IBMSecMainGroup IBMSecMainGroupAlt'>
<div className='IBMSecMain'>
<div className='SearchMainWrapper'>
<div className='IBMSMTitleMain'>
<h2 className='IBMSMTitleMainHeading'>
Game:&nbsp;
<span className='IBMSMTitleMainHeadingSpan'>
{gameName}
</span>
</h2>
</div>
</div>
</div>
2024-10-07 15:45:21 +05:00
<ModFilter
filterOptions={filterOptions}
setFilterOptions={setFilterOptions}
/>
<div className='IBMSecMain IBMSMListWrapper'>
<div className='IBMSMList'>
{currentMods.map((mod) => (
<ModCard key={mod.id} {...mod} />
))}
</div>
</div>
<PaginationWithPageNumbers
currentPage={currentPage}
totalPages={totalPages}
handlePageChange={handlePageChange}
/>
</div>
</div>
</div>
</>
)
}