added form validation to regions form.
All checks were successful
Vercel Production Deployment / Deploy-Production (push) Successful in 1m31s

This commit is contained in:
christian 2024-06-01 09:45:54 +02:00
parent 4f5a9c429c
commit f0125fd472
7 changed files with 57 additions and 78 deletions

View File

@ -1,11 +1,12 @@
import { useFormStatus } from "react-dom"; import { useFormStatus } from "react-dom";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
export default function SubmitButton() { export default function SubmitButton(props: { text: string }) {
const { text } = props;
const { pending } = useFormStatus(); const { pending } = useFormStatus();
return ( return (
<Button disabled={pending}> <Button disabled={pending}>
{pending ? "Adding country.." : "Add country"} {pending ? `Adding ${text}` : `Add ${text}`}
</Button> </Button>
); );
} }

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import { Input } from "~/components/ui/input"; import { Input } from "~/components/ui/input";
import { addCountry } from "~/server/actions/createCountry"; import { addCountry } from "~/server/actions/addCountry";
import SubmitButton from "../SubmitButton"; import SubmitButton from "../SubmitButton";
import { useRef } from "react"; import { useRef } from "react";
@ -17,7 +17,7 @@ export default function CreateCountryForm() {
return ( return (
<form ref={ref} action={handleSubmit}> <form ref={ref} action={handleSubmit}>
<Input name="name" required /> <Input name="name" required />
<SubmitButton /> <SubmitButton text={"Country"} />
</form> </form>
); );
} }

View File

@ -2,7 +2,7 @@
import { Input } from "~/components/ui/input"; import { Input } from "~/components/ui/input";
import SubmitButton from "../SubmitButton"; import SubmitButton from "../SubmitButton";
import { useRef } from "react"; import { useRef } from "react";
import { addRegion } from "~/server/actions/createRegion"; import { addRegion } from "~/server/actions/addRegion";
import { import {
Select, Select,
SelectContent, SelectContent,
@ -10,21 +10,20 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "~/components/ui/select"; } from "~/components/ui/select";
import { useFormState } from "react-dom";
import { init } from "next/dist/compiled/webpack/webpack";
type Country = { interface Country {
id: string; id: string;
name: string; name: string;
}; }
export default function CreateRegionForm(props: { countries: Country[] }) { export default function CreateRegionForm(props: { countries: Country[] }) {
const [state, formAction] = useFormState(addRegion, null);
const { countries } = props; const { countries } = props;
const ref = useRef<HTMLFormElement>(null); const ref = useRef<HTMLFormElement>(null);
const handleSubmit = async (formData: FormData) => {
ref.current?.reset();
await addRegion(formData);
};
return ( return (
<form ref={ref} action={handleSubmit}> <form ref={ref} action={formAction}>
<Input name="name" required /> <Input name="name" required />
<Select name="country"> <Select name="country">
<SelectTrigger className="w-[180px]"> <SelectTrigger className="w-[180px]">
@ -38,8 +37,8 @@ export default function CreateRegionForm(props: { countries: Country[] }) {
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
<SubmitButton text={"Region"} />
<SubmitButton /> <span>{state?.message}</span>
</form> </form>
); );
} }

View File

@ -1,34 +0,0 @@
"use client";
import { Input } from "~/components/ui/input";
import { addCountry } from "~/server/actions/createCountry";
import SubmitButton from "../SubmitButton";
import { useRef } from "react";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
export default function CreateCountryForm() {
const ref = useRef<HTMLFormElement>(null);
const handleSubmit = async (formData: FormData) => {
ref.current?.reset();
await addCountry(formData);
};
return (
<form ref={ref} action={handleSubmit}>
<Input name="name" required />
<Select>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Wine type" />
</SelectTrigger>
<SelectContent>
<SelectItem value="light">Light</SelectItem>
</SelectContent>
</Select>
<SubmitButton />
</form>
);
}

View File

@ -0,0 +1,43 @@
"use server";
import { revalidatePath } from "next/cache";
import { db } from "../db";
import { regions } from "../db/schema";
import { z } from "zod";
const schema = z.object({
countryId: z.string().min(1, "No country selected"),
name: z.string().min(1, "Name is required"),
});
export const addRegion = async (prevstate: any, formData: FormData) => {
const newRegion = schema.safeParse({
name: (formData.get("name") as string).toLowerCase(),
countryId: formData.get("country") as string,
});
if (!newRegion.success) {
return {
message: "failed",
errors: newRegion.error,
data: null,
};
}
const confirmedRegion = await db
.insert(regions)
.values(newRegion.data)
.onConflictDoNothing({ target: regions.name })
.returning({ name: regions.name });
if (!confirmedRegion[0]?.name) {
return {
message: "region already exists",
errors: newRegion.error,
data: null,
};
} else {
const message = `${newRegion.data.name} added`;
const errors = newRegion.error;
const data = newRegion.data;
revalidatePath("/");
return { message, errors, data };
}
};

View File

@ -1,30 +0,0 @@
"use server";
import { revalidatePath } from "next/cache";
import { db } from "../db";
import { regions } from "../db/schema";
import { z } from "zod";
type NewRegion = {
name: string;
countryId: string;
};
const schema = z.object({
countryId: z.string(),
name: z.string().min(1, "Name is required"),
});
export const addRegion = async (formData: FormData) => {
const newRegion: NewRegion = {
name: (formData.get("name") as string).toLowerCase(),
countryId: formData.get("country") as string,
};
revalidatePath("/");
await db.insert(regions).values(newRegion).returning();
return {
message: message,
errors: error,
status: 200,
};
};