This changes the URL to show query params for our three filters, making it easy for people to link to very specific subsets of raids.
111 lines
3.3 KiB
TypeScript
111 lines
3.3 KiB
TypeScript
import React, { useCallback, useEffect, useState } from 'react'
|
|
import { useRouter } from 'next/router'
|
|
|
|
import api from '~utils/api'
|
|
import { appState } from '~utils/appState'
|
|
import { raidGroups } from '~utils/raidGroups'
|
|
|
|
import './index.scss'
|
|
|
|
// Props
|
|
interface Props {
|
|
showAllRaidsOption: boolean
|
|
currentRaid?: string
|
|
onChange?: (raid?: Raid) => void
|
|
onBlur?: (event: React.ChangeEvent<HTMLSelectElement>) => void
|
|
}
|
|
|
|
const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFieldSet(props, ref) {
|
|
// Set up router for locale
|
|
const router = useRouter()
|
|
const locale = router.locale || 'en'
|
|
|
|
// Set up local states for storing raids
|
|
const [currentRaid, setCurrentRaid] = useState<Raid>()
|
|
const [raids, setRaids] = useState<Raid[]>()
|
|
const [sortedRaids, setSortedRaids] = useState<Raid[][]>()
|
|
|
|
// Set up empty raid for "All raids"
|
|
const all = {
|
|
id: '0',
|
|
name: {
|
|
en: 'All raids',
|
|
ja: '全て'
|
|
},
|
|
slug: 'all',
|
|
level: 0,
|
|
group: 0,
|
|
element: 0
|
|
}
|
|
|
|
// Organize raids into groups on mount
|
|
const organizeRaids = useCallback((raids: Raid[]) => {
|
|
const numGroups = Math.max.apply(Math, raids.map(raid => raid.group))
|
|
let groupedRaids = []
|
|
|
|
for (let i = 0; i <= numGroups; i++) {
|
|
groupedRaids[i] = raids.filter(raid => raid.group == i)
|
|
}
|
|
|
|
if (props.showAllRaidsOption) {
|
|
raids.unshift(all)
|
|
groupedRaids[0].unshift(all)
|
|
}
|
|
|
|
setRaids(raids)
|
|
setSortedRaids(groupedRaids)
|
|
appState.raids = raids
|
|
}, [props.showAllRaidsOption])
|
|
|
|
// Fetch all raids on mount
|
|
useEffect(() => {
|
|
api.endpoints.raids.getAll()
|
|
.then(response => organizeRaids(response.data.map((r: any) => r.raid)))
|
|
}, [organizeRaids])
|
|
|
|
// Set current raid on mount
|
|
useEffect(() => {
|
|
if (raids && props.currentRaid) {
|
|
const raid = raids.find(raid => raid.slug === props.currentRaid)
|
|
setCurrentRaid(raid)
|
|
}
|
|
}, [raids, props.currentRaid])
|
|
|
|
// Enable changing select value
|
|
function handleChange(event: React.ChangeEvent<HTMLSelectElement>) {
|
|
if (raids) {
|
|
const raid = raids.find(raid => raid.slug === event.target.value)
|
|
if (props.onChange) props.onChange(raid)
|
|
setCurrentRaid(raid)
|
|
}
|
|
}
|
|
|
|
// Render JSX for each raid option, sorted into optgroups
|
|
function renderRaidGroup(index: number) {
|
|
const options = sortedRaids && sortedRaids.length > 0 && sortedRaids[index].length > 0 &&
|
|
sortedRaids[index].sort((a, b) => a.element - b.element).map((item, i) => {
|
|
return (
|
|
<option key={i} value={item.slug}>{item.name[locale]}</option>
|
|
)
|
|
})
|
|
|
|
return (
|
|
<optgroup key={index} label={raidGroups[index].name[locale]}>
|
|
{options}
|
|
</optgroup>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<select
|
|
key={currentRaid?.slug}
|
|
value={currentRaid?.slug}
|
|
onBlur={props.onBlur}
|
|
onChange={handleChange}
|
|
ref={ref}>
|
|
{ Array.from(Array(sortedRaids?.length)).map((x, i) => renderRaidGroup(i)) }
|
|
</select>
|
|
)
|
|
})
|
|
|
|
export default RaidDropdown
|