I am a newbie. I am trying to make a post request to the express server. I am using typeScript
and Shadcn/ui
form with zod
validation. I have to make a POST request like this JSON object below. I am getting the location dynamically from the server. How do I send the request ?
{
"description": "New Activity",
"price": 50,
"durationInMinutes": 120,
"placeId":1,
"locationId":1,
"status": "available"
}
This is my code of the form to make POST request but this is not working. The validation I made like this below
export const createActivityValidation = z.object({
description: z
.string({
required_error: "Description required",
invalid_type_error: "Description must be characters",
})
.min(1, "Description Needs More than 1 character"),
durationInMinutes: z.number(),
price: z.number(),
status: z
.string({
required_error: "Status required",
invalid_type_error: "Description must be characters",
})
.min(1, "Status is required"),
location: z.string({
required_error: "Place required",
invalid_type_error: "Please select the place",
}),
});
Every time I submit the form zod validation throws error as Eexpected number but got string whereas I have the validation as number.
function CreateActivity() {
const [loading, setLoading] = useState(false);
const [locations, setLocations] = useState<Location[]>([]);
const form = useForm<z.infer<typeof createActivityValidation>>({
resolver: zodResolver(createActivityValidation),
});
const onSubmit = async (value: z.infer<typeof createActivityValidation>) => {
console.log("value", value);
try {
setLoading(true);
const activityConfig = {
description: value.description,
durationInMinutes: value.durationInMinutes,
price: value.price,
status: value.status,
location: value.location,
};
const activityCreation = await fetcher.post(
"activities/activities",
activityConfig,
);
toast.success("Activity Created Successfully!");
console.log(activityCreation.data);
} catch (error) {
setLoading(false);
toast.error("Failed to create new Activity", {
description: "Something went wrong Please try later",
});
console.log(error);
}
};
return (
<Dialog>
<DialogTrigger asChild>
<Button
variant={"default"}
size={"lg"}
className=" bg-blue-600 text-secondary hover:bg-blue-600 rounded-full"
>
<BsPlus size={20} />
<span className="text-sm">Create Activity</span>
</Button>
</DialogTrigger>
<DialogContent className="">
<h1 className="text-center font-semibold text-2xl mt-2">
Create Activity To Do
</h1>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-2">
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>Description</FormLabel>
<FormControl>
<Input
type="text"
placeholder="Activity Description"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="durationInMinutes"
render={({ field }) => (
<FormItem>
<FormLabel>Duration</FormLabel>
<FormControl>
<Input
type="number"
placeholder="Duration of activities in minutes"
onChange={(e) => {
const value = Number(e.target.value);
field.onChange(value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="price"
render={({ field }) => (
<FormItem>
<FormLabel>Price</FormLabel>
<FormControl>
<Input
type="number"
placeholder="Price"
onChange={(e) => {
const value = Number(e.target.value);
field.onChange(value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="status"
render={({ field }) => (
<FormItem>
<FormLabel>Status</FormLabel>
<FormControl>
<Input
type="text"
placeholder="available or unavailabe"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="status"
render={({ field }) => (
<FormItem>
<FormLabel>Status</FormLabel>
<FormControl>
<LocationSelector
value={field.value}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter className="flex items-center justify-evenly px-4">
<Button
variant="outline"
size="sm"
type="submit"
className="bg-primary text-secondary rounded-full gap-2"
disabled={loading}
>
{loading ? (
<span className="flex">
<CircleDashed size={20} className=" mr-1 animate-spin" />
Loading
</span>
) : (
<span className="flex">
<PlusIcon size={20} />
Create
</span>
)}
</Button>
<DialogClose asChild>
<Button
variant="outline"
size="sm"
type="submit"
className=" border-red-600 text-red-600 rounded-full"
>
Cancel
</Button>
</DialogClose>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
);
}
export default CreateActivity;
Hrittik Bhattacharjee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1