import { json, redirect } from '@remix-run/node'; import { useActionData, useNavigate, useOutletContext } from '@remix-run/react'; import { format, formatDistanceToNow } from 'date-fns'; import { useEffect, useRef, useState } from 'react'; import { z } from 'zod'; import { BackButton } from '../components/BackButton'; import { Button } from '../components/Button'; import * as Drawer from '../components/Drawer'; import { RefreshCcw01 } from '../icons/RefreshCcw01'; import * as RotateApiKeyConfirmDialog from '../components/RotateApiKeyConfirmDialog'; import { getSignedInUser } from '../auth.server'; import { validateFormData } from '../utils/utils'; import { createAppKey, deleteAppKey, getAppById } from '../data/zippo.server'; import { BlurredInputWithCopy } from '../components/BlurredInputWithCopy'; import type { ActionArgs } from '@remix-run/node'; import type { AppOutletContext } from './_dashboard.app.$appId'; import type { ErrorWithGeneral } from '../types'; const actionFromModel = z.object({ name: z.string(), keyId: z.string(), appId: z.string(), }); type ActionInput = z.TypeOf; type Errors = ErrorWithGeneral>; export async function action({ request }: ActionArgs) { const [user, headers] = await getSignedInUser(request); if (!user) { throw redirect('/create-account', { headers }); } const formData = await request.formData(); const { body, errors } = validateFormData({ formData, schema: actionFromModel, }); if (errors !== null) { console.warn(errors); return json({ errors: { general: 'Something went wrong. Try again. ' } as Errors }, { headers }); } const app = await getAppById(body.appId); if (app.result === 'ERROR') { console.warn(app.error); return json({ errors: { general: 'Something went wrong. Try again. ' } as Errors }, { headers }); } if (app.data.name !== body.name) { return json( { errors: { name: 'App name does not match', } as Errors, }, { headers }, ); } //TODO: replace it with a single endpoint once zippo implements it const deleteAppKeyResult = await deleteAppKey(body.keyId); if (deleteAppKeyResult.result === 'ERROR') { return json({ errors: { general: 'Cannot remove key' } as Errors }, { headers }); } const createAppKeyResult = await createAppKey({ appId: body.appId, teamId: user.teamId, }); if (createAppKeyResult.result === 'ERROR') { return json({ errors: { general: 'Cannot create new key' } as Errors }, { headers }); } return json({ errors: null }, { headers }); } export default function AppSettings() { const navigate = useNavigate(); const actionData = useActionData(); const { app } = useOutletContext(); const apiKey = app.apiKeys[0]; const containerRef = useRef(null); const [containerRefValue, setContainerRefValue] = useState(); const [rotateApiKeyDialogOpen, setRotateApiKeyDialogOpen] = useState(false); useEffect(() => { if (actionData?.errors === null) { setRotateApiKeyDialogOpen(false); } }, [actionData]); useEffect(() => { setContainerRefValue(containerRef.current); }, [setContainerRefValue]); const createdAt = Date.parse(apiKey.createdAt.toString()); return ( <> { if (!open) { navigate(-1); } }} >
Your API Key
This key will allow you to authenticate API requests to 0x.{' '} Specify the key in your requests via the 0x-api-key header parameter.
Created on
{formatDistanceToNow(createdAt, { addSuffix: true })}
{/*
Last request to this API key
-
*/}
); }