fix: FormProvider

This commit is contained in:
pandeymangg
2024-05-24 15:05:48 +05:30
parent 2e17e70c00
commit a01107521e
4 changed files with 201 additions and 209 deletions

View File

@@ -1,14 +1,13 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/navigation";
import { SubmitHandler, useForm } from "react-hook-form";
import toast from "react-hot-toast";
import { z } from "zod";
import { TProduct, ZProduct } from "@formbricks/types/product";
import { Button } from "@formbricks/ui/Button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@formbricks/ui/Form";
import { FormControl, FormField, FormItem, FormLabel, FormMessage, FormProvider } from "@formbricks/ui/Form";
import { Input } from "@formbricks/ui/Input";
import { updateProductAction } from "../actions";
@@ -28,7 +27,6 @@ export const EditProductNameForm: React.FC<EditProductNameProps> = ({
environmentId,
isProductNameEditDisabled,
}) => {
const router = useRouter();
const form = useForm<TEditProductName>({
defaultValues: {
name: product.name,
@@ -59,7 +57,6 @@ export const EditProductNameForm: React.FC<EditProductNameProps> = ({
if (!!updatedProduct?.id) {
toast.success("Product name updated successfully.");
router.refresh();
form.resetField("name", { defaultValue: updatedProduct.name });
}
} catch (err) {
@@ -69,41 +66,40 @@ export const EditProductNameForm: React.FC<EditProductNameProps> = ({
};
return !isProductNameEditDisabled ? (
<Form
{...form}
className="w-full max-w-sm items-center space-y-2"
onSubmit={form.handleSubmit(updateProduct)}>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel htmlFor="name">What&apos;s your product called?</FormLabel>
<FormControl>
<Input
type="text"
id="name"
{...field}
placeholder="Product Name"
autoComplete="off"
required
isInvalid={!!nameError}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormProvider {...form}>
<form className="w-full max-w-sm items-center space-y-2" onSubmit={form.handleSubmit(updateProduct)}>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel htmlFor="name">What&apos;s your product called?</FormLabel>
<FormControl>
<Input
type="text"
id="name"
{...field}
placeholder="Product Name"
autoComplete="off"
required
isInvalid={!!nameError}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
variant="darkCTA"
size="sm"
loading={isSubmitting}
disabled={isSubmitting || !isDirty}>
Update
</Button>
</Form>
<Button
type="submit"
variant="darkCTA"
size="sm"
loading={isSubmitting}
disabled={isSubmitting || !isDirty}>
Update
</Button>
</form>
</FormProvider>
) : (
<p className="text-sm text-red-700">Only Owners, Admins and Editors can perform this action.</p>
);

View File

@@ -1,14 +1,13 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/navigation";
import { SubmitHandler, useForm } from "react-hook-form";
import toast from "react-hot-toast";
import { z } from "zod";
import { TProduct, ZProduct } from "@formbricks/types/product";
import { Button } from "@formbricks/ui/Button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@formbricks/ui/Form";
import { FormControl, FormField, FormItem, FormLabel, FormMessage, FormProvider } from "@formbricks/ui/Form";
import { Input } from "@formbricks/ui/Input";
import { updateProductAction } from "../actions";
@@ -23,8 +22,6 @@ const ZProductRecontactDaysInput = ZProduct.pick({ recontactDays: true });
type EditWaitingTimeFormValues = z.infer<typeof ZProductRecontactDaysInput>;
export const EditWaitingTimeForm: React.FC<EditWaitingTimeProps> = ({ product, environmentId }) => {
const router = useRouter();
const form = useForm<EditWaitingTimeFormValues>({
defaultValues: {
recontactDays: product.recontactDays,
@@ -40,7 +37,6 @@ export const EditWaitingTimeForm: React.FC<EditWaitingTimeProps> = ({ product, e
const updatedProduct = await updateProductAction(environmentId, product.id, data);
if (!!updatedProduct?.id) {
toast.success("Waiting period updated successfully.");
router.refresh();
form.resetField("recontactDays", { defaultValue: updatedProduct.recontactDays });
}
} catch (err) {
@@ -49,45 +45,46 @@ export const EditWaitingTimeForm: React.FC<EditWaitingTimeProps> = ({ product, e
};
return (
<Form
{...form}
className="flex w-full max-w-sm flex-col space-y-4"
onSubmit={form.handleSubmit(updateWaitingTime)}>
<FormField
control={form.control}
name="recontactDays"
render={({ field }) => (
<FormItem>
<FormLabel htmlFor="recontactDays">Wait X days before showing next survey:</FormLabel>
<FormControl>
<Input
type="number"
id="recontactDays"
{...field}
onChange={(e) => {
const value = e.target.value;
if (value === "") {
field.onChange("");
}
<FormProvider {...form}>
<form
className="flex w-full max-w-sm flex-col space-y-4"
onSubmit={form.handleSubmit(updateWaitingTime)}>
<FormField
control={form.control}
name="recontactDays"
render={({ field }) => (
<FormItem>
<FormLabel htmlFor="recontactDays">Wait X days before showing next survey:</FormLabel>
<FormControl>
<Input
type="number"
id="recontactDays"
{...field}
onChange={(e) => {
const value = e.target.value;
if (value === "") {
field.onChange("");
}
field.onChange(parseInt(value, 10));
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
field.onChange(parseInt(value, 10));
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
variant="darkCTA"
size="sm"
className="w-fit"
loading={isSubmitting}
disabled={isSubmitting || !isDirty}>
Update
</Button>
</Form>
<Button
type="submit"
variant="darkCTA"
size="sm"
className="w-fit"
loading={isSubmitting}
disabled={isSubmitting || !isDirty}>
Update
</Button>
</form>
</FormProvider>
);
};

View File

@@ -8,7 +8,7 @@ import { z } from "zod";
import { cn } from "@formbricks/lib/cn";
import { TProduct } from "@formbricks/types/product";
import { Button } from "@formbricks/ui/Button";
import { Form, FormControl, FormField, FormItem, FormLabel } from "@formbricks/ui/Form";
import { FormControl, FormField, FormItem, FormLabel, FormProvider } from "@formbricks/ui/Form";
import { Label } from "@formbricks/ui/Label";
import { getPlacementStyle } from "@formbricks/ui/PreviewSurvey/lib/utils";
import { RadioGroup, RadioGroupItem } from "@formbricks/ui/RadioGroup";
@@ -68,124 +68,126 @@ export const EditPlacementForm = ({ product }: EditPlacementProps) => {
};
return (
<Form {...form} className="w-full items-center" onSubmit={form.handleSubmit(onSubmit)}>
<div className="flex">
<FormField
control={form.control}
name="placement"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup
{...field}
onValueChange={(value) => {
field.onChange(value);
}}
className="h-full">
{placements.map((placement) => (
<div key={placement.value} className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem
id={placement.value}
value={placement.value}
disabled={placement.disabled}
checked={field.value === placement.value}
/>
<Label htmlFor={placement.value} className="text-slate-900">
{placement.name}
</Label>
</div>
))}
</RadioGroup>
</FormControl>
</FormItem>
)}
/>
<div
className={cn(
clickOutsideClose ? "" : "cursor-not-allowed",
"relative ml-8 h-40 w-full rounded",
overlayStyle
)}>
<FormProvider {...form}>
<form className="w-full items-center" onSubmit={form.handleSubmit(onSubmit)}>
<div className="flex">
<FormField
control={form.control}
name="placement"
render={({ field }) => (
<FormItem>
<FormControl>
<RadioGroup
{...field}
onValueChange={(value) => {
field.onChange(value);
}}
className="h-full">
{placements.map((placement) => (
<div key={placement.value} className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem
id={placement.value}
value={placement.value}
disabled={placement.disabled}
checked={field.value === placement.value}
/>
<Label htmlFor={placement.value} className="text-slate-900">
{placement.name}
</Label>
</div>
))}
</RadioGroup>
</FormControl>
</FormItem>
)}
/>
<div
className={cn(
"absolute h-16 w-16 cursor-default rounded bg-slate-700",
getPlacementStyle(currentPlacement)
)}></div>
clickOutsideClose ? "" : "cursor-not-allowed",
"relative ml-8 h-40 w-full rounded",
overlayStyle
)}>
<div
className={cn(
"absolute h-16 w-16 cursor-default rounded bg-slate-700",
getPlacementStyle(currentPlacement)
)}></div>
</div>
</div>
</div>
{currentPlacement === "center" && (
<>
<div className="mt-6 space-y-2">
<FormField
control={form.control}
name="darkOverlay"
render={({ field }) => (
<FormItem>
<FormLabel className="font-semibold">Centered modal overlay color</FormLabel>
<FormControl>
<RadioGroup
onValueChange={(value) => {
field.onChange(value === "darkOverlay");
}}
className="flex space-x-4">
<div className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id="lightOverlay" value="lightOverlay" checked={!field.value} />
<Label htmlFor="lightOverlay" className="text-slate-900">
Light Overlay
</Label>
</div>
<div className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id="darkOverlay" value="darkOverlay" checked={field.value} />
<Label htmlFor="darkOverlay" className="text-slate-900">
Dark Overlay
</Label>
</div>
</RadioGroup>
</FormControl>
</FormItem>
)}
/>
</div>
<div className="mt-6 space-y-2">
<FormField
control={form.control}
name="clickOutsideClose"
render={({ field }) => (
<FormItem>
<FormLabel className="font-semibold">
Allow users to exit by clicking outside the study
</FormLabel>
<FormControl>
<RadioGroup
onValueChange={(value) => {
field.onChange(value === "allow");
}}
className="flex space-x-4">
<div className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id="disallow" value="disallow" checked={!field.value} />
<Label htmlFor="disallow" className="text-slate-900">
Don&apos;t Allow
</Label>
</div>
<div className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id="allow" value="allow" checked={field.value} />
<Label htmlFor="allow" className="text-slate-900">
Allow
</Label>
</div>
</RadioGroup>
</FormControl>
</FormItem>
)}
/>
</div>
</>
)}
{currentPlacement === "center" && (
<>
<div className="mt-6 space-y-2">
<FormField
control={form.control}
name="darkOverlay"
render={({ field }) => (
<FormItem>
<FormLabel className="font-semibold">Centered modal overlay color</FormLabel>
<FormControl>
<RadioGroup
onValueChange={(value) => {
field.onChange(value === "darkOverlay");
}}
className="flex space-x-4">
<div className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id="lightOverlay" value="lightOverlay" checked={!field.value} />
<Label htmlFor="lightOverlay" className="text-slate-900">
Light Overlay
</Label>
</div>
<div className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id="darkOverlay" value="darkOverlay" checked={field.value} />
<Label htmlFor="darkOverlay" className="text-slate-900">
Dark Overlay
</Label>
</div>
</RadioGroup>
</FormControl>
</FormItem>
)}
/>
</div>
<div className="mt-6 space-y-2">
<FormField
control={form.control}
name="clickOutsideClose"
render={({ field }) => (
<FormItem>
<FormLabel className="font-semibold">
Allow users to exit by clicking outside the study
</FormLabel>
<FormControl>
<RadioGroup
onValueChange={(value) => {
field.onChange(value === "allow");
}}
className="flex space-x-4">
<div className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id="disallow" value="disallow" checked={!field.value} />
<Label htmlFor="disallow" className="text-slate-900">
Don&apos;t Allow
</Label>
</div>
<div className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id="allow" value="allow" checked={field.value} />
<Label htmlFor="allow" className="text-slate-900">
Allow
</Label>
</div>
</RadioGroup>
</FormControl>
</FormItem>
)}
/>
</div>
</>
)}
<Button variant="darkCTA" className="mt-4 w-fit" size="sm" loading={isSubmitting}>
Save
</Button>
</Form>
<Button variant="darkCTA" className="mt-4 w-fit" size="sm" loading={isSubmitting}>
Save
</Button>
</form>
</FormProvider>
);
};

View File

@@ -9,7 +9,6 @@ import {
FieldPath,
FieldValues,
FormProvider,
FormProviderProps,
useFormContext,
} from "react-hook-form";
@@ -17,17 +16,6 @@ import { cn } from "@formbricks/lib/cn";
import { Label } from "../Label";
type FormProps<TFieldValues extends FieldValues = FieldValues> = FormProviderProps<TFieldValues> &
React.FormHTMLAttributes<HTMLFormElement>;
const Form = <TFieldValues extends FieldValues>({ children, ...props }: FormProps<TFieldValues>) => {
return (
<FormProvider {...props}>
<form {...props}>{children}</form>
</FormProvider>
);
};
type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
@@ -154,4 +142,13 @@ const FormMessage = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<
);
FormMessage.displayName = "FormMessage";
export { useFormField, Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormField };
export {
useFormField,
FormProvider,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
};