vorteil/direktiv

View on GitHub
ui/src/pages/namespace/Explorer/Endpoint/EndpointEditor/Form/index.tsx

Summary

Maintainability
B
4 hrs
Test Coverage
import {
  Controller,
  DeepPartialSkipArrayKey,
  UseFormReturn,
  useForm,
} from "react-hook-form";
import { EndpointFormSchema, EndpointFormSchemaType } from "../schema";

import { AuthPluginForm } from "./plugins/Auth";
import Badge from "~/design/Badge";
import { Checkbox } from "~/design/Checkbox";
import { FC } from "react";
import { Fieldset } from "~/components/Form/Fieldset";
import { InboundPluginForm } from "./plugins/Inbound";
import Input from "~/design/Input";
import { OutboundPluginForm } from "./plugins/Outbound";
import { Switch } from "~/design/Switch";
import { TargetPluginForm } from "./plugins/Target";
import { routeMethods } from "~/api/gateway/schema";
import { treatAsNumberOrUndefined } from "../../../utils";
import { useSortedValues } from "./utils";
import { useTranslation } from "react-i18next";
import { zodResolver } from "@hookform/resolvers/zod";

type FormProps = {
  defaultConfig?: EndpointFormSchemaType;
  onSave: (value: EndpointFormSchemaType) => void;
  children: (args: {
    formControls: UseFormReturn<EndpointFormSchemaType>;
    formMarkup: JSX.Element;
    values: DeepPartialSkipArrayKey<EndpointFormSchemaType>;
  }) => JSX.Element;
};

export const Form: FC<FormProps> = ({ defaultConfig, children, onSave }) => {
  const { t } = useTranslation();
  const formControls = useForm<EndpointFormSchemaType>({
    resolver: zodResolver(EndpointFormSchema),
    defaultValues: {
      ...defaultConfig,
    },
  });

  const values = useSortedValues(formControls.control);
  const { register, control } = formControls;

  return children({
    formControls,
    values,
    formMarkup: (
      <div className="flex flex-col gap-8">
        <div className="flex gap-3">
          <Fieldset
            label={t("pages.explorer.endpoint.editor.form.path")}
            htmlFor="path"
            className="grow"
          >
            <Input {...register("path")} id="path" />
          </Fieldset>
          <Fieldset
            label={t("pages.explorer.endpoint.editor.form.timeout")}
            htmlFor="timeout"
            className="w-32"
          >
            <Input
              {...register("timeout", {
                setValueAs: treatAsNumberOrUndefined,
              })}
              type="number"
              id="timeout"
            />
          </Fieldset>
        </div>
        <Fieldset label={t("pages.explorer.endpoint.editor.form.methods")}>
          <Controller
            control={control}
            name="methods"
            render={({ field }) => (
              <div className="grid grid-cols-3 gap-5">
                {routeMethods.map((method) => {
                  const isChecked = field.value?.includes(method);
                  return (
                    <label
                      key={method}
                      className="flex items-center gap-2 text-sm"
                      htmlFor={method}
                    >
                      <Checkbox
                        id={method}
                        value={method}
                        checked={isChecked}
                        onCheckedChange={(checked) => {
                          if (checked === true) {
                            field.onChange([...(field.value ?? []), method]);
                          }
                          if (checked === false && field.value) {
                            field.onChange(
                              field.value.filter((v) => v !== method)
                            );
                          }
                        }}
                      />
                      <Badge variant={isChecked ? undefined : "secondary"}>
                        {method}
                      </Badge>
                    </label>
                  );
                })}
              </div>
            )}
          />
        </Fieldset>
        <Fieldset
          label={t("pages.explorer.endpoint.editor.form.allowAnonymous")}
          htmlFor="allow_anonymous"
          horizontal
        >
          <Controller
            control={control}
            name="allow_anonymous"
            render={({ field }) => (
              <Switch
                defaultChecked={field.value ?? false}
                onCheckedChange={(value) => {
                  field.onChange(value);
                }}
                id="allow_anonymous"
              />
            )}
          />
        </Fieldset>
        <TargetPluginForm form={formControls} onSave={onSave} />
        <InboundPluginForm form={formControls} onSave={onSave} />
        <OutboundPluginForm form={formControls} onSave={onSave} />
        <AuthPluginForm formControls={formControls} onSave={onSave} />
      </div>
    ),
  });
};