diff --git a/components/raids/RaidCombobox/index.tsx b/components/raids/RaidCombobox/index.tsx index b52c649c..028c36d4 100644 --- a/components/raids/RaidCombobox/index.tsx +++ b/components/raids/RaidCombobox/index.tsx @@ -20,7 +20,9 @@ import api from '~utils/api' interface Props { showAllRaidsOption: boolean currentRaid?: Raid + currentRaidSlug?: string defaultRaid?: Raid + minimal?: boolean onChange?: (raid?: Raid) => void onBlur?: (event: React.ChangeEvent) => void } @@ -55,13 +57,19 @@ const RaidCombobox = (props: Props) => { // Data state const [currentSection, setCurrentSection] = useState(1) - const [search, setSearch] = useState('') + const [query, setQuery] = useState('') const [sections, setSections] = useState() const [currentRaid, setCurrentRaid] = useState() // Refs const listRef = createRef() - const selectedRef = createRef() + + function slugToRaid(slug: string) { + return appState.raidGroups + .filter((group) => group.section > 0) + .flatMap((group) => group.raids) + .find((raid) => raid.slug === slug) + } useEffect(() => { if (appState.party.raid) { @@ -70,6 +78,12 @@ const RaidCombobox = (props: Props) => { } }, []) + useEffect(() => { + if (props.currentRaidSlug) { + setCurrentRaid(slugToRaid(props.currentRaidSlug)) + } + }) + // Scroll to the top of the list when the user switches tabs useEffect(() => { if (listRef.current) listRef.current.scrollTop = 0 @@ -77,22 +91,15 @@ const RaidCombobox = (props: Props) => { const scrollToItem = useCallback( (node) => { - if ( - !scrolled && - open && - currentRaid && - listRef.current && - node !== null - ) { - const listRect = listRef.current.getBoundingClientRect() - const itemRect = node.getBoundingClientRect() - const distance = itemRect.top - listRect.top + if (!scrolled && open && currentRaid && listRef.current && node) { + const { top: listTop } = listRef.current.getBoundingClientRect() + const { top: itemTop } = node.getBoundingClientRect() - listRef.current.scrollTop = distance + listRef.current.scrollTop = itemTop - listTop setScrolled(true) } }, - [open, currentRaid, listRef] + [scrolled, open, currentRaid, listRef] ) // Methods: Convenience methods @@ -132,7 +139,7 @@ const RaidCombobox = (props: Props) => { } function clearSearch() { - setSearch('') + setQuery('') } const linkClass = classNames({ @@ -150,79 +157,81 @@ const RaidCombobox = (props: Props) => { }, [sortGroups]) // Methods: Rendering + function renderRaidSections() { - let sections = [] - for (let i = 0; i < NUM_SECTIONS; i++) { - sections.push(renderRaidSection(i)) - } - return sections + // Renders each raid section + return Array.from({ length: NUM_SECTIONS }, (_, i) => renderRaidSection(i)) } function renderRaidSection(section: number) { - if (!sections || !sections[section]) return - else { - const currentSection = sections[section] - return currentSection - .sort((a, b) => { - if (sort === Sort.ASCENDING) return a.order - b.order - else return b.order - a.order - }) - .map((group, i) => renderRaidGroup(section, i)) - } + // Renders the specified raid section + const currentSection = sections?.[section] + if (!currentSection) return + + const sortedGroups = currentSection.sort((a, b) => { + return sort === Sort.ASCENDING ? a.order - b.order : b.order - a.order + }) + + return sortedGroups.map((group, i) => renderRaidGroup(section, i)) } - // Render JSX for each raid option, sorted into optgroups function renderRaidGroup(section: number, index: number) { - let options = [] + // Renders the specified raid group + if (!sections?.[section]?.[index]) return - if (!sections || !sections[section] || !sections[section][index]) return - else { - const group = sections[section][index] + const group = sections[section][index] + const options = generateRaidItems(group.raids) - options = group.raids - .sort((a, b) => { - if (a.element > 0 && b.element > 0) return a.element - b.element - else if (a.name.en.includes('NM') && b.name.en.includes('NM')) - return a.level < b.level ? -1 : 1 - else return a.name.en < b.name.en ? -1 : 1 - }) - .map((item, i) => renderRaidItem(item, i)) + const groupClassName = classNames({ + CommandGroup: true, + Hidden: group.section !== currentSection, + }) - return ( - - {group.name[locale]} -
-
- } - > - {options} -
- ) - } + const heading = ( +
+ {group.name[locale]} +
+
+ ) + + return ( + + {options} + + ) + } + + function generateRaidItems(raids: Raid[]) { + // Generates a list of RaidItem components from the specified raids + return raids + .sort((a, b) => { + if (a.element > 0 && b.element > 0) return a.element - b.element + if (a.name.en.includes('NM') && b.name.en.includes('NM')) + return a.level - b.level + return a.name.en.localeCompare(b.name.en) + }) + .map((item, i) => renderRaidItem(item, i)) } function renderRaidItem(raid: Raid, key: number) { + // Renders a RaidItem component for the specified raid + const isSelected = currentRaid?.id === raid.id + const isRef = isSelected ? scrollToItem : undefined + const imageUrl = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/raids/${raid.slug}.png` + return ( handleValueChange(raid)} > @@ -231,6 +240,113 @@ const RaidCombobox = (props: Props) => { ) } + function renderSegmentedControl() { + // Renders a SegmentedControl component for selecting raid sections. + return ( + + setCurrentSection(2)} + > + {t('raids.sections.events')} + + setCurrentSection(1)} + > + {t('raids.sections.raids')} + + setCurrentSection(3)} + > + {t('raids.sections.solo')} + + + ) + } + + function renderSortButton() { + // Renders a Button for sorting raids and a Tooltip for explaining what it does. + return ( + +
- ) : ( - '' )}
{renderRaidSections()} @@ -344,4 +377,8 @@ const RaidCombobox = (props: Props) => { ) } +RaidCombobox.defaultProps = { + minimal: false, +} + export default RaidCombobox