41 lines
1.1 KiB
TypeScript
41 lines
1.1 KiB
TypeScript
import { useEffect, useState, createContext, useContext } from 'react'
|
|
import type { User } from '../types'
|
|
|
|
interface AuthCtx { user: User }
|
|
const Ctx = createContext<AuthCtx | null>(null)
|
|
|
|
export function useAuth() {
|
|
const ctx = useContext(Ctx)
|
|
if (!ctx) throw new Error('useAuth must be used inside AuthGate')
|
|
return ctx
|
|
}
|
|
|
|
export default function AuthGate({ children }: { children: React.ReactNode }) {
|
|
const [user, setUser] = useState<User | null>(null)
|
|
|
|
useEffect(() => {
|
|
fetch('/api/auth/verify?app=maintenance', { credentials: 'include' })
|
|
.then(r => {
|
|
if (!r.ok) {
|
|
;(window.top ?? window).location.href = '/login'
|
|
return null
|
|
}
|
|
return r.json()
|
|
})
|
|
.then(data => { if (data) setUser(data) })
|
|
.catch(() => { ;(window.top ?? window).location.href = '/login' })
|
|
}, [])
|
|
|
|
if (!user) {
|
|
return (
|
|
<div style={{
|
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
height: '100vh', fontFamily: 'var(--font)', color: 'var(--text-mid)'
|
|
}}>
|
|
Loading…
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return <Ctx.Provider value={{ user }}>{children}</Ctx.Provider>
|
|
}
|