253 lines
7.7 KiB
TypeScript
253 lines
7.7 KiB
TypeScript
import '../styles/filters.css'
|
|
import '../styles/pagination.css'
|
|
import '../styles/styles.css'
|
|
import '../styles/search.css'
|
|
import { ModCard } from '../components/ModCard'
|
|
import { useDidMount } from '../hooks'
|
|
import { Filter, kinds } from 'nostr-tools'
|
|
import { RelayController } from '../controllers'
|
|
import { constructModListFromEvents, log, LogType } from '../utils'
|
|
import { toast } from 'react-toastify'
|
|
import { LoadingSpinner } from '../components/LoadingSpinner'
|
|
import { useState } from 'react'
|
|
import { ModDetails } from '../types'
|
|
|
|
enum SortByFilter {
|
|
Latest = 'Latest',
|
|
Oldest = 'Oldest',
|
|
Best_Rated = 'Best Rated',
|
|
Worst_Rated = 'Worst Rated'
|
|
}
|
|
|
|
enum NSFWFilter {
|
|
Hide_NSFW = 'Hide NSFW',
|
|
Show_NSFW = 'Show NSFW',
|
|
Only_NSFW = 'Only NSFW'
|
|
}
|
|
|
|
enum ModeratedFilter {
|
|
Moderated = 'Moderated',
|
|
Unmoderated = 'Unmoderated'
|
|
}
|
|
|
|
export const ModsPage = () => {
|
|
const [isFetching, setIsFetching] = useState(true)
|
|
const [mods, setMods] = useState<ModDetails[]>([])
|
|
|
|
useDidMount(async () => {
|
|
const filter: Filter = {
|
|
kinds: [kinds.ClassifiedListing]
|
|
}
|
|
|
|
RelayController.getInstance()
|
|
.fetchEvents(filter, [])
|
|
.then((events) => {
|
|
const modList = constructModListFromEvents(events)
|
|
setMods(modList)
|
|
})
|
|
.catch((err) => {
|
|
log(
|
|
true,
|
|
LogType.Error,
|
|
'An error occurred in fetching mods from relays',
|
|
err
|
|
)
|
|
toast.error('An error occurred in fetching mods from relays')
|
|
})
|
|
.finally(() => {
|
|
setIsFetching(false)
|
|
})
|
|
})
|
|
|
|
if (isFetching)
|
|
return <LoadingSpinner desc='Fetching mod details from relays' />
|
|
|
|
return (
|
|
<div className='InnerBodyMain'>
|
|
<div className='ContainerMain'>
|
|
<div className='IBMSecMainGroup IBMSecMainGroupAlt'>
|
|
<PageTitleRow />
|
|
<Filters />
|
|
|
|
<div className='IBMSecMain IBMSMListWrapper'>
|
|
<div className='IBMSMList'>
|
|
{mods.map((mod, index) => (
|
|
<ModCard
|
|
key={`mod-${index}`}
|
|
title={mod.title}
|
|
summary={mod.summary}
|
|
backgroundLink={mod.featuredImageUrl}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<Pagination />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const PageTitleRow = () => {
|
|
return (
|
|
<div className='IBMSecMain'>
|
|
<div className='SearchMainWrapper'>
|
|
<div className='IBMSMTitleMain'>
|
|
<h2 className='IBMSMTitleMainHeading'>Mods</h2>
|
|
</div>
|
|
<div className='SearchMain'>
|
|
<div className='SearchMainInside'>
|
|
<div className='SearchMainInsideWrapper'>
|
|
<input type='text' className='SMIWInput' />
|
|
<button className='btn btnMain SMIWButton' type='button'>
|
|
<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>
|
|
)
|
|
}
|
|
|
|
const Filters = () => {
|
|
return (
|
|
<div className='IBMSecMain'>
|
|
<div className='FiltersMain'>
|
|
<div className='FiltersMainElement'>
|
|
<div className='dropdown dropdownMain'>
|
|
<button
|
|
className='btn dropdown-toggle btnMain btnMainDropdown'
|
|
aria-expanded='false'
|
|
data-bs-toggle='dropdown'
|
|
type='button'
|
|
>
|
|
Latest
|
|
</button>
|
|
|
|
<div className='dropdown-menu dropdownMainMenu'>
|
|
{Object.values(SortByFilter).map((item, index) => (
|
|
<div
|
|
key={`sortByFilterItem-${index}`}
|
|
className='dropdown-item dropdownMainMenuItem'
|
|
>
|
|
{item}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className='FiltersMainElement'>
|
|
<div className='dropdown dropdownMain'>
|
|
<button
|
|
className='btn dropdown-toggle btnMain btnMainDropdown'
|
|
aria-expanded='false'
|
|
data-bs-toggle='dropdown'
|
|
type='button'
|
|
>
|
|
Show all (filtered)
|
|
</button>
|
|
<div className='dropdown-menu dropdownMainMenu'>
|
|
{Object.values(ModeratedFilter).map((item, index) => (
|
|
<div
|
|
key={`moderatedFilterItem-${index}`}
|
|
className='dropdown-item dropdownMainMenuItem'
|
|
>
|
|
{item}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className='FiltersMainElement'>
|
|
<div className='dropdown dropdownMain'>
|
|
<button
|
|
className='btn dropdown-toggle btnMain btnMainDropdown'
|
|
aria-expanded='false'
|
|
data-bs-toggle='dropdown'
|
|
type='button'
|
|
>
|
|
Hide NSFW
|
|
</button>
|
|
<div className='dropdown-menu dropdownMainMenu'>
|
|
{Object.values(NSFWFilter).map((item, index) => (
|
|
<div
|
|
key={`nsfwFilterItem-${index}`}
|
|
className='dropdown-item dropdownMainMenuItem'
|
|
>
|
|
{item}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className='FiltersMainElement'>
|
|
<div className='dropdown dropdownMain'>
|
|
<button
|
|
className='btn dropdown-toggle btnMain btnMainDropdown'
|
|
aria-expanded='false'
|
|
data-bs-toggle='dropdown'
|
|
type='button'
|
|
>
|
|
Show From: DEG Mods
|
|
</button>
|
|
<div className='dropdown-menu dropdownMainMenu'>
|
|
<div className='dropdown-item dropdownMainMenuItem'>
|
|
Show From: {window.location.host}
|
|
</div>
|
|
<div className='dropdown-item dropdownMainMenuItem'>Show All</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const Pagination = () => {
|
|
return (
|
|
<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>
|
|
)
|
|
}
|