Add loading indicator to group switcher
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user