import { useMemo, useState } from 'react' import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers' import { applyStoredTheme } from '../../lib/themeUpdater' import { useGetApiKeysQuery } from '../../lib/networking/queries/useGetApiKeysQuery' import { generateApiKeyMutation } from '../../lib/networking/mutations/generateApiKeyMutation' import { revokeApiKeyMutation } from '../../lib/networking/mutations/revokeApiKeyMutation' import { FormInputProps } from '../../components/elements/FormElements' import { FormModal } from '../../components/patterns/FormModal' import { ConfirmationModal } from '../../components/patterns/ConfirmationModal' import { EmptySettingsRow, SettingsTable, SettingsTableRow, } from '../../components/templates/settings/SettingsTable' import { StyledText } from '../../components/elements/StyledText' import { formattedShortDate } from '../../lib/dateFormatting' export default function Api(): JSX.Element { const { apiKeys, revalidate, isValidating } = useGetApiKeysQuery() const [onDeleteId, setOnDeleteId] = useState('') const [addModalOpen, setAddModalOpen] = useState(false) const [name, setName] = useState('') const [value, setValue] = useState('') const [expiresAt, setExpiresAt] = useState(new Date()) const [formInputs, setFormInputs] = useState([]) const [apiKeyGenerated, setApiKeyGenerated] = useState('') const neverExpiresDate = new Date(8640000000000000) const defaultExpiresAt = 'Never' applyStoredTheme() async function onDelete(id: string): Promise { const result = await revokeApiKeyMutation(id) if (result) { showSuccessToast('API Key deleted', { position: 'bottom-right' }) } else { showErrorToast('Failed to delete', { position: 'bottom-right' }) } revalidate() } async function onCreate(): Promise { const result = await generateApiKeyMutation({ name, expiresAt }) if (result) { setApiKeyGenerated(result) showSuccessToast('API key generated', { position: 'bottom-right' }) } else { showErrorToast('Failed to add', { position: 'bottom-right' }) } revalidate() } function onAdd() { return setFormInputs([ { label: 'Name', onChange: setName, name: 'name', value: value, required: true, }, { label: 'Expires', name: 'expiredAt', required: true, onChange: (e) => { let additionalDays = 0 switch (e.target.value) { case 'in 7 days': additionalDays = 7 break case 'in 30 days': additionalDays = 30 break case 'in 90 days': additionalDays = 90 break case 'in 1 year': additionalDays = 365 break case 'Never': break } const newExpires = additionalDays ? new Date() : neverExpiresDate if (additionalDays) { newExpires.setDate(newExpires.getDate() + additionalDays) } setExpiresAt(newExpires) }, type: 'select', options: [ 'in 7 days', 'in 30 days', 'in 90 days', 'in 1 year', 'Never', ], value: defaultExpiresAt, }, ]) } const sortedApiKeys = useMemo(() => { if (!apiKeys) { return [] } return apiKeys.sort((a, b) => a.createdAt.localeCompare(b.createdAt)) }, [apiKeys]) return ( { onAdd() setName('') setExpiresAt(neverExpiresDate) setAddModalOpen(true) }} > {sortedApiKeys.length > 0 ? ( sortedApiKeys.map((apiKey, i) => { return ( { console.log('onDelete triggered: ', apiKey.id) setOnDeleteId(apiKey.id) }} deleteTitle="Delete" sublineElement={ {`Last used: ${ apiKey.usedAt ? formattedShortDate(apiKey.usedAt) : 'Never' }, `} {`Created: ${formattedShortDate(apiKey.createdAt)}, `} {apiKey.expiresAt && apiKey.expiresAt != neverExpiresDate.toISOString() ? `Expires: ${formattedShortDate(apiKey.expiresAt)}` : 'Never expires'} } /> ) }) ) : ( )} {addModalOpen && ( )} {apiKeyGenerated && ( { await navigator.clipboard.writeText(apiKeyGenerated) setApiKeyGenerated('') }} onOpenChange={() => setApiKeyGenerated('')} /> )} {onDeleteId && ( { await onDelete(onDeleteId) setOnDeleteId('') }} onOpenChange={() => setOnDeleteId('')} /> )} ) }