| 1 | "use client"; |
| 2 | import { Suspense, useEffect, useState } from "react"; |
| 3 | import { useRouter, useSearchParams } from "next/navigation"; |
| 4 | import { api, API_BASE, setToken } from "@/lib/api"; |
| 5 | |
| 6 | function LoginInner() { |
| 7 | const [email, setEmail] = useState("admin@sightline.app"); |
| 8 | const [password, setPassword] = useState("changeme123"); |
| 9 | const [err, setErr] = useState<string | null>(null); |
| 10 | const router = useRouter(); |
| 11 | const params = useSearchParams(); |
| 12 | |
| 13 | useEffect(() => { |
| 14 | const t = params.get("token"); |
| 15 | if (t) { setToken(t); router.push("/"); } |
| 16 | }, [params, router]); |
| 17 | |
| 18 | async function submit(e: React.FormEvent) { |
| 19 | e.preventDefault(); |
| 20 | setErr(null); |
| 21 | try { await api.login(email, password); router.push("/"); } |
| 22 | catch { setErr("Invalid credentials."); } |
| 23 | } |
| 24 | |
| 25 | return ( |
| 26 | <div style={{ maxWidth: 360 }}> |
| 27 | <h1>Sign in</h1> |
| 28 | <p className="muted">Demo: admin@sightline.app / changeme123 (created by the seed loader).</p> |
| 29 | <form onSubmit={submit} className="card" style={{ display: "grid", gap: 12 }}> |
| 30 | <label>Email<input value={email} onChange={(e) => setEmail(e.target.value)} style={{ width: "100%" }} /></label> |
| 31 | <label>Password<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} style={{ width: "100%" }} /></label> |
| 32 | {err && <div className="badge danger">{err}</div>} |
| 33 | <button className="primary" type="submit">Sign in</button> |
| 34 | </form> |
| 35 | <div className="card" style={{ marginTop: 12 }}> |
| 36 | <a href={`${API_BASE}/auth/oidc/login`}>Sign in with SSO (OIDC)</a> |
| 37 | <div className="muted" style={{ fontSize: 12 }}>Enabled only when an OIDC issuer is configured.</div> |
| 38 | </div> |
| 39 | </div> |
| 40 | ); |
| 41 | } |
| 42 | |
| 43 | export default function Login() { |
| 44 | return <Suspense fallback={<div className="muted">Loading…</div>}><LoginInner /></Suspense>; |
| 45 | } |