diff --git a/src/app/App.tsx b/src/app/App.tsx index bf28490..628f8e2 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -4,6 +4,8 @@ import CreateCountry from "./_components/admin/CreateCountry"; import AllCountries from "./_components/AllCountries"; import CreateRegion from "./_components/admin/CreateRegion"; import AllRegions from "./_components/AllRegions"; +import CreateSubRegionForm from "./_components/admin/CreateSubRegionForm"; +import CreateSubRegion from "./_components/admin/CreateSubRegion"; export default function App() { return ( @@ -14,6 +16,7 @@ export default function App() { + ); } diff --git a/src/app/_components/admin/CreateCountry.tsx b/src/app/_components/admin/CreateCountry.tsx index 0c10572..6223e42 100644 --- a/src/app/_components/admin/CreateCountry.tsx +++ b/src/app/_components/admin/CreateCountry.tsx @@ -2,9 +2,9 @@ import CreateCountryForm from "./CreateCountryForm"; export default function CreateCountry() { return ( - <> +

Fill the form to create a new country

- +
); } diff --git a/src/app/_components/admin/CreateRegion.tsx b/src/app/_components/admin/CreateRegion.tsx index 56b6f3f..f5d1d26 100644 --- a/src/app/_components/admin/CreateRegion.tsx +++ b/src/app/_components/admin/CreateRegion.tsx @@ -1,13 +1,14 @@ "use server"; import { db } from "~/server/db"; import CreateRegionForm from "./CreateRegionForm"; +import getAllCountries from "~/server/actions/getAllCountries"; export default async function CreateRegion() { - const allCountries = await db.query.countries.findMany(); + const allCountries = await getAllCountries(); return ( - <> +

Fill the form to create a new region

- +
); } diff --git a/src/app/_components/admin/CreateSubRegion.tsx b/src/app/_components/admin/CreateSubRegion.tsx new file mode 100644 index 0000000..cf608a2 --- /dev/null +++ b/src/app/_components/admin/CreateSubRegion.tsx @@ -0,0 +1,18 @@ +"use server"; +import getAllRegions from "~/server/actions/getAllRegions"; +import CreateSubRegionForm from "./CreateSubRegionForm"; +import getAllCountries from "~/server/actions/getAllCountries"; + +const allRegions = await getAllRegions(); +const allCountries = await getAllCountries(); + +export default async function CreateSubRegion() { + return ( +
+

+ Fill the form to create a new Sub Region +

+ +
+ ); +} diff --git a/src/app/_components/admin/CreateSubRegionForm.tsx b/src/app/_components/admin/CreateSubRegionForm.tsx new file mode 100644 index 0000000..97e4546 --- /dev/null +++ b/src/app/_components/admin/CreateSubRegionForm.tsx @@ -0,0 +1,81 @@ +"use client"; +import clsx from "clsx"; +import { useState } from "react"; +import { useFormState } from "react-dom"; +import { Input } from "~/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "~/components/ui/select"; +import { addRegion } from "~/server/actions/addRegion"; + +type Region = { + id: string; + name: string; + countryId: string; +}; +type Country = { + id: string; + name: string; +}; + +export default function CreateSubRegionForm(props: { + regions: Region[]; + countries: Country[]; +}) { + const { countries, regions } = props; + const [country, setCountry] = useState(undefined); + const [formState, formActions] = useFormState(addRegion, { + message: "", + errors: undefined, + fieldValues: { + name: "", + regionId: "", + }, + }); + return ( +
+ {/* country selector */} + +
+ {/* region selector */} + + +
+
+ ); +} diff --git a/src/server/actions/addCountry.ts b/src/server/actions/addCountry.ts index bbd7728..aa45cfc 100644 --- a/src/server/actions/addCountry.ts +++ b/src/server/actions/addCountry.ts @@ -20,7 +20,7 @@ export async function addCountry(prevstate: any, formData: FormData) { name: z .string() .min(1, { message: "Name is required" }) - .refine(() => !exists[0], { message: `${name} already exists` }), + .refine(() => !exists, { message: `${name} already exists` }), }); //Parse the form data using the schema for validation, and check if the name already exists try { diff --git a/src/server/actions/addRegion.ts b/src/server/actions/addRegion.ts index 5b885fe..9262940 100644 --- a/src/server/actions/addRegion.ts +++ b/src/server/actions/addRegion.ts @@ -23,7 +23,7 @@ export const addRegion = async (prevstate: any, formData: FormData) => { name: z .string() .min(1, "Name is required") - .refine(() => !exists[0], { + .refine(() => !exists, { message: `${name} already exists in selected country`, }), }); diff --git a/src/server/actions/addSubRegion.ts b/src/server/actions/addSubRegion.ts new file mode 100644 index 0000000..6f5e784 --- /dev/null +++ b/src/server/actions/addSubRegion.ts @@ -0,0 +1,62 @@ +"use server"; + +import { eq } from "drizzle-orm"; +import { db } from "../db"; +import { subRegions } from "../db/schema"; +import { ZodError, z } from "zod"; + +export const addSubRegion = async (prevstate: any, formData: FormData) => { + //assign formdaata to variables. + const name = (formData.get("name") as string).toLowerCase(); + const regionId = formData.get("region") as string; + + //check if region already exists in country + const exists = await db + .select({ name: subRegions.name }) + .from(subRegions) + .where(eq(subRegions.regionId, regionId) && eq(subRegions.name, name)); + + //Define the schema for the form data + const schema = z.object({ + regionId: z.string().min(1, "No region selected"), + name: z + .string() + .min(1, "Name is required") + .refine(() => !exists, { + message: `${name} already exists in selected region`, + }), + }); + //Parse the form data using the schema for validation, and check if the name already exists + try { + schema.parse({ + regionId, + name, + }); + //If the name doesn't exist, add the country to the database abd revalidate the page + await db.insert(subRegions).values({ regionId, name }); + //Return a success message + return { + message: "success", + errors: undefined, + fieldValues: { + name: "", + regionId: "", + }, + }; + } 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] ?? "", + regionId: errorMap["regionId"]?.[0] ?? "", + }, + fieldValues: { + name, + regionId, + }, + }; + } +};