spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1"use client";23import { KeyRound } from "lucide-react";4import { useActionState } from "react";5import { LogoMark } from "@/components/brand/logo";6import { Button } from "@/components/ui";7import { loginAction, type LoginState } from "@/app/admin/login/actions";89export function LoginForm({ next, reason }: { next: string; reason?: string }) {10 const [state, action, pending] = useActionState<LoginState, FormData>(loginAction, {});11 return (12 <div className="w-full max-w-[380px] rounded-sm border border-hair bg-surface">13 <div className="flex items-center gap-2.5 border-b border-hair px-4 py-3">14 <LogoMark size={22} />15 <div>16 <div className="text-[13.5px] font-semibold leading-tight text-ink">DataCenterIndex · Admin</div>17 <div className="text-[11.5px] text-ink-3">Operations console</div>18 </div>19 </div>20 <form action={action} className="space-y-3 px-4 py-4">21 <input type="hidden" name="next" value={next} />22 {reason === "expired" && !state.error && <p className="rounded-xs border border-warn/30 bg-warn/10 px-2.5 py-2 text-[12.5px] text-warn">Your session expired or the token was rejected. Sign in again.</p>}23 {reason === "logged-out" && !state.error && <p className="rounded-xs border border-hair bg-surface-2 px-2.5 py-2 text-[12.5px] text-ink-2">Signed out.</p>}24 <label className="block">25 <span className="label-caps mb-1 block">Admin token</span>26 <input27 name="token"28 type="password"29 autoComplete="current-password"30 required31 autoFocus32 spellCheck={false}33 className="h-10 w-full rounded-sm border border-hair-2 bg-paper px-3 font-mono text-[13px] text-ink outline-none focus:border-ink"34 placeholder="x-dci-admin-token"35 />36 </label>37 {state.error && (38 <p role="alert" className="rounded-xs border border-danger/30 bg-danger/10 px-2.5 py-2 text-[12.5px] text-danger">39 {state.error}40 </p>41 )}42 <Button type="submit" variant="primary" className="w-full" disabled={pending}>43 <KeyRound className="size-4" strokeWidth={1.75} />44 {pending ? "Checking…" : "Sign in"}45 </Button>46 <p className="text-[11.5px] leading-snug text-ink-4">The token is verified against the API and kept in an httpOnly cookie for 12 hours. It is never sent to the browser bundle.</p>47 </form>48 </div>49 );50}51