All files / packages/app/features/add-peer add-peer-form.tsx

100% Statements 13/13
100% Branches 6/6
100% Functions 6/6
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                            142x                     54x 66x 66x 66x               66x     66x             3x     66x         113x                             102x                         196x   105x                            
import type React from "react";
 
import { useMutation } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
import { z } from "zod";
 
import { useTrpcMutationOptions } from "~app/hooks/use-trpc-mutation-options";
import type { TRPCMutationOutput } from "~app/trpc";
import { useAppForm } from "~app/utils/forms";
import { useTRPC } from "~app/utils/trpc";
import { emailSchema, peerNameSchema } from "~app/utils/validation";
import { Button } from "~components/button";
import { options as peersAddOptions } from "~mutations/peers/add";
 
const formSchema = z.object({
	name: peerNameSchema,
	email: emailSchema.optional().or(z.literal("")),
});
type Form = z.infer<typeof formSchema>;
 
type Props = {
	initialValue?: string;
	onSuccess?: (response: TRPCMutationOutput<"peers.add">) => void;
};
 
export const AddPeerForm: React.FC<Props> = ({ initialValue, onSuccess }) => {
	const { t } = useTranslation("peers");
	const trpc = useTRPC();
	const addPeerMutation = useMutation(
		trpc.peers.add.mutationOptions(
			useTrpcMutationOptions(peersAddOptions, {
				onSuccess,
			}),
		),
	);
 
	const defaultValues: Partial<Form> = {
		name: initialValue,
	};
	const form = useAppForm({
		defaultValues: defaultValues as Form,
		validators: {
			onMount: formSchema,
			onChange: formSchema,
			onSubmit: formSchema,
		},
		onSubmit: ({ value }) => addPeerMutation.mutate(value),
	});
 
	return (
		<form.AppForm>
			<form.Form className="flex flex-col gap-4">
				<form.AppField name="name">
					{(field) => (
						<field.TextField
							value={field.state.value}
							onValueChange={field.setValue}
							name={field.name}
							onBlur={field.handleBlur}
							label={t("add.form.name.label")}
							fieldError={
								field.state.meta.isDirty ? field.state.meta.errors : undefined
							}
							mutation={addPeerMutation}
						/>
					)}
				</form.AppField>
				<form.AppField name="email">
					{(field) => (
						<field.TextField
							value={field.state.value}
							onValueChange={field.setValue}
							name={field.name}
							onBlur={field.handleBlur}
							label={t("add.form.email.label")}
							fieldError={
								field.state.meta.isDirty ? field.state.meta.errors : undefined
							}
							mutation={addPeerMutation}
						/>
					)}
				</form.AppField>
				<form.Subscribe selector={(state) => state.canSubmit}>
					{(canSubmit) => (
						<Button
							color="primary"
							isDisabled={!canSubmit || addPeerMutation.isPending}
							isLoading={addPeerMutation.isPending}
							type="submit"
						>
							{t("add.form.submit")}
						</Button>
					)}
				</form.Subscribe>
			</form.Form>
		</form.AppForm>
	);
};