Fix page navigation when filtering collections

There was a bug that kept page navigation from working properly when filtering. Things would load multiple times, or load the wrong thing, or not navigate properly. That should all be fixed now.
This commit is contained in:
Justin Edmund 2023-07-04 00:28:05 -07:00
parent acbb10d458
commit a064cfa67c
8 changed files with 91 additions and 93 deletions

View file

@ -21,9 +21,10 @@ interface Props {
children: React.ReactNode
scrolled: boolean
element?: number
raidSlug?: string
raid?: string
recency?: number
onFilter: (filters: FilterSet) => void
onAdvancedFilter: (filters: FilterSet) => void
}
const FilterBar = (props: Props) => {
@ -55,10 +56,10 @@ const FilterBar = (props: Props) => {
const raid = appState.raidGroups
.filter((group) => group.section > 0)
.flatMap((group) => group.raids)
.find((raid) => raid.slug === props.raidSlug)
.find((raid) => raid.id === props.raid)
setCurrentRaid(raid)
}, [props.raidSlug])
}, [props.raid])
useEffect(() => {
// Fetch user's advanced filters
@ -91,12 +92,12 @@ const FilterBar = (props: Props) => {
}
function raidSelectChanged(raid?: Raid) {
props.onFilter({ raidSlug: raid?.slug, ...advancedFilters })
props.onFilter({ raid: raid?.slug, ...advancedFilters })
}
function handleAdvancedFiltersChanged(filters: FilterSet) {
setAdvancedFilters(filters)
props.onFilter(filters)
props.onAdvancedFilter(filters)
}
function onSelectChange(name: 'element' | 'recency') {

View file

@ -112,7 +112,7 @@ const RaidCombobox = (props: Props) => {
// Fetch all raids on mount
useEffect(() => {
api.raidGroups().then((response) => sortGroups(response.data))
sortGroups(appState.raidGroups)
}, [])
// Set current raid and section when the component mounts
@ -136,6 +136,8 @@ const RaidCombobox = (props: Props) => {
if (appState.party.raid && appState.party.raid.group.section > 0)
setCurrentSection(props.currentRaid.group.section)
else setCurrentSection(1)
} else {
setCurrentRaid(undefined)
}
}, [props.currentRaid])
@ -224,7 +226,9 @@ const RaidCombobox = (props: Props) => {
if (group.section > 0) sections[group.section - 1].push(group)
})
if (groups[0]) {
setFarmingRaid(groups[0].raids[0])
}
setSections(sections)
},

View file

@ -1,6 +1,5 @@
import React, { useCallback, useEffect, useState } from 'react'
import InfiniteScroll from 'react-infinite-scroll-component'
import { getCookie } from 'cookies-next'
import { queryTypes, useQueryState } from 'next-usequerystate'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
@ -53,13 +52,12 @@ const ProfileRoute: React.FC<Props> = ({
const { t } = useTranslation('common')
// Set up app-specific states
const [raidsLoading, setRaidsLoading] = useState(true)
const [mounted, setMounted] = useState(false)
const [scrolled, setScrolled] = useState(false)
// Set up page-specific states
const [parties, setParties] = useState<Party[]>([])
const [raids, setRaids] = useState<Raid[]>()
const [raid, setRaid] = useState<Raid>()
// Set up infinite scrolling-related states
const [recordCount, setRecordCount] = useState(0)
@ -74,9 +72,15 @@ const ProfileRoute: React.FC<Props> = ({
parse: (query: string) => parseElement(query),
serialize: (value) => serializeElement(value),
})
const [raidSlug, setRaidSlug] = useQueryState('raid', {
const [raid, setRaid] = useQueryState('raid', {
defaultValue: 'all',
history: 'push',
parse: (query: string) => {
const raids = context?.raidGroups.flatMap((group) => group.raids)
const raid = raids?.find((r: Raid) => r.slug === query)
return raid ? raid.id : 'all'
},
serialize: (value) => value,
})
const [recency, setRecency] = useQueryState('recency', {
defaultValue: -1,
@ -113,6 +117,7 @@ const ProfileRoute: React.FC<Props> = ({
setTotalPages(context.pagination.totalPages)
setRecordCount(context.pagination.count)
replaceResults(context.pagination.count, context.teams)
appState.raidGroups = context.raidGroups
appState.version = version
}
setCurrentPage(1)
@ -139,7 +144,7 @@ const ProfileRoute: React.FC<Props> = ({
const filters = {
params: {
element: element != -1 ? element : undefined,
raid: raid ? raid.id : undefined,
raid: raid === 'all' ? undefined : raid,
recency: recency != -1 ? recency : undefined,
page: currentPage,
...advancedFilters,
@ -183,14 +188,8 @@ const ProfileRoute: React.FC<Props> = ({
// Fetch all raids on mount, then find the raid in the URL if present
useEffect(() => {
api.endpoints.raids.getAll().then((response) => {
setRaids(response.data)
setRaidsLoading(false)
const raid = response.data.find((r: Raid) => r.slug === raidSlug)
setRaid(raid)
return raid
const raids = appState.raidGroups.flatMap((group) => group.raids)
setRaids(raids)
})
}, [setRaids])
@ -198,7 +197,12 @@ const ProfileRoute: React.FC<Props> = ({
// fetch all teams again.
useDidMountEffect(() => {
setCurrentPage(1)
if (mounted) {
fetchProfile({ replace: true })
}
setMounted(true)
}, [username, element, raid, recency, advancedFilters])
// When the page changes, fetch all teams again.
@ -206,25 +210,18 @@ const ProfileRoute: React.FC<Props> = ({
// Current page changed
if (currentPage > 1) fetchProfile({ replace: false })
else if (currentPage == 1) fetchProfile({ replace: true })
setMounted(true)
}, [currentPage])
// Receive filters from the filter bar
function receiveFilters(filters: FilterSet) {
if (filters.element == 0) setElement(0, { shallow: true })
else if (filters.element) setElement(filters.element, { shallow: true })
if (raids && filters.raidSlug) {
const raid = raids.find((raid) => raid.slug === filters.raidSlug)
setRaid(raid)
setRaidSlug(filters.raidSlug, { shallow: true })
if (filters.recency) setRecency(filters.recency, { shallow: true })
if (filters.raid) setRaid(filters.raid, { shallow: true })
}
if (filters.recency) setRecency(filters.recency, { shallow: true })
delete filters.element
delete filters.raidSlug
delete filters.recency
function receiveAdvancedFilters(filters: FilterSet) {
setAdvancedFilters(filters)
}
@ -273,15 +270,16 @@ const ProfileRoute: React.FC<Props> = ({
if (context) {
return (
<div id="Profile">
<div className="profile">
{pageHead()}
<FilterBar
defaultFilterset={permissiveFilterset}
onAdvancedFilter={receiveAdvancedFilters}
onFilter={receiveFilters}
persistFilters={false}
scrolled={scrolled}
element={element}
raidSlug={raidSlug ? raidSlug : undefined}
raid={raid}
recency={recency}
>
<UserInfo user={context.user!} />

View file

@ -25,6 +25,7 @@ import '../styles/globals.scss'
function MyApp({ Component, pageProps }: AppProps) {
const { t } = useTranslation('common')
const [mounted, setMounted] = useState(false)
const [refresh, setRefresh] = useState(false)
// Subscribe to app state to listen for account changes and

View file

@ -1,6 +1,5 @@
import React, { useCallback, useEffect, useState } from 'react'
import InfiniteScroll from 'react-infinite-scroll-component'
import { getCookie } from 'cookies-next'
import { queryTypes, useQueryState } from 'next-usequerystate'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
@ -52,13 +51,12 @@ const SavedRoute: React.FC<Props> = ({
const { t } = useTranslation('common')
// Set up app-specific states
const [raidsLoading, setRaidsLoading] = useState(true)
const [mounted, setMounted] = useState(false)
const [scrolled, setScrolled] = useState(false)
// Set up page-specific states
const [parties, setParties] = useState<Party[]>([])
const [raids, setRaids] = useState<Raid[]>()
const [raid, setRaid] = useState<Raid>()
// Set up infinite scrolling-related states
const [recordCount, setRecordCount] = useState(0)
@ -73,9 +71,15 @@ const SavedRoute: React.FC<Props> = ({
parse: (query: string) => parseElement(query),
serialize: (value) => serializeElement(value),
})
const [raidSlug, setRaidSlug] = useQueryState('raid', {
const [raid, setRaid] = useQueryState('raid', {
defaultValue: 'all',
history: 'push',
parse: (query: string) => {
const raids = context?.raidGroups.flatMap((group) => group.raids)
const raid = raids?.find((r: Raid) => r.slug === query)
return raid ? raid.id : 'all'
},
serialize: (value) => value,
})
const [recency, setRecency] = useQueryState('recency', {
defaultValue: -1,
@ -112,6 +116,7 @@ const SavedRoute: React.FC<Props> = ({
setTotalPages(context.pagination.totalPages)
setRecordCount(context.pagination.count)
replaceResults(context.pagination.count, context.teams)
appState.raidGroups = context.raidGroups
appState.version = version
}
setCurrentPage(1)
@ -138,7 +143,7 @@ const SavedRoute: React.FC<Props> = ({
[key: string]: any
} = {
element: element !== -1 ? element : undefined,
raid: raid ? raid.id : undefined,
raid: raid === 'all' ? undefined : raid,
recency: recency !== -1 ? recency : undefined,
page: currentPage,
...advancedFilters,
@ -186,14 +191,8 @@ const SavedRoute: React.FC<Props> = ({
// Fetch all raids on mount, then find the raid in the URL if present
useEffect(() => {
api.endpoints.raids.getAll().then((response) => {
setRaids(response.data)
setRaidsLoading(false)
const raid = response.data.find((r: Raid) => r.slug === raidSlug)
setRaid(raid)
return raid
const raids = appState.raidGroups.flatMap((group) => group.raids)
setRaids(raids)
})
}, [setRaids])
@ -201,7 +200,12 @@ const SavedRoute: React.FC<Props> = ({
// fetch all teams again.
useDidMountEffect(() => {
setCurrentPage(1)
if (mounted) {
fetchTeams({ replace: true })
}
setMounted(true)
}, [element, raid, recency, advancedFilters])
// When the page changes, fetch all teams again.
@ -209,25 +213,18 @@ const SavedRoute: React.FC<Props> = ({
// Current page changed
if (currentPage > 1) fetchTeams({ replace: false })
else if (currentPage == 1) fetchTeams({ replace: true })
setMounted(true)
}, [currentPage])
// Receive filters from the filter bar
function receiveFilters(filters: FilterSet) {
if (filters.element == 0) setElement(0, { shallow: true })
else if (filters.element) setElement(filters.element, { shallow: true })
if (raids && filters.raidSlug) {
const raid = raids.find((raid) => raid.slug === filters.raidSlug)
setRaid(raid)
setRaidSlug(filters.raidSlug, { shallow: true })
if (filters.recency) setRecency(filters.recency, { shallow: true })
if (filters.raid) setRaid(filters.raid, { shallow: true })
}
if (filters.recency) setRecency(filters.recency, { shallow: true })
delete filters.element
delete filters.raidSlug
delete filters.recency
function receiveAdvancedFilters(filters: FilterSet) {
setAdvancedFilters(filters)
}
@ -313,15 +310,16 @@ const SavedRoute: React.FC<Props> = ({
if (context) {
return (
<div id="Teams">
<div className="teams">
{pageHead()}
<FilterBar
defaultFilterset={permissiveFilterset}
onFilter={receiveFilters}
onAdvancedFilter={receiveAdvancedFilters}
persistFilters={false}
scrolled={scrolled}
element={element}
raidSlug={raidSlug ? raidSlug : undefined}
raid={raid}
recency={recency}
>
<h1>{t('saved.title')}</h1>

View file

@ -52,13 +52,12 @@ const TeamsRoute: React.FC<Props> = ({
const { t } = useTranslation('common')
// Set up app-specific states
const [raidsLoading, setRaidsLoading] = useState(true)
const [mounted, setMounted] = useState(false)
const [scrolled, setScrolled] = useState(false)
// Set up page-specific states
const [parties, setParties] = useState<Party[]>([])
const [raids, setRaids] = useState<Raid[]>()
const [raid, setRaid] = useState<Raid>()
// Set up infinite scrolling-related states
const [recordCount, setRecordCount] = useState(0)
@ -73,9 +72,15 @@ const TeamsRoute: React.FC<Props> = ({
parse: (query: string) => parseElement(query),
serialize: (value) => serializeElement(value),
})
const [raidSlug, setRaidSlug] = useQueryState('raid', {
const [raid, setRaid] = useQueryState('raid', {
defaultValue: 'all',
history: 'push',
parse: (query: string) => {
const raids = context?.raidGroups.flatMap((group) => group.raids)
const raid = raids?.find((r: Raid) => r.slug === query)
return raid ? raid.id : 'all'
},
serialize: (value) => value,
})
const [recency, setRecency] = useQueryState('recency', {
defaultValue: -1,
@ -149,7 +154,7 @@ const TeamsRoute: React.FC<Props> = ({
[key: string]: any
} = {
element: element !== -1 ? element : undefined,
raid: raid ? raid.id : undefined,
raid: raid === 'all' ? undefined : raid,
recency: recency !== -1 ? recency : undefined,
page: currentPage,
...advancedFilters,
@ -196,49 +201,39 @@ const TeamsRoute: React.FC<Props> = ({
// Fetch all raids on mount, then find the raid in the URL if present
useEffect(() => {
api.endpoints.raids.getAll().then((response) => {
setRaids(response.data)
setRaidsLoading(false)
const raid = response.data.find((r: Raid) => r.slug === raidSlug)
setRaid(raid)
return raid
})
const raids = appState.raidGroups.flatMap((group) => group.raids)
setRaids(raids)
}, [setRaids])
// When the element, raid or recency filter changes,
// fetch all teams again.
useDidMountEffect(() => {
setCurrentPage(1)
if (mounted) {
fetchTeams({ replace: true })
}
setMounted(true)
}, [element, raid, recency, advancedFilters])
// When the page changes, fetch all teams again.
useDidMountEffect(() => {
// Current page changed
if (currentPage > 1) fetchTeams({ replace: false })
else if (currentPage == 1) fetchTeams({ replace: true })
else if (currentPage == 1 && mounted) fetchTeams({ replace: true })
setMounted(true)
}, [currentPage])
// Receive filters from the filter bar
function receiveFilters(filters: FilterSet) {
if (filters.element == 0) setElement(0, { shallow: true })
else if (filters.element) setElement(filters.element, { shallow: true })
if (raids && filters.raidSlug) {
const raid = raids.find((raid) => raid.slug === filters.raidSlug)
setRaid(raid)
setRaidSlug(filters.raidSlug, { shallow: true })
if (filters.recency) setRecency(filters.recency, { shallow: true })
if (filters.raid) setRaid(filters.raid, { shallow: true })
}
if (filters.recency) setRecency(filters.recency, { shallow: true })
delete filters.element
delete filters.raidSlug
delete filters.recency
function receiveAdvancedFilters(filters: FilterSet) {
setAdvancedFilters(filters)
}
@ -324,15 +319,16 @@ const TeamsRoute: React.FC<Props> = ({
if (context) {
return (
<div id="Teams">
<div className="teams">
{pageHead()}
<FilterBar
defaultFilterset={defaultFilterset}
onFilter={receiveFilters}
onAdvancedFilter={receiveAdvancedFilters}
persistFilters={true}
scrolled={scrolled}
element={element}
raidSlug={raidSlug ? raidSlug : undefined}
raid={raid}
recency={recency}
>
<h1>{t('teams.title')}</h1>

View file

@ -121,8 +121,8 @@ h5 {
}
// Used for collection pages
#Teams,
#Profile {
.teams,
.profile {
display: flex;
height: 100%;
flex-direction: column;

View file

@ -1,6 +1,6 @@
interface FilterSet {
element?: number
raidSlug?: string
raid?: string
recency?: number
full_auto?: number
auto_guard?: number