import { useEffect, useState, type FormEvent } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import { useAuth } from '@/auth/AuthContext' import { meta } from '@/api/client' import type { MetaInfo } from '@/types/api' import { ErrorBox } from '@/components/ErrorBox' interface LocationState { from?: string } export function LoginPage() { const { login, token, loading } = useAuth() const navigate = useNavigate() const location = useLocation() const [username, setUsername] = useState('admin') const [password, setPassword] = useState('') const [error, setError] = useState(null) const [info, setInfo] = useState(null) useEffect(() => { meta.info().then(setInfo).catch(() => setInfo(null)) }, []) // If already logged in (e.g. nav back to /login), bounce to dashboard. useEffect(() => { if (token) { const dest = (location.state as LocationState | null)?.from ?? '/' navigate(dest, { replace: true }) } }, [token, navigate, location.state]) const onSubmit = async (e: FormEvent) => { e.preventDefault() setError(null) try { await login(username, password) // Effect above handles the redirect; nothing else to do here. } catch (err: unknown) { setError(err instanceof Error ? err : new Error(String(err))) } } return (

vibe_erp

Composable ERP framework for the printing industry

setUsername(e.target.value)} className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm shadow-sm focus:border-brand-500 focus:ring-brand-500" required autoFocus />
setPassword(e.target.value)} className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm shadow-sm focus:border-brand-500 focus:ring-brand-500" required />

The bootstrap admin password is printed to the application boot log on first start.

{error ? : null}

{info ? ( <> Connected to {info.name}{' '} {info.implementationVersion} ) : ( 'Connecting…' )}

) }