Preview:
I will toss you some code and at the and formulate what i want:

addOffshoreForm.tsx :

import {
  ButtonContent,
  DestructiveButton,
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  Icon,
  If,
  Input,
  Toaster,
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import type * as z from "zod";
import React, { useEffect, useState } from "react";
import { toast } from "sonner";
import wretch from "wretch";
import type { VesselInfo } from "@/components/forms/offshoreInfoForm";
import {
  fieldsNameHelper,
  formSchema,
  numberFields,
  toTitleCase,
} from "@/components/forms/offshoreInfoForm";
import type { PostgrestError } from "@supabase/supabase-js";

interface AddOffshoreFormProps {
  fields: string[];
  vesselType: string;
  vesselSubType: string;
  vesselMmsi: string;
  returnMmsi: (mmsi: any) => void;
}

export const AddOffshoreForm = ({
  fields,
  vesselType,
  vesselSubType,
  vesselMmsi,
  returnMmsi,
}: AddOffshoreFormProps) => {
  const excludeFields: string[] = [
    "id",
    "vessel_id",
    "postion_date",
    "eta_iso",
    "destination",
    "longitude",
    "latitude",
    "callsign",
  ];
  const disabledFields: string[] = ["type", "subType"];

  const [selectedType, setSelectedType] = useState<string>();
  const [selectedSubType, setSelectedSubType] = useState<string>(vesselSubType);
  const [mmsi, setMmsi] = useState<string>(vesselMmsi.toString());

  // update selectedType and selectedSubType when vesselType and vesselSubType change
  useEffect(() => {
    setSelectedType(vesselType);
    setSelectedSubType(vesselSubType);
    setMmsi(vesselMmsi);
  }, [vesselType, vesselSubType, vesselMmsi]);

  fields = fields?.sort().filter((item) => !excludeFields.includes(item));

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      type: selectedType,
      subType: selectedSubType,
      mmsi: mmsi,
    },
  });

  async function onSubmit(values: z.infer<typeof formSchema>) {
    const addVessel: VesselInfo = Object.entries(values).reduce(
      (acc: VesselInfo, [key, value]) => {
        const vesselInfoKey: string = fieldsNameHelper[key].name;
        if (key === "subType") {
          acc[vesselInfoKey] = selectedSubType?.toLowerCase() || "";
        } else if (key === "type") {
          acc[vesselInfoKey] = selectedType?.toLowerCase() || "";
        } else if (key === "mmsi") {
          acc[vesselInfoKey] = mmsi;
        } else {
          acc[vesselInfoKey] = (value || "").toString().toLowerCase() || "";
        }
        return acc;
      },
      {},
    );

    try {
      const response = await wretch("/api/form/insertOffshoreVessel")
        .post(addVessel)
        .res();

      if (response.ok) {
        toast.success("Success!", {
          description: "Vessel details inserted.",
        });
        returnMmsi(Number(mmsi));
      } else {
        toast.error("Error submitting form");
      }
    } catch (error) {
      toast.error("Something went wrong", {
        description: (error as PostgrestError | null)?.message,
      });
    }
  }

  const reset = form.reset;

  useEffect(() => {
    reset({}, { keepValues: false });

    reset(
      {
        type: vesselType,
        subType: selectedSubType || vesselSubType,
        mmsi: mmsi,
      },
      { keepValues: false },
    );
  }, [reset]);

  return (
    <div className={"mt-4"}>
      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
          {Object.keys(formSchema.shape).map((key, index) => (
            <>
              <If condition={fields?.includes(fieldsNameHelper[key].name)}>
                <If condition={key !== "buildYear"}>
                  <FormField
                    key={key + index}
                    control={form.control}
                    name={key as any}
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          {toTitleCase(fieldsNameHelper[key].name)}
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <FormControl className={"w-full"}>
                          <Input
                            className={"text-md font-light"}
                            required={false}
                            {...field}
                            type={
                              numberFields.includes(key) ? "number" : "text"
                            }
                            value={field.value ?? ""}
                            disabled={disabledFields.includes(key)}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </If>
                <If condition={key === "buildYear"}>
                  <FormField
                    control={form.control}
                    name="buildYear"
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          Build year
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <FormControl className={"w-full"}>
                          <Input
                            {...field}
                            className={"text-md font-light"}
                            type="number"
                            min={1900}
                            max={2100}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </If>
              </If>
            </>
          ))}
          <div className="flex flex-row justify-end">
            <DestructiveButton type="submit" className="mt-4">
              <ButtonContent>Add vessel</ButtonContent>
            </DestructiveButton>
          </div>
          <Toaster />
        </form>
      </Form>
    </div>
  );
};

offshoreInfoForm.tsx :

import {
  ButtonContent,
  DestructiveButton,
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  Icon,
  If,
  Input,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  Toaster,
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import * as z from "zod";
import React, { useEffect, useState } from "react";
import { toast } from "sonner";
import type { PostgrestError } from "@supabase/supabase-js";
import wretch from "wretch";

export interface VesselInfo {
  [key: string]: string | undefined;
}

interface AddOffshoreFormProps {
  vesselInfo: VesselInfo;
  vesselMmsi: number;
}

export const formSchema = z.object({
  beneficialOwner: z.string().optional(),
  bollardPull: z.string().optional(),
  bsW: z.string().optional(),
  bucketCapacity: z.string().optional(),
  buildYear: z.string().optional(),
  cableTanks: z.string().optional(),
  callsign: z.string().optional(),
  class: z.string().optional(),
  clearDeckArea: z.string().optional(),
  commercialOwner: z.string().optional(),
  craneSize: z.string().optional(),
  cranes: z.string().optional(),
  crudeProcessingCapacity: z.string().optional(),
  cutterPower: z.string().optional(),
  deckArea: z.string().optional(),
  deckLoadCapacity: z.string().optional(),
  designType: z.string().optional(),
  destination: z.string().optional(),
  dredgeDepth: z.string().optional(),
  dredgePumpPower: z.string().optional(),
  dynamicPositioningClass: z.string().optional(),
  engineTypePower: z.string().optional(),
  etaIso: z.string().optional(),
  excavatorPower: z.string().optional(),
  exportableCrude: z.string().optional(),
  fleetName: z.string().optional(),
  fleetOperator: z.string().optional(),
  fluidCapacity: z.string().optional(),
  fuelCapacity: z.string().optional(),
  gas: z.string().optional(),
  grossTonnage: z.string().optional(),
  hS: z.string().optional(),
  heliDeck: z.string().optional(),
  hopperCapacity: z.string().optional(),
  id: z.string().optional(),
  imo: z.string().optional(),
  jetPumps: z.string().optional(),
  latitude: z.string().optional(),
  legs: z.string().optional(),
  longitude: z.string().optional(),
  mainEnginesTypePower: z.string().optional(),
  maxDredgeWidth: z.string().optional(),
  maxFlow: z.string().optional(),
  maxSpeed: z.string().optional(),
  mmsi: z.string().optional(),
  moonPool: z.string().optional(),
  noOfBerths: z.string().optional(),
  oilContentWaterDischarged: z.string().optional(),
  pdfDownloaded: z.string().optional(),
  pipeDiameter: z.string().optional(),
  positionTime: z.string().optional(),
  producedWater: z.string().optional(),
  pumpingDistance: z.string().optional(),
  rov: z.string().optional(),
  rvp: z.string().optional(),
  slopTanks: z.string().optional(),
  specialisedCarriageCapability: z.string().optional(),
  speedConsumption: z.string().optional(),
  subType: z.string().optional(),
  totalPowerInstalled: z.string().optional(),
  towingCapacity: z.string().optional(),
  tugType: z.string().optional(),
  type: z.string().optional(),
  vesselClass: z.string().optional(),
  vesselName: z.string().optional(),
  vesselType: z.string().optional(),
  vesselId: z.string().optional(),
  waterInjectionCapacity: z.string().optional(),
});

type FieldsNameHelper = {
  [key: string]: { name: string; description: string };
};

export const fieldsNameHelper: FieldsNameHelper = {
  beneficialOwner: {
    name: "beneficial owner",
    description: "The beneficial owner of the vessel",
  },
  bollardPull: {
    name: "bollard pull",
    description: "The force exerted by the vessel while tethered",
  },
  bsW: {
    name: "bs&w",
    description: "Basic sediment and water in oil measurement",
  },
  bucketCapacity: {
    name: "bucket capacity",
    description: "Maximum carrying capacity of the bucket",
  },
  buildYear: {
    name: "build year",
    description: "Year the vessel was constructed",
  },
  cableTanks: {
    name: "cable tanks",
    description: "Storage tanks for cables on the vessel",
  },
  callsign: {
    name: "callsign",
    description: "The identifying signal letters or numbers of the vessel",
  },
  class: {
    name: "class",
    description: "Classification society to which the vessel is registered",
  },
  clearDeckArea: {
    name: "clear deck area",
    description: "Total area available for use on the deck",
  },
  commercialOwner: {
    name: "commercial owner",
    description: "The commercial owner of the vessel",
  },
  craneSize: {
    name: "crane size",
    description: "The size and lifting capacity of the crane on the vessel",
  },
  cranes: {
    name: "cranes",
    description: "The number and type of cranes installed on the vessel",
  },
  crudeProcessingCapacity: {
    name: "crude processing capacity",
    description: "Capacity to process crude oil onboard",
  },
  cutterPower: {
    name: "cutter power",
    description: "Power output of the cutting equipment on the vessel",
  },
  deckArea: {
    name: "deck area",
    description: "Total area of the vessel's deck",
  },
  deckLoadCapacity: {
    name: "deck load capacity",
    description: "Maximum load capacity of the vessel’s deck",
  },
  designType: {
    name: "design/type",
    description: "The design and type classification of the vessel",
  },
  destination: {
    name: "destination",
    description: "The intended destination of the vessel",
  },
  dredgeDepth: {
    name: "dredge depth",
    description: "Maximum depth at which the vessel can dredge",
  },
  dredgePumpPower: {
    name: "dredge pump power",
    description: "Power of the dredging pump",
  },
  dynamicPositioningClass: {
    name: "dynamic positioning class",
    description: "Classification of the vessel's dynamic positioning system",
  },
  engineTypePower: {
    name: "engine type & power",
    description: "Type and power output of the vessel’s engines",
  },
  etaIso: {
    name: "eta_iso",
    description: "Estimated time of arrival following ISO standards",
  },
  excavatorPower: {
    name: "excavator power",
    description: "Power output of the excavator on the vessel",
  },
  exportableCrude: {
    name: "exportable crude",
    description: "Volume of crude oil that can be exported by the vessel",
  },
  fleetName: {
    name: "fleet name",
    description: "Name of the fleet the vessel belongs to",
  },
  fleetOperator: {
    name: "fleet operator",
    description: "Operator managing the fleet of vessels",
  },
  fluidCapacity: {
    name: "fluid capacity",
    description: "Total capacity for fluid storage on the vessel",
  },
  fuelCapacity: {
    name: "fuel capacity",
    description: "Fuel storage capacity of the vessel",
  },
  gas: {
    name: "gas",
    description:
      "Capabilities or systems related to gas handling on the vessel",
  },
  grossTonnage: {
    name: "gross tonnage",
    description: "Overall internal volume of the vessel",
  },
  hS: {
    name: "h2s",
    description: "Presence and handling of hydrogen sulfide on the vessel",
  },
  heliDeck: {
    name: "heli-deck",
    description: "Helicopter landing area available on the vessel",
  },
  hopperCapacity: {
    name: "hopper capacity",
    description: "Storage capacity of the hopper on the dredging vessel",
  },
  id: { name: "id", description: "Unique identifier of the vessel" },
  imo: {
    name: "imo",
    description:
      "International Maritime Organization number assigned to the vessel",
  },
  jetPumps: {
    name: "jet pumps",
    description: "Types and capacities of jet pumps on the vessel",
  },
  latitude: {
    name: "latitude",
    description: "Current latitude position of the vessel",
  },
  legs: {
    name: "legs",
    description:
      "Structural supports used in vessels, particularly in offshore applications",
  },
  longitude: {
    name: "longitude",
    description: "Current longitude position of the vessel",
  },
  mainEnginesTypePower: {
    name: "main engines type & power",
    description: "Type and power of the main engines on the vessel",
  },
  maxDredgeWidth: {
    name: "max dredge width",
    description: "Maximum width the vessel can dredge",
  },
  maxFlow: {
    name: "max flow",
    description: "Maximum flow rate achievable by the vessel’s systems",
  },
  maxSpeed: {
    name: "max speed (buckets/min)",
    description:
      "Maximum operational speed of the vessel in buckets per minute",
  },
  mmsi: {
    name: "mmsi",
    description:
      "Maritime Mobile Service Identity used for vessel tracking and safety",
  },
  moonPool: {
    name: "moon pool",
    description:
      "An opening in the bottom or side of the vessel for underwater operations",
  },
  noOfBerths: {
    name: "no of berths",
    description: "Number of sleeping berths available on the vessel",
  },
  oilContentWaterDischarged: {
    name: "oil content water discharged",
    description: "Measure of oil content in discharged water",
  },
  pdfDownloaded: {
    name: "pdf downloaded (y/n)",
    description:
      "Indicates if the vessel’s documentation has been downloaded as PDF",
  },
  pipeDiameter: {
    name: "pipe diameter",
    description: "Diameter of pipes used onboard the vessel",
  },
  positionTime: {
    name: "position_time",
    description: "Timestamp for the vessel's position",
  },
  producedWater: {
    name: "produced water",
    description: "Water produced as a byproduct of the vessel’s operations",
  },
  pumpingDistance: {
    name: "pumping distance",
    description: "Maximum distance over which the vessel can pump materials",
  },
  rov: {
    name: "rov",
    description: "Remotely operated vehicle capabilities of the vessel",
  },
  rvp: {
    name: "rvp",
    description:
      "Reid vapor pressure measurements related to the vessel’s operations",
  },
  slopTanks: {
    name: "slop tanks",
    description:
      "Tanks on the vessel used for temporary storage of oily waste water",
  },
  specialisedCarriageCapability: {
    name: "specialised carriage capability",
    description:
      "Specific carriage capabilities of the vessel for specialized cargoes",
  },
  speedConsumption: {
    name: "speed/consumption",
    description: "The vessel’s speed relative to fuel consumption",
  },
  subType: {
    name: "sub_type",
    description: "Sub-type classification of the vessel",
  },
  totalPowerInstalled: {
    name: "total power installed",
    description: "Total power output of all installed machinery",
  },
  towingCapacity: {
    name: "towing capacity",
    description: "Capacity of the vessel to tow other vessels or structures",
  },
  tugType: {
    name: "tug type",
    description: "Classification of the tug based on its design and use",
  },
  type: {
    name: "type",
    description: "General type classification of the vessel",
  },
  vesselClass: {
    name: "vessel class",
    description: "Class designation for regulatory and operational purposes",
  },
  vesselName: {
    name: "vessel name",
    description: "Official name of the vessel",
  },
  vesselType: {
    name: "vessel type",
    description: "Specific type classification based on structure and function",
  },
  vesselId: {
    name: "vessel_id",
    description: "Unique identification number of the vessel",
  },
  waterInjectionCapacity: {
    name: "water injection capacity",
    description: "Capacity for injecting water into surrounding sea or seabed",
  },
};

export const numberFields: string[] = [
  "bollardPull",
  "buildYear",
  "clearDeckArea",
  "grossTonnage",
  "noOfBerths",
  "dynamicPositioningClass",
  "fuelCapacity",
  "fluidCapacity",
  "deckArea",
  "crudeProcessingCapacity",
  "deckLoadCapacity",
  "waterInjectionCapacity",
  "speedConsumption",
  "totalPowerInstalled",
  "dredgeDepth",
  "maxDredgeWidth",
  "cuttingPower",
  "pumpingDistance",
  "hopperCapacity",
  "bucketCapacity",
  "maxSpeed",
  "mmsi",
  "imo",
];

export const uppercaseFields: string[] = [
  "eta_iso",
  "id",
  "imo",
  "mmsi",
  "h2s",
  "bs&w",
  "rov",
  "rvp",
];

export function toTitleCase(str: string): string {
  if (uppercaseFields.includes(str)) {
    return str.toUpperCase().replace("_", " ");
  } else {
    str = str.replace("_", " ");
    return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
  }
}

export const OffshoreInfoForm = ({
  vesselInfo,
  vesselMmsi,
}: AddOffshoreFormProps) => {
  const disabledFields: string[] = [
    "destination",
    "etaIso",
    "id",
    "imo",
    "latitude",
    "longitude",
    "mmsi",
    "positionTime",
    "vesselId",
  ];
  const [selectedType, setSelectedType] = useState<string | null>(
    vesselInfo["type"] ?? null,
  );

  const defaultFieldsValues = Object.fromEntries(
    Object.keys(fieldsNameHelper).map((key) => [
      key,
      vesselInfo[fieldsNameHelper[key].name as string] ?? "",
    ]),
  );

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: defaultFieldsValues,
  });

  const reset = form.reset;

  useEffect(() => {
    reset({}, { keepValues: false });
    reset(defaultFieldsValues, { keepValues: false });
  }, [reset, defaultFieldsValues]);

  async function onSubmit(values: z.infer<typeof formSchema>) {
    const updatedVesselInfo: VesselInfo = Object.entries(values).reduce(
      (acc: VesselInfo, [key, value]) => {
        const vesselInfoKey: string = fieldsNameHelper[key].name;
        acc[vesselInfoKey] = (value || "").toString().toLowerCase();
        return acc;
      },
      {},
    );

    try {
      const response = await wretch("/api/form/offshoreVessel")
        .post(updatedVesselInfo)
        .res();
      if (response.ok) {
        await wretch(`/api/form/offshoreVessel?mmsi=${vesselMmsi}`)
          .get()
          .json();
        toast.success("Success!", {
          description: "Vessel details updated.",
        });
      } else {
        toast.error("Error submitting form");
      }
    } catch (error) {
      toast.error("Something went wrong", {
        description: (error as PostgrestError | null)?.message,
      });
    }
  }

  return (
    <div className="mt-6 flex w-full flex-col gap-2 p-2 sm:w-1/2">
      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
          {Object.keys(formSchema.shape).map((key, index) => (
            <>
              <If
                condition={Object.keys(vesselInfo).includes(
                  fieldsNameHelper[key].name,
                )}
              >
                <If
                  condition={
                    key !== "type" && key !== "subType" && key !== "buildYear"
                  }
                >
                  <FormField
                    key={key + index}
                    control={form.control}
                    name={key as any}
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          {toTitleCase(fieldsNameHelper[key].name)}
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <FormControl className={"w-full"}>
                          <Input
                            {...field}
                            className={"text-md font-light"}
                            type={
                              numberFields.includes(key) ? "number" : "text"
                            }
                            value={field.value ?? ""}
                            disabled={disabledFields.includes(key)}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </If>
                <If condition={key === "type"}>
                  <FormField
                    control={form.control}
                    name="type"
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          Type
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <Select
                          onValueChange={(value: any) => {
                            field.onChange(value);
                            setSelectedType(value);
                          }}
                          value={field.value ?? ""}
                        >
                          <FormControl className={"text-md w-full font-light"}>
                            <SelectTrigger>
                              <SelectValue placeholder="Select a type" />
                            </SelectTrigger>
                          </FormControl>
                          <SelectContent>
                            <SelectItem value={"offshore support vessel"}>
                              Offshore Support Vessel
                            </SelectItem>
                            <SelectItem
                              value={"oil exploration and drilling vessel"}
                            >
                              Oil Exploration And Drilling Vessel
                            </SelectItem>
                            <SelectItem value={"offshore production vessel"}>
                              Offshore Production Vessel
                            </SelectItem>
                            <SelectItem value={"offshore construction vessel"}>
                              Offshore Construction Vessel
                            </SelectItem>
                          </SelectContent>
                        </Select>
                      </FormItem>
                    )}
                  />
                </If>
                <If condition={key === "subType"}>
                  <FormField
                    control={form.control}
                    name="subType"
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          Sub type
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <Select
                          onValueChange={field.onChange}
                          value={field.value ?? ""}
                        >
                          <FormControl className={"text-md w-full font-light"}>
                            <SelectTrigger>
                              <SelectValue placeholder="Select a sub type" />
                            </SelectTrigger>
                          </FormControl>
                          {selectedType &&
                            selectedType === "offshore support vessel" && (
                              <SelectContent>
                                <SelectItem value={"mpsv"}>MPSV</SelectItem>
                                <SelectItem value={"ahts"}>AHTS</SelectItem>
                                <SelectItem value={"tug"}>Tug</SelectItem>
                                <SelectItem value={"psv"}>PSV</SelectItem>
                              </SelectContent>
                            )}
                          {selectedType &&
                            selectedType === "offshore production vessel" && (
                              <SelectContent>
                                <SelectItem value={"fpso"}>FPSO</SelectItem>
                              </SelectContent>
                            )}
                          {selectedType &&
                            selectedType === "offshore construction vessel" && (
                              <SelectContent>
                                <SelectItem value={"dredger"}>
                                  Dredger
                                </SelectItem>
                                <SelectItem value={"clv"}>CLV</SelectItem>
                                <SelectItem value={"wiv"}>WIV</SelectItem>
                              </SelectContent>
                            )}
                        </Select>
                      </FormItem>
                    )}
                  />
                </If>
                <If condition={key === "buildYear"}>
                  <FormField
                    control={form.control}
                    name="buildYear"
                    render={({ field }) => (
                      <FormItem className={"flex flex-row items-center"}>
                        <FormLabel className={"w-64 text-lg font-light"}>
                          Build year
                        </FormLabel>
                        <div className={"mr-2"}>
                          <TooltipProvider>
                            <Tooltip>
                              <TooltipTrigger className="text-black hover:text-black/50 dark:text-white dark:hover:text-white/50">
                                <Icon name="unknown" style="h-5 w-5" />
                              </TooltipTrigger>
                              <TooltipContent>
                                <p>{fieldsNameHelper[key].description}</p>
                              </TooltipContent>
                            </Tooltip>
                          </TooltipProvider>
                        </div>
                        <FormControl className={"w-full"}>
                          <Input
                            {...field}
                            className={"text-md font-light"}
                            type="number"
                            defaultValue={vesselInfo["build year"]}
                            min={1900}
                            max={2100}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </If>
              </If>
            </>
          ))}
          <If
            condition={vesselInfo && Object.keys(formSchema.shape).length > 0}
          >
            <div className="flex flex-row justify-end">
              <DestructiveButton type="submit" className="mt-4">
                <ButtonContent>Update</ButtonContent>
              </DestructiveButton>
            </div>
          </If>
          <Toaster />
        </form>
      </Form>
    </div>
  );
};

insertOffshoreVessel.ts  :

import type {NextApiRequest, NextApiResponse} from "next";
import wretch from "wretch";
import {env} from "@/env/client.mjs";


/**
 * @swagger
 * /api/form/addLinearReport:
 *   post:
 *     summary: Create a bug report in linear
 *     description: Within the support team.
 *     parameters:
 *        - in: body
 *          name: report
 *          required: true
 *          type: object
 *          description: The report object
 *     produces:
 *       - application/json
 *     responses:
 *       200:
 *         description: Success!
 *       400:
 *         description: No id present as a query parameter.
 *       401:
 *         description: The user does not have an active session or is not authenticated.
 *       405:
 *         description: Method not allowed.
 *       500:
 *         description: Error!
 *     tags:
 *       - deprecated
 */

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const {method} = req;

  switch (method) {
    case "POST":
      try {
        const response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}insert_vessel`)
          .post(req.body)
          .json();
        return res.status(200).json(response);
      } catch (error) {
        console.error("Error origin: POST /api/form/insertOffshoreVessel", error);
        return res.status(500).json(error);
      }
    default:
      res.setHeader("Allow", ["POST"]);
      return res
        .status(405)
        .send(`Method ${method ?? "Undefined"} Not Allowed`);
  }
}

import type {NextApiRequest, NextApiResponse} from "next";
import wretch from "wretch";
import {env} from "@/env/client.mjs";


/**
 * @swagger
 * /api/form/addLinearReport:
 *   post:
 *     summary: Create a bug report in linear
 *     description: Within the support team.
 *     parameters:
 *        - in: body
 *          name: report
 *          required: true
 *          type: object
 *          description: The report object
 *     produces:
 *       - application/json
 *     responses:
 *       200:
 *         description: Success!
 *       400:
 *         description: No id present as a query parameter.
 *       401:
 *         description: The user does not have an active session or is not authenticated.
 *       405:
 *         description: Method not allowed.
 *       500:
 *         description: Error!
 *     tags:
 *       - deprecated
 */

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const {method} = req;

  switch (method) {
    case "GET":
      try {
        const mmsi = req.query.mmsi;
        const subType = req.query.sub_type;
        let response;
        if (subType) {
          response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}attributes_by_sub_type?sub_type=${subType}`)
            .get()
            .json();
        } else {
          response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}get_mmsi?mmsi=${mmsi}`)
          .get()
          .json();
        }

        return res.status(200).json(response);
      } catch (error) {
        console.error("Error origin: GET /api/form/offshoreVessel | ", error);
        return res.status(500).json(error);
      }

    case "POST":
      try {
        const response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}update_vessel`)
          .post(req.body)
          .json();
        return res.status(200).json(response);
      } catch (error) {
        console.error("Error origin: POST /api/form/offshoreVessel | ", error);
        return res.status(500).json(error);
      }

    case "INSERT_POST":
      try {
        const response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}insert_vessel`)
          .post(req.body)
          .json();

        return res.status(200).json(response);
      } catch (error) {
        console.error("Error origin: POST /api/form/offshoreVessel", error);
        return res.status(500).json(error);
      }
    default:
      res.setHeader("Allow", ["POST", "GET"]);
      return res
        .status(405)
        .send(`Method ${method ?? "Undefined"} Not Allowed`);
  }
}

offshoreVessel.ts :

import type {NextApiRequest, NextApiResponse} from "next";
import wretch from "wretch";
import {env} from "@/env/client.mjs";


/**
 * @swagger
 * /api/form/addLinearReport:
 *   post:
 *     summary: Create a bug report in linear
 *     description: Within the support team.
 *     parameters:
 *        - in: body
 *          name: report
 *          required: true
 *          type: object
 *          description: The report object
 *     produces:
 *       - application/json
 *     responses:
 *       200:
 *         description: Success!
 *       400:
 *         description: No id present as a query parameter.
 *       401:
 *         description: The user does not have an active session or is not authenticated.
 *       405:
 *         description: Method not allowed.
 *       500:
 *         description: Error!
 *     tags:
 *       - deprecated
 */

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const {method} = req;

  switch (method) {
    case "GET":
      try {
        const mmsi = req.query.mmsi;
        const subType = req.query.sub_type;
        let response;
        if (subType) {
          response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}attributes_by_sub_type?sub_type=${subType}`)
            .get()
            .json();
        } else {
          response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}get_mmsi?mmsi=${mmsi}`)
          .get()
          .json();
        }

        return res.status(200).json(response);
      } catch (error) {
        console.error("Error origin: GET /api/form/offshoreVessel | ", error);
        return res.status(500).json(error);
      }

    case "POST":
      try {
        const response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}update_vessel`)
          .post(req.body)
          .json();
        return res.status(200).json(response);
      } catch (error) {
        console.error("Error origin: POST /api/form/offshoreVessel | ", error);
        return res.status(500).json(error);
      }

    case "INSERT_POST":
      try {
        const response = await wretch(`${env.NEXT_PUBLIC_UI_FLASK_URL}insert_vessel`)
          .post(req.body)
          .json();

        return res.status(200).json(response);
      } catch (error) {
        console.error("Error origin: POST /api/form/offshoreVessel", error);
        return res.status(500).json(error);
      }
    default:
      res.setHeader("Allow", ["POST", "GET"]);
      return res
        .status(405)
        .send(`Method ${method ?? "Undefined"} Not Allowed`);
  }
}

offshoreVesselInfo.tsx :

import type { NextPage } from "next";
import {
  BackHomeButton,
  CommandPalletteButton,
  If,
  Input,
  MinimalPage,
  PageHeading,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
} from "ui";
import { BugReportButton, CommandInterface, Navigation } from "@/components";
import type { ChangeEvent } from "react";
import { useEffect, useState } from "react";
import wretch from "wretch";
import { AddOffshoreForm } from "@/components/forms/addOffshoreForm";
import { OffshoreInfoForm } from "@/components/forms/offshoreInfoForm";

interface VesselInfo {
  [key: string]: string | undefined;
}

const OffshoreVesselInfo: NextPage = () => {
  const [vesselInfo, setVesselInfo] = useState<VesselInfo | null>();
  const [mmsi, setMmsi] = useState<number | null>();
  const [vesselSubType, setVesselSubType] = useState<string>("");
  const [offshoreType, setOffshoreType] = useState<string>("");
  const [newOffshoreForm, setNewOffshoreForm] = useState<any>();

  // get vessel info data from the api endpoint
  useEffect(() => {
    const fetchData = async () => {
      if (mmsi) {
        setVesselInfo(null);
        try {
          const response = await wretch(`/api/form/offshoreVessel?mmsi=${mmsi}`)
            .get()
            .res();
          if (response.ok) {
            const data: VesselInfo | null = await response.json();
            setVesselInfo(data);
          } else {
            console.error("Error:", response.statusText);
          }
        } catch (error) {
          console.error("Error:", error);
        }
      } else {
        setVesselInfo(null);
      }
    };
    fetchData();
  }, [mmsi]);

  useEffect(() => {
    const fetchData = async () => {
      if (vesselSubType) {
        try {
          const response = await wretch(
            `/api/form/offshoreVessel?sub_type=${vesselSubType}`,
          )
            .get()
            .res();
          if (response.ok) {
            const data: any = await response.json();
            setNewOffshoreForm(data);
          } else {
            console.error("Error:", response.statusText);
          }
        } catch (error) {
          console.error("Error:", error);
        }
      } else {
        setNewOffshoreForm(null);
      }
    };
    fetchData();
  }, [vesselSubType]);

  function capitalizeFirstLetter(string: string): string {
    return string.replace(/\b\w/g, function (l) {
      return l.toUpperCase();
    });
  }

  useEffect(() => {
    if (!mmsi) {
      setVesselSubType("");
      setOffshoreType("");
    }
  }, [mmsi]);

  function getVesselAfterInsert(mmsi: number) {
    setMmsi(mmsi);
    const fetchData = async () => {
      if (mmsi) {
        try {
          const response = await wretch(`/api/form/offshoreVessel?mmsi=${mmsi}`)
            .get()
            .res();
          if (response.ok) {
            const data: VesselInfo | null = await response.json();
            setVesselInfo(data);
          } else {
            console.error("Error:", response.statusText);
          }
        } catch (error) {
          console.error("Error:", error);
        }
      } else {
        setVesselInfo(null);
      }
    };
    fetchData();
  }

  return (
    <MinimalPage
      pageTitle={"Offshore Vessel Info | Email Interface"}
      pageDescription={"Spot Ship Email Interface | Offshore Vessel Info"}
      commandPrompt
    >
      <div className="flex w-full flex-row justify-between pl-1 pt-1">
        <div>
          <BackHomeButton />
        </div>
        <Navigation />
        <div className="flex flex-row gap-4">
          <BugReportButton />
          <CommandPalletteButton />
          <CommandInterface />
        </div>
      </div>
      <PageHeading text="Offshore Vessel Info" />
      <div className="mt-6 flex w-full flex-col gap-2 p-2 sm:w-1/2">
        <div className={"flex flex-row items-center"}>
          <div
            className={"w-28 text-2xl font-normal text-black dark:text-white"}
          >
            MMSI
          </div>
          <Input
            type={"number"}
            className={"text-md"}
            maxLength={9}
            onChange={(event: ChangeEvent<HTMLInputElement>) => {
              setMmsi(parseFloat(event.target.value) || null);
            }}
          />
        </div>
        <div className={"font-sans text-sm text-black dark:text-white"}>
          International Maritime Mobile Service Identity (MMSI) from 0 to
          9-digit identifier.
        </div>
      </div>
      <If condition={!!(mmsi && vesselInfo?.["message"])}>
        <div className={"mt-2 flex w-full flex-col gap-2 p-2 sm:w-1/2"}>
          <div
            className={"mb-6 text-center text-lg text-black dark:text-white"}
          >
            No information found for MMSI: {mmsi}. Add new offshore vessel
          </div>
          <div>
            <div className={"grid grid-cols-2 gap-4"}>
              <Select
                onValueChange={(type: any) => {
                  setVesselSubType("");
                  if (!offshoreType || offshoreType !== type) {
                    setOffshoreType(type);
                  } else if (offshoreType === type) {
                    setOffshoreType("");
                  }
                }}
              >
                <SelectTrigger>
                  {capitalizeFirstLetter(offshoreType) || "Select vessel type"}
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={"offshore support vessel"}>
                    Offshore Support Vessel
                  </SelectItem>
                  <SelectItem value={"oil exploration and drilling vessel"}>
                    Oil Exploration And Drilling Vessel
                  </SelectItem>
                  <SelectItem value={"offshore production vessel"}>
                    Offshore Production Vessel
                  </SelectItem>
                  <SelectItem value={"offshore construction vessel"}>
                    Offshore Construction Vessel
                  </SelectItem>
                </SelectContent>
              </Select>
              <If condition={offshoreType === "offshore support vessel"}>
                <div>
                  <Select
                    onValueChange={(value: any) => {
                      setVesselSubType(value);
                    }}
                  >
                    <SelectTrigger>
                      {vesselSubType.toUpperCase() || "Select vessel sub type"}
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value={"mpsv"}>MPSV</SelectItem>
                      <SelectItem value={"ahts"}>AHTS</SelectItem>
                      <SelectItem value={"tug"}>Tug</SelectItem>
                      <SelectItem value={"psv"}>PSV</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
              </If>
              <If condition={offshoreType === "offshore production vessel"}>
                <div>
                  <Select
                    onValueChange={(value: any) => {
                      setVesselSubType(value);
                    }}
                  >
                    <SelectTrigger>
                      {vesselSubType.toUpperCase() || "Select vessel sub type"}
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value={"fpso"}>FPSO</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
              </If>
              <If condition={offshoreType === "offshore construction vessel"}>
                <div>
                  <Select
                    onValueChange={(value: any) => {
                      setVesselSubType(value);
                    }}
                  >
                    <SelectTrigger>
                      {vesselSubType.toUpperCase() || "Select vessel sub type"}
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value={"dredger"}>Dredger</SelectItem>
                      <SelectItem value={"clv"}>CLV</SelectItem>
                      <SelectItem value={"wiv"}>WIV</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
              </If>
            </div>
            <If condition={!!newOffshoreForm}>
              <div className={"mt-6"}>
                <AddOffshoreForm
                  fields={newOffshoreForm}
                  vesselType={offshoreType}
                  vesselSubType={vesselSubType}
                  vesselMmsi={mmsi ? mmsi.toString() : ""}
                  returnMmsi={(mmsi: number) => {
                    getVesselAfterInsert(mmsi);
                    setOffshoreType("");
                    setVesselSubType("");
                  }}
                />
              </div>
            </If>
          </div>
        </div>
      </If>
      <If
        condition={
          !!(
            mmsi &&
            vesselInfo &&
            !vesselInfo?.["message"] &&
            typeof vesselInfo === "object"
          )
        }
      >
        <OffshoreInfoForm
          vesselInfo={vesselInfo as VesselInfo}
          vesselMmsi={mmsi as number}
        />
      </If>
    </MinimalPage>
  );
};

export default OffshoreVesselInfo;


and now, I want to create similar structure for regular vessel. We have less in this part :

export const fieldsNameHelper: FieldsNameHelper = {
  beneficialOwner: {
    name: "beneficial owner",
    description: "The beneficial owner of the vessel",
  },
  bollardPull: {
    name: "bollard pull",
    description: "The force exerted by the vessel while tethered",
  },
  bsW: {
    name: "bs&w",
    description: "Basic sediment and water in oil measurement",
  },
  bucketCapacity: {
    name: "bucket capacity",
    description: "Maximum carrying capacity of the bucket",
  },
  buildYear: {
    name: "build year",
    description: "Year the vessel was constructed",
  },
  cableTanks: {
    name: "cable tanks",
    description: "Storage tanks for cables on the vessel",
  },
  callsign: {
    name: "callsign",
    description: "The identifying signal letters or numbers of the vessel",
  },
  class: {
    name: "class",
    description: "Classification society to which the vessel is registered",
  },
  clearDeckArea: {
    name: "clear deck area",
    description: "Total area available for use on the deck",
  },
  commercialOwner: {
    name: "commercial owner",
    description: "The commercial owner of the vessel",
  },
  craneSize: {
    name: "crane size",
    description: "The size and lifting capacity of the crane on the vessel",
  },
  cranes: {
    name: "cranes",
    description: "The number and type of cranes installed on the vessel",
  },
  crudeProcessingCapacity: {
    name: "crude processing capacity",
    description: "Capacity to process crude oil onboard",
  },
  cutterPower: {
    name: "cutter power",
    description: "Power output of the cutting equipment on the vessel",
  },
  deckArea: {
    name: "deck area",
    description: "Total area of the vessel's deck",
  },
  deckLoadCapacity: {
    name: "deck load capacity",
    description: "Maximum load capacity of the vessel’s deck",
  },
  designType: {
    name: "design/type",
    description: "The design and type classification of the vessel",
  },
  destination: {
    name: "destination",
    description: "The intended destination of the vessel",
  },
  dredgeDepth: {
    name: "dredge depth",
    description: "Maximum depth at which the vessel can dredge",
  },
  dredgePumpPower: {
    name: "dredge pump power",
    description: "Power of the dredging pump",
  },
  dynamicPositioningClass: {
    name: "dynamic positioning class",
    description: "Classification of the vessel's dynamic positioning system",
  },
  engineTypePower: {
    name: "engine type & power",
    description: "Type and power output of the vessel’s engines",
  },
  etaIso: {
    name: "eta_iso",
    description: "Estimated time of arrival following ISO standards",
  },
  excavatorPower: {
    name: "excavator power",
    description: "Power output of the excavator on the vessel",
  },
  exportableCrude: {
    name: "exportable crude",
    description: "Volume of crude oil that can be exported by the vessel",
  },
  fleetName: {
    name: "fleet name",
    description: "Name of the fleet the vessel belongs to",
  },
  fleetOperator: {
    name: "fleet operator",
    description: "Operator managing the fleet of vessels",
  },
  fluidCapacity: {
    name: "fluid capacity",
    description: "Total capacity for fluid storage on the vessel",
  },
  fuelCapacity: {
    name: "fuel capacity",
    description: "Fuel storage capacity of the vessel",
  },
  gas: {
    name: "gas",
    description:
      "Capabilities or systems related to gas handling on the vessel",
  },
  grossTonnage: {
    name: "gross tonnage",
    description: "Overall internal volume of the vessel",
  },
  hS: {
    name: "h2s",
    description: "Presence and handling of hydrogen sulfide on the vessel",
  },
  heliDeck: {
    name: "heli-deck",
    description: "Helicopter landing area available on the vessel",
  },
  hopperCapacity: {
    name: "hopper capacity",
    description: "Storage capacity of the hopper on the dredging vessel",
  },
  id: { name: "id", description: "Unique identifier of the vessel" },
  imo: {
    name: "imo",
    description:
      "International Maritime Organization number assigned to the vessel",
  },
  jetPumps: {
    name: "jet pumps",
    description: "Types and capacities of jet pumps on the vessel",
  },
  latitude: {
    name: "latitude",
    description: "Current latitude position of the vessel",
  },
  legs: {
    name: "legs",
    description:
      "Structural supports used in vessels, particularly in offshore applications",
  },
  longitude: {
    name: "longitude",
    description: "Current longitude position of the vessel",
  },
  mainEnginesTypePower: {
    name: "main engines type & power",
    description: "Type and power of the main engines on the vessel",
  },
  maxDredgeWidth: {
    name: "max dredge width",
    description: "Maximum width the vessel can dredge",
  },
  maxFlow: {
    name: "max flow",
    description: "Maximum flow rate achievable by the vessel’s systems",
  },
  maxSpeed: {
    name: "max speed (buckets/min)",
    description:
      "Maximum operational speed of the vessel in buckets per minute",
  },
  mmsi: {
    name: "mmsi",
    description:
      "Maritime Mobile Service Identity used for vessel tracking and safety",
  },
  moonPool: {
    name: "moon pool",
    description:
      "An opening in the bottom or side of the vessel for underwater operations",
  },
  noOfBerths: {
    name: "no of berths",
    description: "Number of sleeping berths available on the vessel",
  },
  oilContentWaterDischarged: {
    name: "oil content water discharged",
    description: "Measure of oil content in discharged water",
  },
  pdfDownloaded: {
    name: "pdf downloaded (y/n)",
    description:
      "Indicates if the vessel’s documentation has been downloaded as PDF",
  },
  pipeDiameter: {
    name: "pipe diameter",
    description: "Diameter of pipes used onboard the vessel",
  },
  positionTime: {
    name: "position_time",
    description: "Timestamp for the vessel's position",
  },
  producedWater: {
    name: "produced water",
    description: "Water produced as a byproduct of the vessel’s operations",
  },
  pumpingDistance: {
    name: "pumping distance",
    description: "Maximum distance over which the vessel can pump materials",
  },
  rov: {
    name: "rov",
    description: "Remotely operated vehicle capabilities of the vessel",
  },
  rvp: {
    name: "rvp",
    description:
      "Reid vapor pressure measurements related to the vessel’s operations",
  },
  slopTanks: {
    name: "slop tanks",
    description:
      "Tanks on the vessel used for temporary storage of oily waste water",
  },
  specialisedCarriageCapability: {
    name: "specialised carriage capability",
    description:
      "Specific carriage capabilities of the vessel for specialized cargoes",
  },
  speedConsumption: {
    name: "speed/consumption",
    description: "The vessel’s speed relative to fuel consumption",
  },
  subType: {
    name: "sub_type",
    description: "Sub-type classification of the vessel",
  },
  totalPowerInstalled: {
    name: "total power installed",
    description: "Total power output of all installed machinery",
  },
  towingCapacity: {
    name: "towing capacity",
    description: "Capacity of the vessel to tow other vessels or structures",
  },
  tugType: {
    name: "tug type",
    description: "Classification of the tug based on its design and use",
  },
  type: {
    name: "type",
    description: "General type classification of the vessel",
  },
  vesselClass: {
    name: "vessel class",
    description: "Class designation for regulatory and operational purposes",
  },
  vesselName: {
    name: "vessel name",
    description: "Official name of the vessel",
  },
  vesselType: {
    name: "vessel type",
    description: "Specific type classification based on structure and function",
  },
  vesselId: {
    name: "vessel_id",
    description: "Unique identification number of the vessel",
  },
  waterInjectionCapacity: {
    name: "water injection capacity",
    description: "Capacity for injecting water into surrounding sea or seabed",
  },
};
and everywhere we have fields or name like this above. Those are things that we will be updating in our db so similar to whats above:

  imo: {
    name: "IMO",
    description: "International Maritime Organization identifier",
  },
  cargo_type: {
    name: "Cargo Type",
    description: "The type of cargo the vessel carries",
  },
  cargo_sub_type: {
    name: "Cargo Sub Type",
    description: "The subtype of cargo the vessel carries",
  },
  mmsi: { name: "MMSI", description: "Maritime Mobile Service Identity" },
  vessel_name: { name: "Vessel Name", description: "The name of the vessel" },
  year_of_build: {
    name: "Year of Build",
    description: "The year the vessel was built",
  },
  flag: { name: "Flag", description: "The flag country code" },
  grt: { name: "GRT", description: "Gross Registered Tonnage" },
  dwt: { name: "DWT", description: "Dead Weight Tonnage" },
  overall_length: {
    name: "Overall Length",
    description: "The overall length of the vessel",
  },
  beam: { name: "Beam", description: "The beam of the vessel" },
  maximum_draft: {
    name: "Maximum Draft",
    description:
      "The deepest point of the vessel below the waterline when fully loaded",
  },
}; 
+ also 
downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter