import { useQuery } from "@tanstack/react-query"; import { createApiKey, deleteApiKey, getApiKeys, type ApiKey } from "api/api"; import { AsyncButton } from "../AsyncButton"; import { useEffect, useState } from "react"; import { Copy, Trash } from "lucide-react"; type CopiedState = { x: number; y: number; visible: boolean; }; export default function ApiKeysModal() { const [input, setInput] = useState('') const [loading, setLoading ] = useState(false) const [err, setError ] = useState() const [displayData, setDisplayData] = useState([]) const [copied, setCopied] = useState(null); const { isPending, isError, data, error } = useQuery({ queryKey: [ 'api-keys' ], queryFn: () => { return getApiKeys(); }, }); useEffect(() => { if (data) { setDisplayData(data) } }, [data]) if (isError) { return (

Error: {error.message}

) } if (isPending) { return (

Loading...

) } const handleCopy = (e: React.MouseEvent, text: string) => { navigator.clipboard.writeText(text); const parentRect = (e.currentTarget.closest(".relative") as HTMLElement).getBoundingClientRect(); const buttonRect = e.currentTarget.getBoundingClientRect(); setCopied({ x: buttonRect.left - parentRect.left + buttonRect.width / 2, // center of button y: buttonRect.top - parentRect.top - 8, // above the button visible: true, }); setTimeout(() => setCopied(null), 1500); }; const handleCreateApiKey = () => { setError(undefined) if (input === "") { setError("a label must be provided") return } setLoading(true) createApiKey(input) .then(r => { setDisplayData([r, ...displayData]) setInput('') }).catch((err) => setError(err.message)) setLoading(false) } const handleDeleteApiKey = (id: number) => { setError(undefined) setLoading(true) deleteApiKey(id) .then(r => { if (r.ok) { setDisplayData(displayData.filter((v) => v.id != id)) } else { r.json().then((r) => setError(r.error)) } }) setLoading(false) } return (

API Keys

{displayData.map((v) => (
{v.key.slice(0, 8)+'...'} {v.label}
handleDeleteApiKey(v.id)} confirm>
))}
setInput(e.target.value)} /> Create
{err &&

{err}

} {copied?.visible && (
Copied!
)}
) }