keys-form.tsx99 lines · main
1'use client';
2
3import { useState } from 'react';
4
5export function BrivenEngineKeysForm() {
6 const [projectId, setProjectId] = useState('');
7 const [name, setName] = useState('app key');
8 const [plaintext, setPlaintext] = useState<string | null>(null);
9 const [status, setStatus] = useState<string | null>(null);
10 const [busy, setBusy] = useState(false);
11
12 async function onCreate(e: React.FormEvent) {
13 e.preventDefault();
14 setStatus(null);
15 setPlaintext(null);
16 if (!projectId.trim()) {
17 setStatus('Project id required.');
18 return;
19 }
20 setBusy(true);
21 try {
22 const origin =
23 process.env.NEXT_PUBLIC_BRIVEN_API_ORIGIN?.replace(/\/$/, '') ||
24 'https://api.briven.tech';
25 const res = await fetch(
26 `${origin}/v1/auth-core/projects/${encodeURIComponent(projectId.trim())}/keys`,
27 {
28 method: 'POST',
29 headers: { 'content-type': 'application/json' },
30 credentials: 'include',
31 body: JSON.stringify({ name }),
32 },
33 );
34 const body = (await res.json().catch(() => ({}))) as {
35 key?: { plaintext?: string; hint?: string };
36 message?: string;
37 note?: string;
38 };
39 if (!res.ok) {
40 setStatus(body.message ?? `Create failed (${res.status})`);
41 } else {
42 setPlaintext(body.key?.plaintext ?? null);
43 setStatus(body.note ?? 'Key created. Copy it now.');
44 }
45 } catch (err) {
46 setStatus(err instanceof Error ? err.message : 'Network error');
47 } finally {
48 setBusy(false);
49 }
50 }
51
52 return (
53 <form
54 onSubmit={onCreate}
55 className="flex max-w-lg flex-col gap-3 rounded-md border p-4"
56 style={{ borderColor: 'var(--auth-accent-border, var(--color-border))' }}
57 >
58 <p className="font-mono text-sm text-[var(--color-text)]">create API key</p>
59 <label className="flex flex-col gap-1 font-mono text-xs text-[var(--color-text-muted)]">
60 Project id
61 <input
62 className="rounded border bg-transparent px-2 py-1.5 text-[var(--color-text)]"
63 style={{ borderColor: 'var(--auth-accent-border, var(--color-border))' }}
64 value={projectId}
65 onChange={(e) => setProjectId(e.target.value)}
66 placeholder="p_…"
67 />
68 </label>
69 <label className="flex flex-col gap-1 font-mono text-xs text-[var(--color-text-muted)]">
70 Key name
71 <input
72 className="rounded border bg-transparent px-2 py-1.5 text-[var(--color-text)]"
73 style={{ borderColor: 'var(--auth-accent-border, var(--color-border))' }}
74 value={name}
75 onChange={(e) => setName(e.target.value)}
76 />
77 </label>
78 <button
79 type="submit"
80 disabled={busy}
81 className="rounded px-3 py-2 font-mono text-xs font-medium text-black disabled:opacity-50"
82 style={{ background: 'var(--auth-accent, #FFFD74)' }}
83 >
84 {busy ? 'Creating…' : 'Create key'}
85 </button>
86 {status ? (
87 <p className="font-mono text-[10px] text-[var(--color-text-muted)]">{status}</p>
88 ) : null}
89 {plaintext ? (
90 <div
91 className="break-all rounded border p-2 font-mono text-[11px] text-[var(--color-text)]"
92 style={{ borderColor: 'var(--auth-accent-border, var(--color-border))' }}
93 >
94 {plaintext}
95 </div>
96 ) : null}
97 </form>
98 );
99}