- {formState.message === "success" ? (
+ {formState.message !== "" && !formState.errors?.name ? (
) : (
""
)}
- {formState.message === "error" ? (
-
+ {formState.errors?.name ? (
+
+
+ {formState.errors?.name}
+
) : (
""
)}
diff --git a/src/app/_components/admin/CreateRegionForm.tsx b/src/app/_components/admin/CreateRegionForm.tsx
index 2c3ba9b..88f33b4 100644
--- a/src/app/_components/admin/CreateRegionForm.tsx
+++ b/src/app/_components/admin/CreateRegionForm.tsx
@@ -1,7 +1,7 @@
"use client";
import { Input } from "~/components/ui/input";
import SubmitButton from "../SubmitButton";
-import { useActionState } from "react";
+import { useEffect, useRef } from "react";
import { addRegion } from "~/server/actions/addRegion";
import {
Select,
@@ -11,6 +11,8 @@ import {
SelectValue,
} from "~/components/ui/select";
import { useFormState } from "react-dom";
+import clsx from "clsx";
+import { Check, CircleX } from "lucide-react";
interface Country {
id: string;
@@ -18,25 +20,72 @@ interface Country {
}
export default function CreateRegionForm(props: { countries: Country[] }) {
- const [state, formAction] = useFormState(addRegion, null);
+ const [formState, formAction] = useFormState(addRegion, {
+ message: "",
+ errors: undefined,
+ fieldValues: {
+ name: "",
+ countryId: "",
+ },
+ });
const { countries } = props;
+ const formRef = useRef
(null);
+ useEffect(() => {
+ if (formState.message === "success") {
+ formRef.current?.reset();
+ }
+ }, [formState.message]);
return (
-
);
}
diff --git a/src/server/actions/addCountry.ts b/src/server/actions/addCountry.ts
index 2bb4b66..bbd7728 100644
--- a/src/server/actions/addCountry.ts
+++ b/src/server/actions/addCountry.ts
@@ -7,7 +7,9 @@ import { ZodError, z } from "zod";
import { eq } from "drizzle-orm";
export async function addCountry(prevstate: any, formData: FormData) {
+ //assign formdaata to variables.
const name = (formData.get("name") as string).toLowerCase();
+ //check if country already exists
const exists = await db
.select({ name: countries.name })
.from(countries)
@@ -26,10 +28,7 @@ export async function addCountry(prevstate: any, formData: FormData) {
name,
});
//If the name doesn't exist, add the country to the database abd revalidate the page
- await db
- .insert(countries)
- .values({ name })
- .returning({ name: countries.name });
+ await db.insert(countries).values({ name });
revalidatePath("/");
//Return a success message
return {
@@ -42,6 +41,7 @@ export async function addCountry(prevstate: any, formData: FormData) {
} catch (error) {
const zodError = error as ZodError;
const errorMap = zodError.flatten().fieldErrors;
+ //Return an error object with the field values and errors.
return {
message: "error",
errors: {
diff --git a/src/server/actions/addRegion.ts b/src/server/actions/addRegion.ts
index 989538c..5b885fe 100644
--- a/src/server/actions/addRegion.ts
+++ b/src/server/actions/addRegion.ts
@@ -3,40 +3,63 @@
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"),
-});
+import { ZodError, z } from "zod";
+import { eq } from "drizzle-orm";
export const addRegion = async (prevstate: any, formData: FormData) => {
- const regionData = {
- name: (formData.get("name") as string).toLowerCase(),
- countryId: formData.get("country") as string,
- };
- const newRegion = schema.safeParse(regionData);
- if (!newRegion.success) {
- return {
- message: newRegion.error.issues[0]?.message,
- data: newRegion.data,
- };
- }
- const confirmedRegion = await db
- .insert(regions)
- .values(newRegion.data)
- .onConflictDoNothing()
- .returning({ name: regions.name });
- if (!confirmedRegion[0]) {
- return {
- message: `${newRegion.data.name} already exists`,
- data: newRegion.data,
- };
- } else {
- const message = `${newRegion.data.name} added`;
- const errors = newRegion.error;
- const data = newRegion.data;
+ //assign formdaata to variables.
+ const name = (formData.get("name") as string).toLowerCase();
+ const countryId = formData.get("country") as string;
+
+ //check if region already exists in country
+ const exists = await db
+ .select({ name: regions.name })
+ .from(regions)
+ .where(eq(regions.countryId, countryId) && eq(regions.name, name));
+
+ //Define the schema for the form data
+ const schema = z.object({
+ countryId: z.string().min(1, "No country selected"),
+ name: z
+ .string()
+ .min(1, "Name is required")
+ .refine(() => !exists[0], {
+ message: `${name} already exists in selected country`,
+ }),
+ });
+
+ //Parse the form data using the schema for validation, and check if the name already exists
+ try {
+ schema.parse({
+ countryId,
+ name,
+ });
+ //If the name doesn't exist, add the country to the database abd revalidate the page
+ await db.insert(regions).values({ countryId, name });
revalidatePath("/");
- return { message, errors, data };
+ //Return a success message
+ return {
+ message: "success",
+ errors: undefined,
+ fieldValues: {
+ name: "",
+ countryId: "",
+ },
+ };
+ } catch (error) {
+ const zodError = error as ZodError;
+ const errorMap = zodError.flatten().fieldErrors;
+ //Return an error object with the field values and errors.
+ return {
+ message: "error",
+ errors: {
+ name: errorMap["name"]?.[0] ?? "",
+ countryId: errorMap["countryId"]?.[0] ?? "",
+ },
+ fieldValues: {
+ name,
+ countryId,
+ },
+ };
}
};