import { useEffect, useState } from 'react' interface User { email: string name: string is_admin: boolean } interface Props { children: (user: User) => React.ReactNode } export function AuthGate({ children }: Props) { const [state, setState] = useState<'checking' | 'authed' | 'login'>('checking') const [user, setUser] = useState(null) const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [error, setError] = useState('') const [loading, setLoading] = useState(false) useEffect(() => { fetch('/api/auth/verify?app=noticeboard', { credentials: 'include' }) .then(async r => { if (r.ok) { const data = await r.json() setUser(data) setState('authed') } else { setState('login') } }) .catch(() => setState('login')) }, []) async function login(e: React.FormEvent) { e.preventDefault() setLoading(true) setError('') try { const res = await fetch('/api/auth/login', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), }) if (!res.ok) { setError('Invalid email or password') return } const verify = await fetch('/api/auth/verify?app=noticeboard', { credentials: 'include' }) if (verify.ok) { const data = await verify.json() setUser(data) setState('authed') } else { setError("You don't have access to this app.") } } catch { setError('Connection error — please try again') } finally { setLoading(false) } } if (state === 'checking') { return (
Loading…
) } if (state === 'login') { return (

Noticeboard

{import.meta.env.VITE_HOTEL_NAME}

setEmail(e.target.value)} placeholder="Email" required autoComplete="email" style={inputStyle} /> setPassword(e.target.value)} placeholder="Password" required autoComplete="current-password" style={inputStyle} /> {error &&

{error}

}
) } return <>{children(user!)} } const inputStyle: React.CSSProperties = { background: 'var(--navy-dark)', border: '1px solid var(--surface-2)', borderRadius: '6px', color: 'var(--text)', padding: '0.625rem 0.75rem', fontSize: '1rem', width: '100%', outline: 'none', } const btnStyle: React.CSSProperties = { background: 'var(--gold)', color: 'var(--navy-dark)', border: 'none', borderRadius: '6px', padding: '0.625rem', fontSize: '1rem', fontWeight: 600, marginTop: '0.25rem', }