import { type LoaderFunctionArgs, type ActionFunctionArgs, } from "@remix-run/server-runtime"; import { Plus, Copy } from "lucide-react"; import { Button } from "~/components/ui"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "~/components/ui/dialog"; import { useFetcher } from "@remix-run/react"; import { Input } from "~/components/ui/input"; import { useState } from "react"; import { parse } from "@conform-to/zod"; import { json } from "@remix-run/node"; import { z } from "zod"; import { createPersonalAccessToken, getValidPersonalAccessTokens, revokePersonalAccessToken, } from "~/services/personalAccessToken.server"; import { requireUserId } from "~/services/session.server"; import { useTypedLoaderData } from "remix-typedjson"; import { APITable } from "~/components/api"; import { SettingSection } from "~/components/setting-section"; export const APIKeyBodyRequest = z.object({ name: z.string(), }); export const APIKeyDeleteBodyRequest = z.object({ id: z.string(), }); export async function action({ request }: ActionFunctionArgs) { const userId = await requireUserId(request); if (request.method === "DELETE") { const formData = await request.formData(); const submission = parse(formData, { schema: APIKeyDeleteBodyRequest, }); if (!submission.value || submission.intent !== "submit") { return json(submission); } const results = await revokePersonalAccessToken(submission.value.id); return json(results); } const formData = await request.formData(); const submission = parse(formData, { schema: APIKeyBodyRequest, }); if (!submission.value || submission.intent !== "submit") { return json(submission); } const results = await createPersonalAccessToken({ name: submission.value.name, userId, }); return json(results); } export async function loader({ request }: LoaderFunctionArgs) { const userId = await requireUserId(request); const personalAccessTokens = await getValidPersonalAccessTokens(userId); return personalAccessTokens; } export default function API() { const personalAccessTokens = useTypedLoaderData(); const [open, setOpen] = useState(false); const [showToken, setShowToken] = useState(false); const fetcher = useFetcher<{ token: string }>(); const isSubmitting = fetcher.state !== "idle"; const [name, setName] = useState(""); const onSubmit = async (event: React.FormEvent) => { fetcher.submit({ name }, { method: "POST", action: "/settings/api" }); setOpen(false); setShowToken(true); }; const copyToClipboard = (text: string | undefined) => { text && navigator.clipboard.writeText(text); }; return (
} description="Create and manage API keys to access your data programmatically." >
Create API Key
setName(e.target.value)} name="name" placeholder="Enter API key name" className="mt-1" required />
Your New API Key

Make sure to copy your API key now. You won't be able to see it again!

{fetcher.data?.token}
); }