import { useState } from "react" import { withRefresh } from "@/api/with-refresh.ts" import { orgStore } from "@/auth/org.ts" import { makeOrgsApi } from "@/sdkClient.ts" import { zodResolver } from "@hookform/resolvers/zod" import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query" import { useForm } from "react-hook-form" import { toast } from "sonner" import { z } from "zod" import { Button } from "@/components/ui/button.tsx" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx" import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog.tsx" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form.tsx" import { Input } from "@/components/ui/input.tsx" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table.tsx" const createSchema = z.object({ name: z.string(), expires_in_hours: z.number().min(1).max(43800), }) type CreateValues = z.infer export const OrgApiKeys = () => { const api = makeOrgsApi() const qc = useQueryClient() const orgId = orgStore.get() const q = useQuery({ enabled: !!orgId, queryKey: ["org:keys", orgId], queryFn: () => withRefresh(() => api.listOrgKeys({ id: orgId! })), }) const form = useForm({ resolver: zodResolver(createSchema), defaultValues: { name: "", expires_in_hours: 720, }, }) const [showSecret, setShowSecret] = useState<{ key?: string secret?: string } | null>(null) const createMut = useMutation({ mutationFn: (v: CreateValues) => api.createOrgKey({ id: orgId!, body: v }), onSuccess: (resp) => { void qc.invalidateQueries({ queryKey: ["org:keys", orgId] }) setShowSecret({ key: resp.org_key, secret: resp.org_secret }) toast.success("Key created") form.reset({ name: "", expires_in_hours: undefined }) }, onError: (e: any) => toast.error(e?.message ?? "Failed to create key"), }) const deleteMut = useMutation({ mutationFn: (keyId: string) => api.deleteOrgKey({ id: orgId!, keyId }), onSuccess: () => { void qc.invalidateQueries({ queryKey: ["org:keys", orgId] }) toast.success("Key deleted") }, onError: (e: any) => toast.error(e?.message ?? "Failed to delete key"), }) if (!orgId) return

Pick an organization.

if (q.isLoading) return

Loading...

if (q.error) return

Failed to load keys.

return ( Org API Keys
createMut.mutate(v))} className="grid grid-cols-1 items-end gap-3 md:grid-cols-12" >
( Name )} />
( Expires In (hours) )} />
Name Scope Created Expires {q.data?.map((k) => ( {k.name ?? "-"} {k.scope} {new Date(k.created_at!).toLocaleString()} {k.expires_at ? new Date(k.expires_at).toLocaleString() : "-"} ))} {q.data?.length === 0 && ( No keys. )}
{/* Show once dialog with key/secret */} !o && setShowSecret(null)}> Copy your credentials
Org Key
e.currentTarget.select()} />
Org Secret
e.currentTarget.select()} />

This secret is shown once. Store it securely.

) }