Spaces:
Sleeping
Sleeping
File size: 3,552 Bytes
1e5ae4b cc20f66 1e5ae4b cc20f66 1e5ae4b cc20f66 1e5ae4b cc20f66 1e5ae4b 53a811b 1e5ae4b cc20f66 1e5ae4b cc20f66 1e5ae4b cc20f66 1e5ae4b cc20f66 1e5ae4b 53a811b 1e5ae4b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | import { Copy, KeyRound } from 'lucide-react';
import { useState } from 'react';
import { toast } from 'sonner';
import { ConfigError } from '@/components/admin/admin-form-parts';
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Spinner } from '@/components/ui/spinner';
import { generateApiKey } from '@/lib/rag-client';
import type { GeneratedApiKey } from '@/types/admin';
export function AdminApiKeyCard() {
const [generatedApiKey, setGeneratedApiKey] =
useState<GeneratedApiKey | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | undefined>();
async function handleGenerateApiKey(): Promise<void> {
setIsLoading(true);
setError(undefined);
try {
const result = await generateApiKey();
setGeneratedApiKey(result);
} catch (e) {
setError(
e instanceof Error ? e.message : 'Gagal membuat API key.',
);
} finally {
setIsLoading(false);
}
}
function handleCopyApiKey(): void {
if (!generatedApiKey?.api_key) {
return;
}
void navigator.clipboard.writeText(generatedApiKey.api_key);
toast.success('API key disalin.');
}
return (
<Card className="border-(--lecturer-border) bg-(--lecturer-surface)">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<KeyRound className="size-5 text-(--lecturer-primary)" />
API Key Iframe
</CardTitle>
<CardDescription>
API key hanya ditampilkan sekali setelah dibuat.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-4">
<Button
disabled={isLoading}
onClick={() => {
void handleGenerateApiKey();
}}
type="button"
>
{isLoading ? (
<Spinner className="size-4" />
) : (
<KeyRound className="size-4" />
)}
Generate API Key
</Button>
<ConfigError message={error} />
{generatedApiKey ? (
<div className="grid gap-3 rounded-xl border border-(--lecturer-border) bg-(--lecturer-surface) p-4">
<Label>API Key Baru</Label>
<div className="flex gap-2">
<Input readOnly value={generatedApiKey.api_key} />
<Button
onClick={handleCopyApiKey}
type="button"
variant="outline"
>
<Copy className="size-4" />
</Button>
</div>
<p className="text-sm text-muted-foreground">
Expired: {generatedApiKey.expires_at ?? '-'}
</p>
</div>
) : null}
</CardContent>
</Card>
);
}
|