✨(app-desk) create mailbox for a mail domain
Add form to create a mailbox for a mail domain. It sends a http POST request mail-domains/<mail-domain-id>/mailboxes/ on form submit. The form appears inside a modal. Installs react-hook-form, zod, and @hookform/resolvers for form manipulation and field validation.
This commit is contained in:
committed by
Sebastien Nobour
parent
37d32888f5
commit
6981ef17df
@@ -16,6 +16,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@gouvfr-lasuite/integration": "0.1.3",
|
||||
"@hookform/resolvers": "3.4.2",
|
||||
"@openfun/cunningham-react": "2.9.0",
|
||||
"@tanstack/react-query": "5.36.0",
|
||||
"i18next": "23.11.4",
|
||||
@@ -25,12 +26,15 @@
|
||||
"react": "*",
|
||||
"react-aria-components": "1.2.0",
|
||||
"react-dom": "*",
|
||||
"react-hook-form": "7.51.5",
|
||||
"react-i18next": "14.1.1",
|
||||
"react-select": "5.8.0",
|
||||
"styled-components": "6.1.11",
|
||||
"zod": "3.23.8",
|
||||
"zustand": "4.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hookform/devtools": "4.3.1",
|
||||
"@svgr/webpack": "8.1.0",
|
||||
"@tanstack/react-query-devtools": "5.36.0",
|
||||
"@testing-library/jest-dom": "6.4.5",
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { UUID } from 'crypto';
|
||||
|
||||
import {
|
||||
UseMutationOptions,
|
||||
useMutation,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
import { APIError, errorCauses, fetchAPI } from '@/api';
|
||||
|
||||
import { KEY_LIST_MAILBOX } from './useMailboxes';
|
||||
|
||||
export interface CreateMailboxParams {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
local_part: string;
|
||||
secondary_email: string;
|
||||
phone_number: string;
|
||||
mailDomainId: UUID;
|
||||
}
|
||||
|
||||
export const createMailbox = async ({
|
||||
mailDomainId,
|
||||
...data
|
||||
}: CreateMailboxParams): Promise<void> => {
|
||||
const response = await fetchAPI(`mail-domains/${mailDomainId}/mailboxes/`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
// TODO: extend errorCauses to return the name of the invalid field names to highlight in the form?
|
||||
throw new APIError(
|
||||
'Failed to create the mailbox',
|
||||
await errorCauses(response),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
type UseCreateMailboxParams = { domainId: UUID } & UseMutationOptions<
|
||||
void,
|
||||
APIError,
|
||||
CreateMailboxParams
|
||||
>;
|
||||
|
||||
export function useCreateMailbox(options: UseCreateMailboxParams) {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<void, APIError, CreateMailboxParams>({
|
||||
mutationFn: createMailbox,
|
||||
onSuccess: (data, variables, context) => {
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: [KEY_LIST_MAILBOX, { id: variables.mailDomainId }],
|
||||
});
|
||||
if (options?.onSuccess) {
|
||||
options.onSuccess(data, variables, context);
|
||||
}
|
||||
},
|
||||
onError: (error, variables, context) => {
|
||||
if (options?.onError) {
|
||||
options.onError(error, variables, context);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export const getMailDomainMailboxes = async ({
|
||||
return response.json() as Promise<MailDomainMailboxesResponse>;
|
||||
};
|
||||
|
||||
const KEY_LIST_MAILBOX = 'mailboxes';
|
||||
export const KEY_LIST_MAILBOX = 'mailboxes';
|
||||
|
||||
export function useMailDomainMailboxes(
|
||||
param: MailDomainMailboxesParams,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M21.34 26.04C20.9 26.02 20.46 26 20 26C15.16 26 10.64 27.34 6.78 29.64C5.02 30.68 4 32.64 4 34.7V40H22.52C20.94 37.74 20 34.98 20 32C20 29.86 20.5 27.86 21.34 26.04Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M20 24C24.4183 24 28 20.4183 28 16C28 11.5817 24.4183 8 20 8C15.5817 8 12 11.5817 12 16C12 20.4183 15.5817 24 20 24Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M33 24C28.032 24 24 28.032 24 33C24 37.968 28.032 42 33 42C37.968 42 42 37.968 42 33C42 28.032 37.968 24 33 24ZM36.6 33.9H33.9V36.6C33.9 37.095 33.495 37.5 33 37.5C32.505 37.5 32.1 37.095 32.1 36.6V33.9H29.4C28.905 33.9 28.5 33.495 28.5 33C28.5 32.505 28.905 32.1 29.4 32.1H32.1V29.4C32.1 28.905 32.505 28.5 33 28.5C33.495 28.5 33.9 28.905 33.9 29.4V32.1H36.6C37.095 32.1 37.5 32.505 37.5 33C37.5 33.495 37.095 33.9 36.6 33.9Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 925 B |
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
Button,
|
||||
DataGrid,
|
||||
Loader,
|
||||
SortModel,
|
||||
@@ -8,11 +9,13 @@ import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Card, Text, TextErrors } from '@/components';
|
||||
import { MailDomain } from '@/features/mail-domains';
|
||||
import { useMailDomainMailboxes } from '@/features/mail-domains/api/useMailDomainMailboxes';
|
||||
import { PAGE_SIZE } from '@/features/mail-domains/conf';
|
||||
|
||||
import { useMailboxes } from '../api/useMailboxes';
|
||||
import { default as MailDomainsLogo } from '../assets/mail-domains-logo.svg';
|
||||
import { PAGE_SIZE } from '../conf';
|
||||
import { MailDomain, MailDomainMailbox } from '../types';
|
||||
|
||||
import { CreateMailboxForm } from './forms/CreateMailboxForm';
|
||||
|
||||
export type ViewMailbox = { email: string; id: string };
|
||||
|
||||
@@ -44,6 +47,9 @@ function formatSortModel(
|
||||
export function MailDomainsContent({ mailDomain }: { mailDomain: MailDomain }) {
|
||||
const [sortModel, setSortModel] = useState<SortModel>([]);
|
||||
const { t } = useTranslation();
|
||||
const [isCreateMailboxFormVisible, setIsCreateMailboxFormVisible] =
|
||||
useState(false);
|
||||
|
||||
const pagination = usePagination({
|
||||
defaultPage: 1,
|
||||
pageSize: PAGE_SIZE,
|
||||
@@ -52,7 +58,7 @@ export function MailDomainsContent({ mailDomain }: { mailDomain: MailDomain }) {
|
||||
const { page, pageSize, setPagesCount } = pagination;
|
||||
const ordering = sortModel.length ? formatSortModel(sortModel[0]) : undefined;
|
||||
|
||||
const { data, isLoading, error } = useMailDomainMailboxes({
|
||||
const { data, isLoading, error } = useMailboxes({
|
||||
id: mailDomain.id,
|
||||
page,
|
||||
ordering,
|
||||
@@ -60,7 +66,7 @@ export function MailDomainsContent({ mailDomain }: { mailDomain: MailDomain }) {
|
||||
|
||||
const viewMailboxes: ViewMailbox[] =
|
||||
mailDomain && data?.results?.length
|
||||
? data.results.map((mailbox) => ({
|
||||
? data.results.map((mailbox: MailDomainMailbox) => ({
|
||||
email: `${mailbox.local_part}@${mailDomain.name}`,
|
||||
id: mailbox.id,
|
||||
}))
|
||||
@@ -75,7 +81,16 @@ export function MailDomainsContent({ mailDomain }: { mailDomain: MailDomain }) {
|
||||
</Box>
|
||||
) : (
|
||||
<>
|
||||
<TopBanner name={mailDomain.name} />
|
||||
{isCreateMailboxFormVisible && mailDomain ? (
|
||||
<CreateMailboxForm
|
||||
mailDomain={mailDomain}
|
||||
setIsFormVisible={setIsCreateMailboxFormVisible}
|
||||
/>
|
||||
) : null}
|
||||
<TopBanner
|
||||
name={mailDomain.name}
|
||||
setIsFormVisible={setIsCreateMailboxFormVisible}
|
||||
/>
|
||||
<Card
|
||||
$padding={{ bottom: 'small' }}
|
||||
$margin={{ all: 'big', top: 'none' }}
|
||||
@@ -104,20 +119,36 @@ export function MailDomainsContent({ mailDomain }: { mailDomain: MailDomain }) {
|
||||
);
|
||||
}
|
||||
|
||||
const TopBanner = ({ name }: { name: string }) => {
|
||||
const TopBanner = ({
|
||||
name,
|
||||
setIsFormVisible,
|
||||
}: {
|
||||
name: string;
|
||||
setIsFormVisible: (value: boolean) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$margin={{ all: 'big', vertical: 'xbig' }}
|
||||
$gap="2.25rem"
|
||||
>
|
||||
<MailDomainsLogo aria-label={t('Mail Domains icon')} />
|
||||
<Text $margin="none" as="h3" $size="h3">
|
||||
{name}
|
||||
</Text>
|
||||
</Box>
|
||||
<>
|
||||
<Box
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$margin={{ all: 'big', vertical: 'xbig' }}
|
||||
$gap="2.25rem"
|
||||
>
|
||||
<MailDomainsLogo aria-label={t('Mail Domains icon')} />
|
||||
<Text $margin="none" as="h3" $size="h3">
|
||||
{name}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box $margin={{ all: 'big', bottom: 'small' }} $align="flex-end">
|
||||
<Button
|
||||
aria-label={t(`Create a mailbox in {{name}} domain`, { name })}
|
||||
onClick={() => setIsFormVisible(true)}
|
||||
>
|
||||
{t('Create a mailbox')}
|
||||
</Button>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Modal,
|
||||
ModalSize,
|
||||
VariantType,
|
||||
useToastProvider,
|
||||
} from '@openfun/cunningham-react';
|
||||
import React from 'react';
|
||||
import {
|
||||
Controller,
|
||||
FormProvider,
|
||||
UseFormReturn,
|
||||
useForm,
|
||||
} from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Box, Text, TextErrors } from '@/components';
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
|
||||
import { CreateMailboxParams, useCreateMailbox } from '../../api';
|
||||
import IconCreateMailbox from '../../assets/create-mailbox.svg';
|
||||
import { MailDomain } from '../../types';
|
||||
|
||||
const FORM_ID: string = 'form-create-mailbox';
|
||||
|
||||
const createMailboxValidationSchema = z.object({
|
||||
first_name: z.string().min(1),
|
||||
last_name: z.string().min(1),
|
||||
local_part: z.string().min(1),
|
||||
secondary_email: z.string().min(1),
|
||||
phone_number: z.string().min(1),
|
||||
});
|
||||
|
||||
export const CreateMailboxForm = ({
|
||||
mailDomain,
|
||||
setIsFormVisible,
|
||||
}: {
|
||||
mailDomain: MailDomain;
|
||||
setIsFormVisible: (value: boolean) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToastProvider();
|
||||
const { colorsTokens } = useCunninghamTheme();
|
||||
|
||||
const methods = useForm<CreateMailboxParams>({
|
||||
delayError: 0,
|
||||
defaultValues: {
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
local_part: '',
|
||||
secondary_email: '',
|
||||
phone_number: '',
|
||||
},
|
||||
mode: 'onChange',
|
||||
reValidateMode: 'onChange',
|
||||
resolver: zodResolver(createMailboxValidationSchema),
|
||||
});
|
||||
|
||||
const { mutate: createMailbox, ...queryState } = useCreateMailbox({
|
||||
domainId: mailDomain.id,
|
||||
onSuccess: () => {
|
||||
toast(t('Mailbox created!'), VariantType.SUCCESS, {
|
||||
duration: 4000,
|
||||
});
|
||||
|
||||
setIsFormVisible(false);
|
||||
},
|
||||
});
|
||||
|
||||
const closeModal = () => setIsFormVisible(false);
|
||||
|
||||
const onSubmitCallback = (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
void methods.handleSubmit((data) =>
|
||||
createMailbox({ ...data, mailDomainId: mailDomain.id }),
|
||||
)();
|
||||
};
|
||||
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<Modal
|
||||
isOpen
|
||||
leftActions={
|
||||
<Button
|
||||
color="secondary"
|
||||
fullWidth
|
||||
onClick={closeModal}
|
||||
disabled={methods.formState.isSubmitting}
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
}
|
||||
onClose={closeModal}
|
||||
closeOnClickOutside
|
||||
hideCloseButton
|
||||
rightActions={
|
||||
<Button
|
||||
color="primary"
|
||||
fullWidth
|
||||
type="submit"
|
||||
form={FORM_ID}
|
||||
disabled={methods.formState.isSubmitting}
|
||||
>
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
}
|
||||
size={ModalSize.MEDIUM}
|
||||
title={
|
||||
<Box $align="center" $gap="1rem">
|
||||
<IconCreateMailbox
|
||||
width={48}
|
||||
color={colorsTokens()['primary-text']}
|
||||
title={t('Mailbox creation form')}
|
||||
/>
|
||||
<Text $size="h3" $margin="none" role="heading" aria-level={3}>
|
||||
{t('Create a mailbox')}
|
||||
</Text>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Box $width="100%" $margin={{ top: 'large', bottom: 'xl' }}>
|
||||
{queryState.isError && (
|
||||
<TextErrors className="mb-s" causes={queryState.error.cause} />
|
||||
)}
|
||||
{methods ? (
|
||||
<Form
|
||||
methods={methods}
|
||||
mailDomain={mailDomain}
|
||||
onSubmitCallback={onSubmitCallback}
|
||||
/>
|
||||
) : null}
|
||||
</Box>
|
||||
</Modal>
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const Form = ({
|
||||
methods,
|
||||
mailDomain,
|
||||
onSubmitCallback,
|
||||
}: {
|
||||
methods: UseFormReturn<CreateMailboxParams>;
|
||||
mailDomain: MailDomain;
|
||||
onSubmitCallback: (event: React.FormEvent) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmitCallback} id={FORM_ID}>
|
||||
<Box $direction="column" $width="100%" $gap="2rem" $margin="auto">
|
||||
<Box $margin={{ horizontal: 'none' }}>
|
||||
<Controller
|
||||
control={methods.control}
|
||||
name="first_name"
|
||||
render={({ fieldState }) => (
|
||||
<Input
|
||||
aria-invalid={!!fieldState.error}
|
||||
label={t('First name')}
|
||||
state={fieldState.error ? 'error' : 'default'}
|
||||
text={
|
||||
fieldState.error
|
||||
? t('Please enter your first name')
|
||||
: undefined
|
||||
}
|
||||
{...methods.register('first_name')}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box $margin={{ horizontal: 'none' }}>
|
||||
<Controller
|
||||
control={methods.control}
|
||||
name="last_name"
|
||||
render={({ fieldState }) => (
|
||||
<Input
|
||||
aria-invalid={!!fieldState.error}
|
||||
label={t('Last name')}
|
||||
state={fieldState.error ? 'error' : 'default'}
|
||||
text={
|
||||
fieldState.error
|
||||
? t('Please enter your last name')
|
||||
: undefined
|
||||
}
|
||||
{...methods.register('last_name')}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box $margin={{ horizontal: 'none' }} $direction="row">
|
||||
<Box $width="65%">
|
||||
<Controller
|
||||
control={methods.control}
|
||||
name="local_part"
|
||||
render={({ fieldState }) => (
|
||||
<Input
|
||||
aria-invalid={!!fieldState.error}
|
||||
label={t('Main email address')}
|
||||
state={fieldState.error ? 'error' : 'default'}
|
||||
text={
|
||||
fieldState.error
|
||||
? t(
|
||||
'Please enter the first part of the email address, without including "@" in it',
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
{...methods.register('local_part')}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Text
|
||||
as="span"
|
||||
$theme="primary"
|
||||
$size="1rem"
|
||||
$display="inline-block"
|
||||
$css={`
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
left: 1rem;
|
||||
top: 1rem;
|
||||
`}
|
||||
>
|
||||
@{mailDomain.name}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box $margin={{ horizontal: 'none' }}>
|
||||
<Controller
|
||||
control={methods.control}
|
||||
name="secondary_email"
|
||||
render={({ fieldState }) => (
|
||||
<Input
|
||||
aria-invalid={!!fieldState.error}
|
||||
label={t('Secondary email address')}
|
||||
state={fieldState.error ? 'error' : 'default'}
|
||||
text={
|
||||
fieldState.error
|
||||
? t('Please enter your secondary email address')
|
||||
: undefined
|
||||
}
|
||||
{...methods.register('secondary_email')}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box $margin={{ horizontal: 'none' }}>
|
||||
<Controller
|
||||
control={methods.control}
|
||||
name="phone_number"
|
||||
render={({ fieldState }) => (
|
||||
<Input
|
||||
aria-invalid={!!fieldState.error}
|
||||
label={t('Phone number')}
|
||||
state={fieldState.error ? 'error' : 'default'}
|
||||
text={
|
||||
fieldState.error
|
||||
? t('Please enter your phone number')
|
||||
: undefined
|
||||
}
|
||||
{...methods.register('phone_number')}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './components/';
|
||||
export * from './components';
|
||||
export * from './types';
|
||||
export * from './api';
|
||||
export * from './store';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './useMailDomainsStore';
|
||||
@@ -1120,7 +1120,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
|
||||
integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==
|
||||
|
||||
"@emotion/is-prop-valid@1.2.2":
|
||||
"@emotion/is-prop-valid@1.2.2", "@emotion/is-prop-valid@^1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337"
|
||||
integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==
|
||||
@@ -1132,7 +1132,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
|
||||
integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
|
||||
|
||||
"@emotion/react@^11.8.1":
|
||||
"@emotion/react@^11.1.5", "@emotion/react@^11.8.1":
|
||||
version "11.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.4.tgz#3a829cac25c1f00e126408fab7f891f00ecc3c1d"
|
||||
integrity sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==
|
||||
@@ -1146,7 +1146,7 @@
|
||||
"@emotion/weak-memoize" "^0.3.1"
|
||||
hoist-non-react-statics "^3.3.1"
|
||||
|
||||
"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3":
|
||||
"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3", "@emotion/serialize@^1.1.4":
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.4.tgz#fc8f6d80c492cfa08801d544a05331d1cc7cd451"
|
||||
integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==
|
||||
@@ -1162,6 +1162,18 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec"
|
||||
integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==
|
||||
|
||||
"@emotion/styled@^11.3.0":
|
||||
version "11.11.5"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.5.tgz#0c5c8febef9d86e8a926e663b2e5488705545dfb"
|
||||
integrity sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.18.3"
|
||||
"@emotion/babel-plugin" "^11.11.0"
|
||||
"@emotion/is-prop-valid" "^1.2.2"
|
||||
"@emotion/serialize" "^1.1.4"
|
||||
"@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
|
||||
"@emotion/utils" "^1.2.1"
|
||||
|
||||
"@emotion/unitless@0.8.1", "@emotion/unitless@^0.8.1":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3"
|
||||
@@ -1403,6 +1415,25 @@
|
||||
resolved "https://registry.yarnpkg.com/@gouvfr-lasuite/integration/-/integration-0.1.3.tgz#cbf44473cd2a5b9497814faff459c3d88bc1ddce"
|
||||
integrity sha512-WvAaMyEcNZkNX88Rbi6xo1rxFIGjsg3w8Gxi5NKVyNY0Ph2dXcGkP63ybCKD8JAsWHfxwAvs82wqXFZk5RCJ1g==
|
||||
|
||||
"@hookform/devtools@4.3.1":
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@hookform/devtools/-/devtools-4.3.1.tgz#5df1b77ea12b4f1c220da3d2dba737f81cbb12bc"
|
||||
integrity sha512-CrWxEoHQZaOXJZVQ8KBgOuAa8p2LI8M0DAN5GTRTmdCieRwFVjVDEmuTAVazWVRRkpEQSgSt3KYp7VmmqXdEnw==
|
||||
dependencies:
|
||||
"@emotion/react" "^11.1.5"
|
||||
"@emotion/styled" "^11.3.0"
|
||||
"@types/lodash" "^4.14.168"
|
||||
little-state-machine "^4.1.0"
|
||||
lodash "^4.17.21"
|
||||
react-simple-animate "^3.3.12"
|
||||
use-deep-compare-effect "^1.8.1"
|
||||
uuid "^8.3.2"
|
||||
|
||||
"@hookform/resolvers@3.4.2":
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-3.4.2.tgz#b69525248c2a9a1b2546411251ea25029915841a"
|
||||
integrity sha512-1m9uAVIO8wVf7VCDAGsuGA0t6Z3m6jVGAN50HkV9vYLl0yixKK/Z1lr01vaRvYCkIKGoy1noVRxMzQYb4y/j1Q==
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.14":
|
||||
version "0.11.14"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
|
||||
@@ -3393,6 +3424,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.1.tgz#0fabfcf2f2127ef73b119d98452bd317c4a17eb8"
|
||||
integrity sha512-X+2qazGS3jxLAIz5JDXDzglAF3KpijdhFxlf/V1+hEsOUc+HnWi81L/uv/EvGuV90WY+7mPGFCUDGfQC3Gj95Q==
|
||||
|
||||
"@types/lodash@^4.14.168":
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.4.tgz#0303b64958ee070059e3a7184048a55159fe20b7"
|
||||
integrity sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==
|
||||
|
||||
"@types/luxon@3.4.2":
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.4.2.tgz#e4fc7214a420173cea47739c33cdf10874694db7"
|
||||
@@ -4704,7 +4740,7 @@ delayed-stream@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||
|
||||
dequal@^2.0.3:
|
||||
dequal@^2.0.2, dequal@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
|
||||
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
|
||||
@@ -6991,6 +7027,11 @@ lines-and-columns@^1.1.6:
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
little-state-machine@^4.1.0:
|
||||
version "4.8.0"
|
||||
resolved "https://registry.yarnpkg.com/little-state-machine/-/little-state-machine-4.8.0.tgz#4853d01f71dc7e15fec00193692f845020a57686"
|
||||
integrity sha512-xfi5+iDxTLhu0hbnNubUs+qoQQqxhtEZeObP5ELjUlHnl74bbasY7mOonsGQrAouyrbag3ebNLSse5xX1T7buQ==
|
||||
|
||||
locate-path@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
|
||||
@@ -7885,6 +7926,11 @@ react-dom@*, react-dom@18.2.0, react-dom@18.3.1:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react-hook-form@7.51.5:
|
||||
version "7.51.5"
|
||||
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.51.5.tgz#4afbfb819312db9fea23e8237a3a0d097e128b43"
|
||||
integrity sha512-J2ILT5gWx1XUIJRETiA7M19iXHlG74+6O3KApzvqB/w8S5NQR7AbU8HVZrMALdmDgWpRPYiZJl0zx8Z4L2mP6Q==
|
||||
|
||||
react-i18next@14.1.1:
|
||||
version "14.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-14.1.1.tgz#3d942a99866555ae3552c40f9fddfa061e29d7f3"
|
||||
@@ -7938,6 +7984,11 @@ react-select@5.8.0:
|
||||
react-transition-group "^4.3.0"
|
||||
use-isomorphic-layout-effect "^1.1.2"
|
||||
|
||||
react-simple-animate@^3.3.12:
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/react-simple-animate/-/react-simple-animate-3.5.2.tgz#ab08865c8bd47872b92bd1e25902326bf7c695b3"
|
||||
integrity sha512-xLE65euP920QMTOmv5haPlml+hmOPDkbIr5WeF7ADIXWBYt5kW/vwpNfWg8EKMab8aeDxIZ6QjffVh8v2dUyhg==
|
||||
|
||||
react-stately@3.30.1:
|
||||
version "3.30.1"
|
||||
resolved "https://registry.yarnpkg.com/react-stately/-/react-stately-3.30.1.tgz#7d87649c69f1bcf42c68a732f121ff23393f5abb"
|
||||
@@ -8463,7 +8514,16 @@ string-length@^4.0.1:
|
||||
char-regex "^1.0.2"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
"string-width-cjs@npm:string-width@^4.2.0":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
@@ -8541,7 +8601,14 @@ string_decoder@~1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
@@ -9106,6 +9173,14 @@ url-parse@^1.5.3:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
use-deep-compare-effect@^1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/use-deep-compare-effect/-/use-deep-compare-effect-1.8.1.tgz#ef0ce3b3271edb801da1ec23bf0754ef4189d0c6"
|
||||
integrity sha512-kbeNVZ9Zkc0RFGpfMN3MNfaKNvcLNyxOAAd9O4CBZ+kCBXXscn9s/4I+8ytUER4RDpEYs5+O6Rs4PqiZ+rHr5Q==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
dequal "^2.0.2"
|
||||
|
||||
use-isomorphic-layout-effect@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb"
|
||||
@@ -9126,6 +9201,11 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
uuid@^8.3.2:
|
||||
version "8.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||
|
||||
v8-compile-cache-lib@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||
@@ -9369,7 +9449,16 @@ word-wrap@^1.2.5:
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
|
||||
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
|
||||
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
@@ -9471,6 +9560,11 @@ yocto-queue@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
zod@3.23.8:
|
||||
version "3.23.8"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
|
||||
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
|
||||
|
||||
zustand@4.5.2:
|
||||
version "4.5.2"
|
||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.2.tgz#fddbe7cac1e71d45413b3682cdb47b48034c3848"
|
||||
|
||||
Reference in New Issue
Block a user