Make RaidDropdown to be a controlled component
It also indexes on the raid's `slug` instead of `id`, a new key that will let us get to using query params to filter
This commit is contained in:
parent
79b5960cea
commit
aefd6c3754
3 changed files with 57 additions and 21 deletions
|
|
@ -1,24 +1,36 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useSnapshot } from 'valtio'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
|
||||||
import RaidDropdown from '~components/RaidDropdown'
|
import RaidDropdown from '~components/RaidDropdown'
|
||||||
|
|
||||||
|
import { appState } from '~utils/appState'
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
scrolled: boolean
|
scrolled: boolean
|
||||||
|
element?: number
|
||||||
|
raidSlug?: string
|
||||||
|
recency?: number
|
||||||
onFilter: (element?: number, raid?: string, recency?: number) => void
|
onFilter: (element?: number, raid?: string, recency?: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const FilterBar = (props: Props) => {
|
const FilterBar = (props: Props) => {
|
||||||
|
// Set up translation
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
|
// Set up state object
|
||||||
|
const app = useSnapshot(appState)
|
||||||
|
|
||||||
|
// Set up refs for filter dropdowns
|
||||||
const elementSelect = React.createRef<HTMLSelectElement>()
|
const elementSelect = React.createRef<HTMLSelectElement>()
|
||||||
const raidSelect = React.createRef<HTMLSelectElement>()
|
const raidSelect = React.createRef<HTMLSelectElement>()
|
||||||
const recencySelect = React.createRef<HTMLSelectElement>()
|
const recencySelect = React.createRef<HTMLSelectElement>()
|
||||||
|
|
||||||
|
// Set up classes object for showing shadow on scroll
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
'FilterBar': true,
|
'FilterBar': true,
|
||||||
'shadow': props.scrolled
|
'shadow': props.scrolled
|
||||||
|
|
@ -26,8 +38,13 @@ const FilterBar = (props: Props) => {
|
||||||
|
|
||||||
function selectChanged(event: React.ChangeEvent<HTMLSelectElement>) {
|
function selectChanged(event: React.ChangeEvent<HTMLSelectElement>) {
|
||||||
const elementValue = (elementSelect.current) ? parseInt(elementSelect.current.value) : -1
|
const elementValue = (elementSelect.current) ? parseInt(elementSelect.current.value) : -1
|
||||||
const raidValue = (raidSelect.current) ? raidSelect.current.value : ''
|
|
||||||
const recencyValue = (recencySelect.current) ? parseInt(recencySelect.current.value) : -1
|
const recencyValue = (recencySelect.current) ? parseInt(recencySelect.current.value) : -1
|
||||||
|
let raidValue = ''
|
||||||
|
|
||||||
|
if (app.raids) {
|
||||||
|
const raid = app.raids.find((raid: Raid) => raid.slug === raidSelect.current?.value)
|
||||||
|
raidValue = (raid) ? raid.id : ''
|
||||||
|
}
|
||||||
|
|
||||||
props.onFilter(elementValue, raidValue, recencyValue)
|
props.onFilter(elementValue, raidValue, recencyValue)
|
||||||
}
|
}
|
||||||
|
|
@ -35,19 +52,19 @@ const FilterBar = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
{props.children}
|
{props.children}
|
||||||
<select onChange={selectChanged} ref={elementSelect}>
|
<select onChange={selectChanged} ref={elementSelect} value={props.element}>
|
||||||
<option key={-1} value={-1}>{t('elements.full.all')}</option>
|
<option data-element="all" key={-1} value={-1}>{t('elements.full.all')}</option>
|
||||||
<option key={-0} value={0}>{t('elements.full.null')}</option>
|
<option data-element="null" key={-0} value={0}>{t('elements.full.null')}</option>
|
||||||
<option key={1}value={1}>{t('elements.full.wind')}</option>
|
<option data-element="wind" key={1} value={1}>{t('elements.full.wind')}</option>
|
||||||
<option key={2}value={2}>{t('elements.full.fire')}</option>
|
<option data-element="fire" key={2} value={2}>{t('elements.full.fire')}</option>
|
||||||
<option key={3}value={3}>{t('elements.full.water')}</option>
|
<option data-element="water" key={3} value={3}>{t('elements.full.water')}</option>
|
||||||
<option key={4}value={4}>{t('elements.full.earth')}</option>
|
<option data-element="earth" key={4} value={4}>{t('elements.full.earth')}</option>
|
||||||
<option key={5}value={5}>{t('elements.full.dark')}</option>
|
<option data-element="dark" key={5} value={5}>{t('elements.full.dark')}</option>
|
||||||
<option key={6}value={6}>{t('elements.full.light')}</option>
|
<option data-element="light" key={6} value={6}>{t('elements.full.light')}</option>
|
||||||
</select>
|
</select>
|
||||||
<RaidDropdown
|
<RaidDropdown
|
||||||
allOption={true}
|
showAllRaidsOption={true}
|
||||||
onChange={selectChanged}
|
onChange={selectChanged}
|
||||||
ref={raidSelect}
|
ref={raidSelect}
|
||||||
/>
|
/>
|
||||||
<select onChange={selectChanged} ref={recencySelect}>
|
<select onChange={selectChanged} ref={recencySelect}>
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ const PartyDetails = (props: Props) => {
|
||||||
function updateDetails(event: React.ChangeEvent) {
|
function updateDetails(event: React.ChangeEvent) {
|
||||||
const nameValue = nameInput.current?.value
|
const nameValue = nameInput.current?.value
|
||||||
const descriptionValue = descriptionInput.current?.value
|
const descriptionValue = descriptionInput.current?.value
|
||||||
const raid = raids.find(raid => raid.id == raidSelect.current?.value)
|
const raid = raids.find(raid => raid.slug === raidSelect.current?.value)
|
||||||
|
|
||||||
props.updateCallback(nameValue, descriptionValue, raid)
|
props.updateCallback(nameValue, descriptionValue, raid)
|
||||||
}
|
}
|
||||||
|
|
@ -83,8 +83,8 @@ const PartyDetails = (props: Props) => {
|
||||||
ref={nameInput}
|
ref={nameInput}
|
||||||
/>
|
/>
|
||||||
<RaidDropdown
|
<RaidDropdown
|
||||||
allOption={false}
|
showAllRaidsOption={false}
|
||||||
selected={party.raid?.id || ''}
|
currentRaid={party.raid?.slug || ''}
|
||||||
onBlur={updateDetails}
|
onBlur={updateDetails}
|
||||||
ref={raidSelect}
|
ref={raidSelect}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import './index.scss'
|
||||||
// Props
|
// Props
|
||||||
interface Props {
|
interface Props {
|
||||||
showAllRaidsOption: boolean
|
showAllRaidsOption: boolean
|
||||||
currentRaidId?: string
|
currentRaid?: string
|
||||||
onChange?: (event: React.ChangeEvent<HTMLSelectElement>) => void
|
onChange?: (event: React.ChangeEvent<HTMLSelectElement>) => void
|
||||||
onBlur?: (event: React.ChangeEvent<HTMLSelectElement>) => void
|
onBlur?: (event: React.ChangeEvent<HTMLSelectElement>) => void
|
||||||
}
|
}
|
||||||
|
|
@ -20,7 +20,8 @@ const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFiel
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const locale = router.locale || 'en'
|
const locale = router.locale || 'en'
|
||||||
|
|
||||||
// Set up local states for storing lists of raids
|
// Set up local states for storing raids
|
||||||
|
const [currentRaid, setCurrentRaid] = useState<Raid>()
|
||||||
const [raids, setRaids] = useState<Raid[]>()
|
const [raids, setRaids] = useState<Raid[]>()
|
||||||
const [sortedRaids, setSortedRaids] = useState<Raid[][]>()
|
const [sortedRaids, setSortedRaids] = useState<Raid[][]>()
|
||||||
|
|
||||||
|
|
@ -53,6 +54,7 @@ const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFiel
|
||||||
|
|
||||||
setRaids(raids)
|
setRaids(raids)
|
||||||
setSortedRaids(groupedRaids)
|
setSortedRaids(groupedRaids)
|
||||||
|
appState.raids = raids
|
||||||
}, [props.showAllRaidsOption])
|
}, [props.showAllRaidsOption])
|
||||||
|
|
||||||
// Fetch all raids on mount
|
// Fetch all raids on mount
|
||||||
|
|
@ -61,12 +63,29 @@ const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFiel
|
||||||
.then(response => organizeRaids(response.data.map((r: any) => r.raid)))
|
.then(response => organizeRaids(response.data.map((r: any) => r.raid)))
|
||||||
}, [organizeRaids])
|
}, [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(event)
|
||||||
|
setCurrentRaid(raid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render JSX for each raid option, sorted into optgroups
|
// Render JSX for each raid option, sorted into optgroups
|
||||||
function renderRaidGroup(index: number) {
|
function renderRaidGroup(index: number) {
|
||||||
const options = sortedRaids && sortedRaids.length > 0 && sortedRaids[index].length > 0 &&
|
const options = sortedRaids && sortedRaids.length > 0 && sortedRaids[index].length > 0 &&
|
||||||
sortedRaids[index].sort((a, b) => a.element - b.element).map((item, i) => {
|
sortedRaids[index].sort((a, b) => a.element - b.element).map((item, i) => {
|
||||||
return (
|
return (
|
||||||
<option key={i} value={item.id}>{item.name[locale]}</option>
|
<option key={i} value={item.slug}>{item.name[locale]}</option>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -79,10 +98,10 @@ const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFiel
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
key={props.currentRaidId}
|
key={currentRaid?.slug}
|
||||||
defaultValue={props.currentRaidId}
|
value={currentRaid?.slug}
|
||||||
onBlur={props.onBlur}
|
onBlur={props.onBlur}
|
||||||
onChange={props.onChange}
|
onChange={handleChange}
|
||||||
ref={ref}>
|
ref={ref}>
|
||||||
{ Array.from(Array(sortedRaids?.length)).map((x, i) => renderRaidGroup(i)) }
|
{ Array.from(Array(sortedRaids?.length)).map((x, i) => renderRaidGroup(i)) }
|
||||||
</select>
|
</select>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue