mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 00:03:33 +10:00
fix: add hack for root zod validation with hook form
This commit is contained in:
@ -126,12 +126,12 @@ export const AddSignersFormPartial = ({
|
|||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{signers.map((signer, index) => (
|
{signers.map((signer, index) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={signer.formId}
|
key={signer.id}
|
||||||
data-native-id={signer.nativeId}
|
data-native-id={signer.nativeId}
|
||||||
className="flex flex-wrap items-end gap-x-4"
|
className="flex flex-wrap items-end gap-x-4"
|
||||||
>
|
>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Label htmlFor={`signer-${signer.formId}-email`}>
|
<Label htmlFor={`signer-${signer.id}-email`}>
|
||||||
Email
|
Email
|
||||||
<span className="text-destructive ml-1 inline-block font-medium">*</span>
|
<span className="text-destructive ml-1 inline-block font-medium">*</span>
|
||||||
</Label>
|
</Label>
|
||||||
@ -141,7 +141,7 @@ export const AddSignersFormPartial = ({
|
|||||||
name={`signers.${index}.email`}
|
name={`signers.${index}.email`}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input
|
<Input
|
||||||
id={`signer-${signer.formId}-email`}
|
id={`signer-${signer.id}-email`}
|
||||||
type="email"
|
type="email"
|
||||||
className="bg-background mt-2"
|
className="bg-background mt-2"
|
||||||
disabled={isSubmitting || hasBeenSentToRecipientId(signer.nativeId)}
|
disabled={isSubmitting || hasBeenSentToRecipientId(signer.nativeId)}
|
||||||
@ -153,14 +153,14 @@ export const AddSignersFormPartial = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Label htmlFor={`signer-${signer.formId}-name`}>Name</Label>
|
<Label htmlFor={`signer-${signer.id}-name`}>Name</Label>
|
||||||
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name={`signers.${index}.name`}
|
name={`signers.${index}.name`}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input
|
<Input
|
||||||
id={`signer-${signer.formId}-name`}
|
id={`signer-${signer.id}-name`}
|
||||||
type="text"
|
type="text"
|
||||||
className="bg-background mt-2"
|
className="bg-background mt-2"
|
||||||
disabled={isSubmitting || hasBeenSentToRecipientId(signer.nativeId)}
|
disabled={isSubmitting || hasBeenSentToRecipientId(signer.nativeId)}
|
||||||
@ -195,7 +195,11 @@ export const AddSignersFormPartial = ({
|
|||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormErrorMessage className="mt-2" error={errors.signers} />
|
<FormErrorMessage
|
||||||
|
className="mt-2"
|
||||||
|
// Dirty hack to handle errors when .root is populated for an array type
|
||||||
|
error={'signers__root' in errors && errors['signers__root']}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<Button type="button" disabled={isSubmitting} onClick={() => onAddSigner()}>
|
<Button type="button" disabled={isSubmitting} onClick={() => onAddSigner()}>
|
||||||
|
|||||||
@ -1,19 +1,24 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export const ZAddSignersFormSchema = z.object({
|
export const ZAddSignersFormSchema = z
|
||||||
signers: z
|
.object({
|
||||||
.array(
|
signers: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
formId: z.string().min(1),
|
formId: z.string().min(1),
|
||||||
nativeId: z.number().optional(),
|
nativeId: z.number().optional(),
|
||||||
email: z.string().min(1).email(),
|
email: z.string().min(1).email(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
}),
|
}),
|
||||||
)
|
),
|
||||||
.refine((signers) => {
|
})
|
||||||
const emails = signers.map((signer) => signer.email);
|
.refine(
|
||||||
|
(schema) => {
|
||||||
|
const emails = schema.signers.map((signer) => signer.email.toLowerCase());
|
||||||
|
|
||||||
return new Set(emails).size === emails.length;
|
return new Set(emails).size === emails.length;
|
||||||
}, 'Signers must have unique emails'),
|
},
|
||||||
});
|
// Dirty hack to handle errors when .root is populated for an array type
|
||||||
|
{ message: 'Signers must have unique emails', path: ['signers__root'] },
|
||||||
|
);
|
||||||
|
|
||||||
export type TAddSignersFormSchema = z.infer<typeof ZAddSignersFormSchema>;
|
export type TAddSignersFormSchema = z.infer<typeof ZAddSignersFormSchema>;
|
||||||
|
|||||||
@ -4,13 +4,17 @@ import { cn } from '@documenso/ui/lib/utils';
|
|||||||
|
|
||||||
export type FormErrorMessageProps = {
|
export type FormErrorMessageProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
error: { message?: string } | undefined;
|
error: { message?: string } | undefined | unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isErrorWithMessage = (error: unknown): error is { message?: string } => {
|
||||||
|
return typeof error === 'object' && error !== null && 'message' in error;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FormErrorMessage = ({ error, className }: FormErrorMessageProps) => {
|
export const FormErrorMessage = ({ error, className }: FormErrorMessageProps) => {
|
||||||
return (
|
return (
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{error && (
|
{isErrorWithMessage(error) && (
|
||||||
<motion.p
|
<motion.p
|
||||||
initial={{
|
initial={{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user