import type { AdminConsoleKey } from '@logto/phrases'; import type { Application } from '@logto/schemas'; import { conditional } from '@silverhand/essentials'; import type { KeyboardEvent } from 'react'; import { useContext, useRef } from 'react'; import { Controller, FormProvider, useForm } from 'react-hook-form'; import { toast } from 'react-hot-toast'; import { useTranslation } from 'react-i18next'; import useSWR from 'swr'; import { GuideContext } from '@/components/Guide'; import MultiTextInputField from '@/components/MultiTextInputField'; import Button from '@/ds-components/Button'; import { convertRhfErrorMessage, createValidatorForRhf, } from '@/ds-components/MultiTextInput/utils'; import type { RequestError } from '@/hooks/use-api'; import useApi from '@/hooks/use-api'; import type { GuideForm } from '@/types/guide'; import { trySubmitSafe } from '@/utils/form'; import { uriValidator } from '@/utils/validator'; import * as styles from './index.module.scss'; type Props = { name: 'redirectUris' | 'postLogoutRedirectUris'; /** The default value of the input field when there's no data. */ defaultValue?: string; }; function UriInputField({ name, defaultValue }: Props) { const methods = useForm>(); const { control, getValues, handleSubmit, reset, formState: { isSubmitting }, } = methods; const { app } = useContext(GuideContext); const appId = app?.id; const { data, mutate } = useSWR(appId && `api/applications/${appId}`); const ref = useRef(null); const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const api = useApi(); const title: AdminConsoleKey = name === 'redirectUris' ? 'application_details.redirect_uri' : 'application_details.post_sign_out_redirect_uri'; const onSubmit = trySubmitSafe(async (value: string[]) => { if (!appId) { return; } const updatedApp = await api .patch(`api/applications/${appId}`, { json: { oidcClientMetadata: { [name]: value.filter(Boolean), }, }, }) .json(); void mutate(updatedApp); toast.success(t('general.saved')); // Reset form to set 'isDirty' to false reset(getValues()); }); const onKeyPress = (event: KeyboardEvent, value: string[]) => { if (event.key === 'Enter') { event.preventDefault(); void handleSubmit(async () => onSubmit(value))(); } }; const clientMetadata = data?.oidcClientMetadata[name]; const defaultValueArray = clientMetadata?.length ? clientMetadata : conditional(defaultValue && [defaultValue]); return (
!value || uriValidator(value), message: t('errors.invalid_uri_format'), }, }), }} render={({ field: { onChange, value = [] }, fieldState: { error, isDirty } }) => { const errorObject = convertRhfErrorMessage(error?.message); return (
{ onKeyPress(event, value); }} />
); }} />
); } export default UriInputField;