import { zodResolver } from "@hookform/resolvers/zod"; import { t } from "@lingui/core/macro"; import { Trans } from "@lingui/react/macro"; import { CopyIcon, PlusIcon } from "@phosphor-icons/react"; import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { useCopyToClipboard } from "usehooks-ts"; import z from "zod"; import { Button } from "@/components/ui/button"; import { Combobox } from "@/components/ui/combobox"; import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@/components/ui/input-group"; import { useFormBlocker } from "@/hooks/use-form-blocker"; import { authClient } from "@/integrations/auth/client"; import { type DialogProps, useDialogStore } from "../store"; const formSchema = z.object({ name: z.string().min(1).max(64), expiresIn: z.number().min(1), }); type FormValues = z.infer; export function CreateApiKeyDialog(_: DialogProps<"api-key.create">) { const [apiKey, setApiKey] = useState(null); if (apiKey) return ; return ; } type CreateApiKeyFormProps = { setApiKey: (apiKey: string) => void; }; const CreateApiKeyForm = ({ setApiKey }: CreateApiKeyFormProps) => { const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { name: "", expiresIn: 3600 * 24 * 30, }, }); const { blockEvents } = useFormBlocker(form); const onSubmit = async (values: FormValues) => { const toastId = toast.loading(t`Creating your API key...`); const { data, error } = await authClient.apiKey.create({ name: values.name, expiresIn: values.expiresIn, }); if (error) { toast.error(error.message, { id: toastId }); return; } setApiKey(data.key); toast.dismiss(toastId); }; return ( Create a new API key This will generate a new API key to access the Reactive Resume API to allow machines to interact with your resume data.
( Name } /> Tip: Give your API key a name, corresponding to the purpose of the key, to help you identify it later. )} /> ( Expires in value && field.onChange(Number(value))} options={[ { // 1 month = 30 days value: 3600 * 24 * 30, label: t`1 month`, }, { // 3 months = 90 days value: 3600 * 24 * 90, label: t`3 months`, }, { // 6 months = 180 days value: 3600 * 24 * 180, label: t`6 months`, }, { // 1 year = 365 days value: 3600 * 24 * 365, label: t`1 year`, }, ]} /> } /> )} />
); }; type CopyApiKeyFormProps = { apiKey: string; }; const CopyApiKeyForm = ({ apiKey }: CopyApiKeyFormProps) => { const queryClient = useQueryClient(); const [_, copyToClipboard] = useCopyToClipboard(); const closeDialog = useDialogStore((state) => state.closeDialog); const onCopy = () => { copyToClipboard(apiKey); toast.success(t`Your API key has been copied to the clipboard.`); }; const onConfirm = () => { closeDialog(); queryClient.invalidateQueries({ queryKey: ["auth", "api-keys"] }); }; return ( Here's your new API key Copy this secret key and use it in your applications to access your data.
For security reasons, this key will only be displayed once.
); };