admin-forms #12
@ -4,8 +4,10 @@ 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";
 | 
			
		||||
import AllSubRegions from "./_components/AllSubRegions";
 | 
			
		||||
import CreateProducer from "./_components/admin/CreateProducer";
 | 
			
		||||
import AllProducers from "./_components/allProducers";
 | 
			
		||||
 | 
			
		||||
export default function App() {
 | 
			
		||||
  return (
 | 
			
		||||
@ -17,6 +19,9 @@ export default function App() {
 | 
			
		||||
      <CreateRegion />
 | 
			
		||||
      <AllRegions />
 | 
			
		||||
      <CreateSubRegion />
 | 
			
		||||
      <AllSubRegions />
 | 
			
		||||
      <CreateProducer />
 | 
			
		||||
      <AllProducers />
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
import { Delete } from "lucide-react";
 | 
			
		||||
import deleteRegion from "~/server/actions/deleteRegion";
 | 
			
		||||
import getAllCountries from "~/server/actions/getAllCountries";
 | 
			
		||||
import getAllRegions from "~/server/actions/getAllRegions";
 | 
			
		||||
 | 
			
		||||
@ -7,24 +9,16 @@ export default async function AllRegions() {
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="pt-4">
 | 
			
		||||
      <h1 className="text-2xl">All Regions:</h1>
 | 
			
		||||
      {allRegions[0] ? (
 | 
			
		||||
        <>
 | 
			
		||||
          <ul>
 | 
			
		||||
            {allRegions.map((region) => (
 | 
			
		||||
              <li key={region.id}>
 | 
			
		||||
                {region.name} -{" "}
 | 
			
		||||
                {
 | 
			
		||||
                  allCountries.find(
 | 
			
		||||
                    (country) => country.id === region.countryId,
 | 
			
		||||
                  )?.name
 | 
			
		||||
                }
 | 
			
		||||
              </li>
 | 
			
		||||
            ))}
 | 
			
		||||
          </ul>
 | 
			
		||||
        </>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <p>There are no regions in the db.</p>
 | 
			
		||||
      )}
 | 
			
		||||
      {allRegions.map((region) => (
 | 
			
		||||
        <div key={region.id} className="flex gap-1">
 | 
			
		||||
          <p>{region.name}</p>
 | 
			
		||||
          <form action={deleteRegion.bind(null, region.id)}>
 | 
			
		||||
            <button>
 | 
			
		||||
              <Delete />
 | 
			
		||||
            </button>
 | 
			
		||||
          </form>
 | 
			
		||||
        </div>
 | 
			
		||||
      ))}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								src/app/_components/AllSubRegions.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/app/_components/AllSubRegions.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
import { Delete } from "lucide-react";
 | 
			
		||||
import deleteSubRegion from "~/server/actions/deleteSubRegion";
 | 
			
		||||
import getAllSubRegions from "~/server/actions/getAllSubRegions";
 | 
			
		||||
 | 
			
		||||
export default async function AllSubRegions() {
 | 
			
		||||
  const allSubRegions = await getAllSubRegions();
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="pt-4">
 | 
			
		||||
      <h1 className="text-2xl">All Sub Regions:</h1>
 | 
			
		||||
      {allSubRegions.map((subRegion) => (
 | 
			
		||||
        <div key={subRegion.id} className="flex gap-1">
 | 
			
		||||
          <p>{subRegion.name}</p>
 | 
			
		||||
          <form action={deleteSubRegion.bind(null, subRegion.id)}>
 | 
			
		||||
            <button>
 | 
			
		||||
              <Delete />
 | 
			
		||||
            </button>
 | 
			
		||||
          </form>
 | 
			
		||||
        </div>
 | 
			
		||||
      ))}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/app/_components/admin/CreateProducer.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/app/_components/admin/CreateProducer.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import getAllCountries from "~/server/actions/getAllCountries";
 | 
			
		||||
import CreateProducerForm from "./CreateProducerForm";
 | 
			
		||||
 | 
			
		||||
export default async function CreateProducer() {
 | 
			
		||||
  const allCountries = await getAllCountries();
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="container flex w-full flex-col justify-center py-4">
 | 
			
		||||
      <h1 className="pt-4 text-2xl">Fill the form to create a new producer</h1>
 | 
			
		||||
      <CreateProducerForm allCountries={allCountries} />
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										108
									
								
								src/app/_components/admin/CreateProducerForm.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/app/_components/admin/CreateProducerForm.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,108 @@
 | 
			
		||||
"use client";
 | 
			
		||||
import clsx from "clsx";
 | 
			
		||||
import { Check, CircleX } from "lucide-react";
 | 
			
		||||
import { useFormState } from "react-dom";
 | 
			
		||||
import { Input } from "~/components/ui/input";
 | 
			
		||||
import {
 | 
			
		||||
  Select,
 | 
			
		||||
  SelectContent,
 | 
			
		||||
  SelectItem,
 | 
			
		||||
  SelectTrigger,
 | 
			
		||||
  SelectValue,
 | 
			
		||||
} from "~/components/ui/select";
 | 
			
		||||
import { Textarea } from "~/components/ui/textarea";
 | 
			
		||||
import { addProducer } from "~/server/actions/addProducer";
 | 
			
		||||
import SubmitButton from "../SubmitButton";
 | 
			
		||||
 | 
			
		||||
type Country = {
 | 
			
		||||
  id: string;
 | 
			
		||||
  name: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function CreateProducerForm(props: { allCountries: Country[] }) {
 | 
			
		||||
  const { allCountries } = props;
 | 
			
		||||
  const [formState, formAction] = useFormState(addProducer, {
 | 
			
		||||
    message: "",
 | 
			
		||||
    errors: undefined,
 | 
			
		||||
    fieldValues: {
 | 
			
		||||
      name: "",
 | 
			
		||||
      description: "",
 | 
			
		||||
      imageUrl: "",
 | 
			
		||||
      countryId: "",
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
  return (
 | 
			
		||||
    <form action={formAction}>
 | 
			
		||||
      <Input
 | 
			
		||||
        name="name"
 | 
			
		||||
        id="name"
 | 
			
		||||
        placeholder="Enter the name of the producer..."
 | 
			
		||||
        className={clsx({ "border-red-500": formState.errors?.name })}
 | 
			
		||||
      />
 | 
			
		||||
      {formState.message !== "" && !formState.errors?.name ? (
 | 
			
		||||
        <Check className="text-green-500" />
 | 
			
		||||
      ) : (
 | 
			
		||||
        ""
 | 
			
		||||
      )}
 | 
			
		||||
      {formState.errors?.name ? (
 | 
			
		||||
        <div className="flex min-w-96 items-center gap-1 text-red-500">
 | 
			
		||||
          <CircleX />
 | 
			
		||||
          <span className="text-sm">{formState.errors?.name}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      ) : (
 | 
			
		||||
        ""
 | 
			
		||||
      )}
 | 
			
		||||
      <Textarea
 | 
			
		||||
        name="description"
 | 
			
		||||
        id="description"
 | 
			
		||||
        placeholder="Enter a description of the producer..."
 | 
			
		||||
        className={clsx({ "border-red-500": formState.errors?.description })}
 | 
			
		||||
      />
 | 
			
		||||
      {formState.message !== "" && !formState.errors?.description ? (
 | 
			
		||||
        <Check className="text-green-500" />
 | 
			
		||||
      ) : (
 | 
			
		||||
        ""
 | 
			
		||||
      )}
 | 
			
		||||
      {formState.errors?.description ? (
 | 
			
		||||
        <div className="flex min-w-96 items-center gap-1 text-red-500">
 | 
			
		||||
          <CircleX />
 | 
			
		||||
          <span className="text-sm">{formState.errors?.description}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      ) : (
 | 
			
		||||
        ""
 | 
			
		||||
      )}
 | 
			
		||||
      <Input
 | 
			
		||||
        name="imageUrl"
 | 
			
		||||
        id="imageUrl"
 | 
			
		||||
        placeholder="Image URL"
 | 
			
		||||
        className={clsx({ "border-red-500": formState.errors?.imageUrl })}
 | 
			
		||||
      />
 | 
			
		||||
      {formState.message !== "" && !formState.errors?.imageUrl ? (
 | 
			
		||||
        <Check className="text-green-500" />
 | 
			
		||||
      ) : (
 | 
			
		||||
        ""
 | 
			
		||||
      )}
 | 
			
		||||
      {formState.errors?.imageUrl ? (
 | 
			
		||||
        <div className="flex min-w-96 items-center gap-1 text-red-500">
 | 
			
		||||
          <CircleX />
 | 
			
		||||
          <span className="text-sm">{formState.errors?.imageUrl}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      ) : (
 | 
			
		||||
        ""
 | 
			
		||||
      )}
 | 
			
		||||
      <Select name="countryId">
 | 
			
		||||
        <SelectTrigger className={`w-[180px] `}>
 | 
			
		||||
          <SelectValue placeholder="select country" />
 | 
			
		||||
        </SelectTrigger>
 | 
			
		||||
        <SelectContent>
 | 
			
		||||
          {allCountries.map((country) => (
 | 
			
		||||
            <SelectItem key={country.id} value={country.id}>
 | 
			
		||||
              {country.name}
 | 
			
		||||
            </SelectItem>
 | 
			
		||||
          ))}
 | 
			
		||||
        </SelectContent>
 | 
			
		||||
      </Select>
 | 
			
		||||
      <SubmitButton text={"producer"} />
 | 
			
		||||
    </form>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import { db } from "~/server/db";
 | 
			
		||||
import CreateRegionForm from "./CreateRegionForm";
 | 
			
		||||
import getAllCountries from "~/server/actions/getAllCountries";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
"use client";
 | 
			
		||||
import clsx from "clsx";
 | 
			
		||||
import { ChangeEvent, useEffect, useState } from "react";
 | 
			
		||||
import { ChangeEvent, useEffect, useRef, useState } from "react";
 | 
			
		||||
import { useFormState } from "react-dom";
 | 
			
		||||
import { Input } from "~/components/ui/input";
 | 
			
		||||
import {
 | 
			
		||||
@ -12,6 +12,7 @@ import {
 | 
			
		||||
} from "~/components/ui/select";
 | 
			
		||||
import { addSubRegion } from "~/server/actions/addSubRegion";
 | 
			
		||||
import SubmitButton from "../SubmitButton";
 | 
			
		||||
import { Check, CircleX } from "lucide-react";
 | 
			
		||||
 | 
			
		||||
type Region = {
 | 
			
		||||
  id: string;
 | 
			
		||||
@ -51,16 +52,22 @@ export default function CreateSubRegionForm(props: {
 | 
			
		||||
      setSelectCountryRegions(regions);
 | 
			
		||||
    }
 | 
			
		||||
  }, [selectCountryId]);
 | 
			
		||||
 | 
			
		||||
  const formRef = useRef<HTMLFormElement>(null);
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (formState.message === "success") {
 | 
			
		||||
      formRef.current?.reset();
 | 
			
		||||
    }
 | 
			
		||||
  }, [formState.message]);
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
    <div className="flex flex-col gap-2">
 | 
			
		||||
      {/* country selector */}
 | 
			
		||||
      <p>{selectCountryId}</p>
 | 
			
		||||
      <Select
 | 
			
		||||
        name="country"
 | 
			
		||||
        onValueChange={(value) => setSelectCountryId(value)}
 | 
			
		||||
      >
 | 
			
		||||
        <SelectTrigger className={`w-[180px] `}>
 | 
			
		||||
          <SelectValue placeholder="Country" />
 | 
			
		||||
          <SelectValue placeholder="select country" />
 | 
			
		||||
        </SelectTrigger>
 | 
			
		||||
        <SelectContent>
 | 
			
		||||
          {allCountries.map((country) => (
 | 
			
		||||
@ -70,28 +77,58 @@ export default function CreateSubRegionForm(props: {
 | 
			
		||||
          ))}
 | 
			
		||||
        </SelectContent>
 | 
			
		||||
      </Select>
 | 
			
		||||
      <form action={formActions}>
 | 
			
		||||
      <form ref={formRef} action={formActions}>
 | 
			
		||||
        {/* region selector */}
 | 
			
		||||
        <Select name="regionId">
 | 
			
		||||
          <SelectTrigger
 | 
			
		||||
            className={`w-[180px] ${clsx({ "border-red-500": formState.errors?.regionId })}`}
 | 
			
		||||
          >
 | 
			
		||||
            <SelectValue placeholder="Region" />
 | 
			
		||||
          </SelectTrigger>
 | 
			
		||||
          <SelectContent>
 | 
			
		||||
            {selectCountryRegions.map((region) => (
 | 
			
		||||
              <SelectItem key={region.id} value={region.id}>
 | 
			
		||||
                {region.name}
 | 
			
		||||
              </SelectItem>
 | 
			
		||||
            ))}
 | 
			
		||||
          </SelectContent>
 | 
			
		||||
        </Select>
 | 
			
		||||
        <Input
 | 
			
		||||
          name="name"
 | 
			
		||||
          id="name"
 | 
			
		||||
          placeholder="Name"
 | 
			
		||||
          className={`${clsx({ "border-red-500": formState.errors?.name })}`}
 | 
			
		||||
        />
 | 
			
		||||
        <div className="flex max-w-3xl items-center gap-2">
 | 
			
		||||
          <Select name="regionId">
 | 
			
		||||
            <SelectTrigger
 | 
			
		||||
              className={`w-[180px] ${clsx({ "border-red-500": formState.errors?.regionId })}`}
 | 
			
		||||
            >
 | 
			
		||||
              <SelectValue placeholder="select region" />
 | 
			
		||||
            </SelectTrigger>
 | 
			
		||||
            <SelectContent>
 | 
			
		||||
              {selectCountryRegions.map((region) => (
 | 
			
		||||
                <SelectItem key={region.id} value={region.id}>
 | 
			
		||||
                  {region.name}
 | 
			
		||||
                </SelectItem>
 | 
			
		||||
              ))}
 | 
			
		||||
            </SelectContent>
 | 
			
		||||
          </Select>
 | 
			
		||||
          {formState.message === "success" && !formState.errors?.regionId ? (
 | 
			
		||||
            <Check className="text-green-500" />
 | 
			
		||||
          ) : (
 | 
			
		||||
            ""
 | 
			
		||||
          )}
 | 
			
		||||
          {formState.errors?.regionId ? (
 | 
			
		||||
            <div className="flex min-w-40 items-center gap-1 text-red-500">
 | 
			
		||||
              <CircleX className="text-red-500" />
 | 
			
		||||
              <span className="text-sm">{formState.errors?.regionId}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
          ) : (
 | 
			
		||||
            ""
 | 
			
		||||
          )}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="flex max-w-3xl items-center gap-2">
 | 
			
		||||
          <Input
 | 
			
		||||
            name="name"
 | 
			
		||||
            id="name"
 | 
			
		||||
            placeholder="Name the sub region"
 | 
			
		||||
            className={`${clsx({ "border-red-500": formState.errors?.name })}`}
 | 
			
		||||
          />
 | 
			
		||||
          {formState.message === "success" && !formState.errors?.name ? (
 | 
			
		||||
            <Check className="text-green-500" />
 | 
			
		||||
          ) : (
 | 
			
		||||
            ""
 | 
			
		||||
          )}
 | 
			
		||||
          {formState.errors?.name ? (
 | 
			
		||||
            <div className="flex min-w-40 items-center gap-1 text-red-500">
 | 
			
		||||
              <CircleX className="text-red-500" />
 | 
			
		||||
              <span className="text-sm">{formState.errors?.name}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
          ) : (
 | 
			
		||||
            ""
 | 
			
		||||
          )}
 | 
			
		||||
        </div>
 | 
			
		||||
        <SubmitButton text={"sub region"} />
 | 
			
		||||
      </form>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								src/app/_components/allProducers.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/app/_components/allProducers.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
import { Delete } from "lucide-react";
 | 
			
		||||
import deleteProducer from "~/server/actions/deleteProducer";
 | 
			
		||||
import getAllProducers from "~/server/actions/getAllProducers";
 | 
			
		||||
 | 
			
		||||
export default async function AllProducers() {
 | 
			
		||||
  const allProducers = await getAllProducers();
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="pt-4">
 | 
			
		||||
      <h1 className="text-2xl">All Producers:</h1>
 | 
			
		||||
      {allProducers.map((producer) => (
 | 
			
		||||
        <div key={producer.id} className="flex gap-1">
 | 
			
		||||
          <p>{producer.name}</p>
 | 
			
		||||
          <form action={deleteProducer.bind(null, producer.id)}>
 | 
			
		||||
            <button>
 | 
			
		||||
              <Delete />
 | 
			
		||||
            </button>
 | 
			
		||||
          </form>
 | 
			
		||||
        </div>
 | 
			
		||||
      ))}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/components/ui/textarea.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/components/ui/textarea.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
import * as React from "react"
 | 
			
		||||
 | 
			
		||||
import { cn } from "~/lib/utils"
 | 
			
		||||
 | 
			
		||||
export interface TextareaProps
 | 
			
		||||
  extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
 | 
			
		||||
 | 
			
		||||
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
 | 
			
		||||
  ({ className, ...props }, ref) => {
 | 
			
		||||
    return (
 | 
			
		||||
      <textarea
 | 
			
		||||
        className={cn(
 | 
			
		||||
          "flex min-h-[80px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm ring-offset-white placeholder:text-slate-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-800 dark:bg-slate-950 dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus-visible:ring-slate-300",
 | 
			
		||||
          className
 | 
			
		||||
        )}
 | 
			
		||||
        ref={ref}
 | 
			
		||||
        {...props}
 | 
			
		||||
      />
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
Textarea.displayName = "Textarea"
 | 
			
		||||
 | 
			
		||||
export { Textarea }
 | 
			
		||||
							
								
								
									
										77
									
								
								src/server/actions/addProducer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/server/actions/addProducer.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import { eq } from "drizzle-orm";
 | 
			
		||||
import { db } from "../db";
 | 
			
		||||
import { producers } from "../db/schema";
 | 
			
		||||
import { ZodError, z } from "zod";
 | 
			
		||||
import { revalidatePath } from "next/cache";
 | 
			
		||||
 | 
			
		||||
export const addProducer = async (prevstate: any, formData: FormData) => {
 | 
			
		||||
  //assign formdaata to variables.
 | 
			
		||||
  const name = (formData.get("name") as string).toLowerCase();
 | 
			
		||||
  const description = (formData.get("description") as string).toLowerCase();
 | 
			
		||||
  const imageUrl = (formData.get("imageUrl") as string).toLowerCase();
 | 
			
		||||
  const countryId = formData.get("countryId") as string;
 | 
			
		||||
 | 
			
		||||
  //check if producer already exists in country
 | 
			
		||||
  const exists = await db
 | 
			
		||||
    .select({ name: producers.name })
 | 
			
		||||
    .from(producers)
 | 
			
		||||
    .where(eq(producers.name, name));
 | 
			
		||||
 | 
			
		||||
  //Define the schema for the form data
 | 
			
		||||
  const schema = z.object({
 | 
			
		||||
    name: z
 | 
			
		||||
      .string()
 | 
			
		||||
      .min(1, "Name is required")
 | 
			
		||||
      .refine(() => !exists[0], {
 | 
			
		||||
        message: `${name} already exists in selected country`,
 | 
			
		||||
      }),
 | 
			
		||||
    description: z.string(),
 | 
			
		||||
    imageUrl: z.string(),
 | 
			
		||||
    countryId: z.string().min(1, "No country selected"),
 | 
			
		||||
  });
 | 
			
		||||
  //Parse the form data using the schema for validation, and check if the name already exists
 | 
			
		||||
  try {
 | 
			
		||||
    schema.parse({
 | 
			
		||||
      name,
 | 
			
		||||
      description,
 | 
			
		||||
      imageUrl,
 | 
			
		||||
      countryId,
 | 
			
		||||
    });
 | 
			
		||||
    //If the name doesn't exist, add the country to the database abd revalidate the page
 | 
			
		||||
    await db
 | 
			
		||||
      .insert(producers)
 | 
			
		||||
      .values({ name, description, imageUrl, countryId });
 | 
			
		||||
    revalidatePath("/");
 | 
			
		||||
    //Return a success message
 | 
			
		||||
    return {
 | 
			
		||||
      message: "success",
 | 
			
		||||
      errors: undefined,
 | 
			
		||||
      fieldValues: {
 | 
			
		||||
        name: "",
 | 
			
		||||
        description: "",
 | 
			
		||||
        imageUrl: "",
 | 
			
		||||
        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] ?? "",
 | 
			
		||||
        description: errorMap["description"]?.[0] ?? "",
 | 
			
		||||
        imageUrl: errorMap["imageUrl"]?.[0] ?? "",
 | 
			
		||||
        countryId: errorMap["countryId"]?.[0] ?? "",
 | 
			
		||||
      },
 | 
			
		||||
      fieldValues: {
 | 
			
		||||
        name,
 | 
			
		||||
        description,
 | 
			
		||||
        imageUrl,
 | 
			
		||||
        countryId,
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";
 | 
			
		||||
import { db } from "../db";
 | 
			
		||||
import { subRegions } from "../db/schema";
 | 
			
		||||
import { ZodError, z } from "zod";
 | 
			
		||||
import { revalidatePath } from "next/cache";
 | 
			
		||||
 | 
			
		||||
export const addSubRegion = async (prevstate: any, formData: FormData) => {
 | 
			
		||||
  //assign formdaata to variables.
 | 
			
		||||
@ -34,6 +35,7 @@ export const addSubRegion = async (prevstate: any, formData: FormData) => {
 | 
			
		||||
    });
 | 
			
		||||
    //If the name doesn't exist, add the country to the database abd revalidate the page
 | 
			
		||||
    await db.insert(subRegions).values({ regionId, name });
 | 
			
		||||
    revalidatePath("/");
 | 
			
		||||
    //Return a success message
 | 
			
		||||
    return {
 | 
			
		||||
      message: "success",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/server/actions/deleteProducer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/server/actions/deleteProducer.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import { eq } from "drizzle-orm";
 | 
			
		||||
import { db } from "../db";
 | 
			
		||||
import { producers } from "../db/schema";
 | 
			
		||||
import { revalidatePath } from "next/cache";
 | 
			
		||||
 | 
			
		||||
export default async function deleteProducer(id: string) {
 | 
			
		||||
  await db.delete(producers).where(eq(producers.id, id));
 | 
			
		||||
  revalidatePath("/");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/server/actions/deleteRegion.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/server/actions/deleteRegion.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import { eq } from "drizzle-orm";
 | 
			
		||||
import { db } from "../db";
 | 
			
		||||
import { regions } from "../db/schema";
 | 
			
		||||
import { revalidatePath } from "next/cache";
 | 
			
		||||
 | 
			
		||||
export default async function deleteRegion(id: string) {
 | 
			
		||||
  await db.delete(regions).where(eq(regions.id, id));
 | 
			
		||||
  revalidatePath("/");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/server/actions/deleteSubRegion.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/server/actions/deleteSubRegion.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import { eq } from "drizzle-orm";
 | 
			
		||||
import { db } from "../db";
 | 
			
		||||
import { subRegions } from "../db/schema";
 | 
			
		||||
import { revalidatePath } from "next/cache";
 | 
			
		||||
 | 
			
		||||
export default async function deleteSubRegion(id: string) {
 | 
			
		||||
  await db.delete(subRegions).where(eq(subRegions.id, id));
 | 
			
		||||
  revalidatePath("/");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								src/server/actions/getAllProducers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/server/actions/getAllProducers.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import { db } from "../db";
 | 
			
		||||
 | 
			
		||||
export default async function getAllProducers() {
 | 
			
		||||
  const allProducers = await db.query.producers.findMany();
 | 
			
		||||
  return allProducers;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								src/server/actions/getAllSubRegions.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/server/actions/getAllSubRegions.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import { db } from "../db";
 | 
			
		||||
 | 
			
		||||
export default async function getAllSubRegions() {
 | 
			
		||||
  const allSubRegions = await db.query.subRegions.findMany();
 | 
			
		||||
  return allSubRegions;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user