Enterprise-CMCS/macpro-mako

View on GitHub
react-app/src/components/RHF/FieldArray.tsx

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import { useEffect } from "react";
import { FieldValues, useFieldArray } from "react-hook-form";
import { FieldArrayProps } from "shared-types";
import { Plus, Trash2 } from "lucide-react";
import { Button } from "../Inputs";
import { slotInitializer } from "./utils";
import { Field } from "./Field";
import { cn } from "@/utils";

export const RHFFieldArray = <TFields extends FieldValues>(
  props: FieldArrayProps<TFields>,
) => {
  const fieldArr = useFieldArray<any>({
    control: props.control,
    name: props.name,
    shouldUnregister: true,
  });

  const onAppend = () => {
    fieldArr.append(props.fields.reduce(slotInitializer(), {}) as never);
  };

  useEffect(() => {
    if (fieldArr.fields.length) return;
    fieldArr.append(props.fields.reduce(slotInitializer(), {}) as never, {
      shouldFocus: false,
    });
  }, [fieldArr, props.fields]);

  return (
    <div className={"flex flex-col gap-6 w-full"}>
      {fieldArr.fields.map((FLD, index) => {
        return (
          <div
            className={cn("flex flex-row gap-6", props.fieldArrayClassName)}
            key={FLD.id}
          >
            {props.fields.map((SLOT, i) => {
              return (
                <Field
                  key={`${SLOT.name}-${i}`}
                  {...props}
                  index={index}
                  SLOT={SLOT}
                />
              );
            })}
            {/* FieldArray Removal */}
            {index >= 1 && !props.removeText && (
              <Trash2
                className="self-end mb-2 cursor-pointer stroke-primary"
                data-testid={`removeRowButton-${index}`}
                onClick={() => fieldArr.remove(index)}
              />
            )}
            {/* FieldGroup Removal */}
            {index >= 1 && props.removeText && (
              <Button
                className="self-end m-2 mr-0"
                variant={"destructive"}
                data-testid={`removeGroupButton-${index}`}
                onClick={() => {
                  fieldArr.remove(index);
                }}
              >
                {props.removeText ?? "Remove Group"}
              </Button>
            )}
            {props.divider && (
              <div className="w-full border-slate-300 border-b-[1px]" />
            )}
          </div>
        );
      })}
      {props.lastDivider && (
        <div
          className={cn(
            "w-full border-slate-300 border-b-[1px]",
            props.lastDivider,
          )}
        />
      )}
      <div className={cn("flex items-center", props.appendClassName)}>
        <Button
          type="button"
          size="sm"
          onClick={onAppend}
          data-testid={`appendRowButton-${props.name}`}
          variant={props.appendVariant ?? "outline"}
        >
          <Plus className="h-5 w-5 mr-2" />
          {props.appendText || "New Row"}
        </Button>
      </div>
    </div>
  );
};