Add loading indicator to group switcher

This commit is contained in:
VityaSchel
2023-10-15 00:58:12 +04:00
parent 95f1b8914f
commit 7e440c9bff
7 changed files with 194 additions and 30 deletions

View File

@@ -7,8 +7,11 @@ import Link from 'next/link'
import { useRouter } from 'next/router'
import { FaGithub } from 'react-icons/fa'
import cx from 'classnames'
import { NavContext, NavContextProvider } from '@/shared/context/nav-context'
export function NavBar() {
export function NavBar({ cacheAvailableFor }: {
cacheAvailableFor: string[]
}) {
const { resolvedTheme } = useTheme()
const [schemeTheme, setSchemeTheme] = React.useState<string>()
const navRef = React.useRef<HTMLDivElement>(null)
@@ -37,23 +40,25 @@ export function NavBar() {
}, [theme])
return (
<header className="sticky top-0 w-full p-2 bg-background z-[1] pb-0 mb-2 shadow-header">
<nav className={cx('rounded-lg p-2 w-full flex justify-between', { 'bg-slate-200': theme === 'light', 'bg-slate-900': theme === 'dark' })} ref={navRef}>
<ul className="flex gap-2">
<NavBarItem url="/ps7">ПС-7</NavBarItem>
<NavBarItem url="/pks35k">ПКС-35к</NavBarItem>
<AddGroupButton />
</ul>
<div className='flex gap-1 min-[500px]:gap-2'>
<Link href='https://github.com/VityaSchel/kspguti-schedule' target='_blank' rel='nofollower noreferrer'>
<Button variant='outline' size='icon' tabIndex={-1}>
<FaGithub />
</Button>
</Link>
<ThemeSwitcher />
</div>
</nav>
</header>
<NavContextProvider cacheAvailableFor={cacheAvailableFor}>
<header className="sticky top-0 w-full p-2 bg-background z-[1] pb-0 mb-2 shadow-header">
<nav className={cx('rounded-lg p-2 w-full flex justify-between', { 'bg-slate-200': theme === 'light', 'bg-slate-900': theme === 'dark' })} ref={navRef}>
<ul className="flex gap-2">
<NavBarItem url="/ps7">ПС-7</NavBarItem>
<NavBarItem url="/pks35k">ПКС-35к</NavBarItem>
<AddGroupButton />
</ul>
<div className='flex gap-1 min-[500px]:gap-2'>
<Link href='https://github.com/VityaSchel/kspguti-schedule' target='_blank' rel='nofollower noreferrer'>
<Button variant='outline' size='icon' tabIndex={-1}>
<FaGithub />
</Button>
</Link>
<ThemeSwitcher />
</div>
</nav>
</header>
</NavContextProvider>
)
}
@@ -62,12 +67,50 @@ function NavBarItem({ url, children }: React.PropsWithChildren<{
}>) {
const router = useRouter()
const isActive = router.asPath === url
const { cacheAvailableFor, isLoading, setIsLoading } = React.useContext(NavContext)
const handleStartLoading = async () => {
let isLoaded = false
const loadEnd = () => {
isLoaded = true
setIsLoading(false)
}
router.events.on('routeChangeComplete', loadEnd)
router.events.on('routeChangeError', loadEnd)
if (cacheAvailableFor.includes(url.slice(1))) {
await new Promise(resolve => setTimeout(resolve, 500))
if(isLoaded) return
}
setIsLoading(url)
return () => {
router.events.off('routeChangeComplete', loadEnd)
router.events.off('routeChangeError', loadEnd)
}
}
const button = (
<Button
tabIndex={-1} variant={isActive ? 'default' : 'secondary'}
disabled={Boolean(isLoading)}
loading={isLoading === url}
>
{children}
</Button>
)
return (
<li>
<Link href={url}>
<Button tabIndex={-1} variant={isActive ? 'default' : 'secondary'}>{children}</Button>
</Link>
{isLoading ? (
button
) : (
<Link href={url} onClick={handleStartLoading}>
{button}
</Link>
)}
</li>
)
}