added more descriptive error handling of forms #11
@ -23,19 +23,22 @@ export default function CreateCountryForm() {
 | 
			
		||||
  }, [formState.message]);
 | 
			
		||||
  return (
 | 
			
		||||
    <form ref={formRef} action={formAction} className="flex flex-col gap-2">
 | 
			
		||||
      <div className="flex items-center gap-2">
 | 
			
		||||
      <div className="flex max-w-3xl items-center gap-2">
 | 
			
		||||
        <Input
 | 
			
		||||
          name="name"
 | 
			
		||||
          id="name"
 | 
			
		||||
          className={clsx({ "border-red-500": formState.errors?.name })}
 | 
			
		||||
        />
 | 
			
		||||
        {formState.message === "success" ? (
 | 
			
		||||
        {formState.message !== "" && !formState.errors?.name ? (
 | 
			
		||||
          <Check className="text-green-500" />
 | 
			
		||||
        ) : (
 | 
			
		||||
          ""
 | 
			
		||||
        )}
 | 
			
		||||
        {formState.message === "error" ? (
 | 
			
		||||
          <CircleX className="text-red-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>
 | 
			
		||||
        ) : (
 | 
			
		||||
          ""
 | 
			
		||||
        )}
 | 
			
		||||
 | 
			
		||||
@ -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<HTMLFormElement>(null);
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (formState.message === "success") {
 | 
			
		||||
      formRef.current?.reset();
 | 
			
		||||
    }
 | 
			
		||||
  }, [formState.message]);
 | 
			
		||||
  return (
 | 
			
		||||
    <form action={formAction}>
 | 
			
		||||
      <Input name="name" />
 | 
			
		||||
      <Select name="country">
 | 
			
		||||
        <SelectTrigger className="w-[180px]">
 | 
			
		||||
          <SelectValue placeholder="Country" />
 | 
			
		||||
        </SelectTrigger>
 | 
			
		||||
        <SelectContent>
 | 
			
		||||
          {countries.map((country) => (
 | 
			
		||||
            <SelectItem key={country.id} value={country.id}>
 | 
			
		||||
              {country.name}
 | 
			
		||||
            </SelectItem>
 | 
			
		||||
          ))}
 | 
			
		||||
        </SelectContent>
 | 
			
		||||
      </Select>
 | 
			
		||||
    <form ref={formRef} action={formAction} className="flex flex-col gap-2">
 | 
			
		||||
      <div className="flex max-w-3xl items-center gap-2">
 | 
			
		||||
        <Input
 | 
			
		||||
          name="name"
 | 
			
		||||
          id="name"
 | 
			
		||||
          placeholder="Name"
 | 
			
		||||
          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>
 | 
			
		||||
      <div className="flex max-w-3xl items-center gap-2">
 | 
			
		||||
        <Select name="country">
 | 
			
		||||
          <SelectTrigger
 | 
			
		||||
            className={`w-[180px] ${clsx({ "border-red-500": formState.errors?.countryId })}`}
 | 
			
		||||
          >
 | 
			
		||||
            <SelectValue placeholder="Country" />
 | 
			
		||||
          </SelectTrigger>
 | 
			
		||||
          <SelectContent>
 | 
			
		||||
            {countries.map((country) => (
 | 
			
		||||
              <SelectItem key={country.id} value={country.id}>
 | 
			
		||||
                {country.name}
 | 
			
		||||
              </SelectItem>
 | 
			
		||||
            ))}
 | 
			
		||||
          </SelectContent>
 | 
			
		||||
        </Select>
 | 
			
		||||
        {formState.message !== "" && !formState.errors?.countryId ? (
 | 
			
		||||
          <Check className="text-green-500" />
 | 
			
		||||
        ) : (
 | 
			
		||||
          ""
 | 
			
		||||
        )}
 | 
			
		||||
        {formState.errors?.countryId ? (
 | 
			
		||||
          <CircleX className="text-red-500" />
 | 
			
		||||
        ) : (
 | 
			
		||||
          ""
 | 
			
		||||
        )}
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <SubmitButton text={"Region"} />
 | 
			
		||||
      <span>{state?.message}</span>
 | 
			
		||||
    </form>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user