spb/crypto-trade-bot
Public
Python 54.7%
TypeScript 42.5%
SQL 1.9%
1"use client";2import { Gauge } from "lucide-react";3import { useRouter, useSearchParams } from "next/navigation";4import { Suspense, useState } from "react";5import { api, ApiError } from "@/lib/api";6import { Button, Field, Input } from "@/components/ui";78function LoginForm() {9 const router = useRouter();10 const params = useSearchParams();11 const [pw, setPw] = useState("");12 const [err, setErr] = useState<string | null>(null);13 const [busy, setBusy] = useState(false);14 async function submit(e: React.FormEvent) {15 e.preventDefault();16 setBusy(true);17 setErr(null);18 try {19 await api("/api/auth/login", { method: "POST", json: { password: pw } });20 const next = params.get("next");21 router.replace(next && next.startsWith("/") ? next : "/");22 } catch (e) {23 setErr(e instanceof ApiError ? e.message : "login failed");24 } finally {25 setBusy(false);26 }27 }28 return (29 <form onSubmit={submit} className="w-full max-w-sm rounded-lg border border-line bg-bg-elev p-6">30 <div className="mb-5 flex items-center gap-2">31 <Gauge className="h-5 w-5 text-accent" aria-hidden />32 <div>33 <h1 className="text-base font-semibold">ktrade</h1>34 <p className="text-xs text-fg-muted">Kraken quantitative trading terminal — owner access</p>35 </div>36 </div>37 <Field label="Owner password" htmlFor="pw">38 <Input id="pw" type="password" autoComplete="current-password" value={pw} onChange={(e) => setPw(e.target.value)} required autoFocus />39 </Field>40 {err && <p role="alert" className="mt-3 text-xs text-down">{err}</p>}41 <Button type="submit" variant="primary" className="mt-4 w-full" loading={busy}>Sign in</Button>42 <p className="mt-4 text-[11px] text-fg-dim">Sessions are HttpOnly cookies signed server-side. Live trading stays disabled regardless of login.</p>43 </form>44 );45}4647export default function LoginPage() {48 return (49 <div className="flex min-h-screen items-center justify-center p-4">50 <Suspense>51 <LoginForm />52 </Suspense>53 </div>54 );55}56