import { ButtonContent, DestructiveButton, Form, FormControl, FormField, FormItem, FormLabel, FormMessage, Icon, Input, 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, { useState } from "react"; import { toast } from "sonner"; import wretch from "wretch"; import { useGetVesselFromIMO } from "@/hooks"; const formSchema = z.object({ imo: z.string().max(7), cargo_type: z.string().optional(), cargo_sub_type: z.string().optional(), mmsi: z.string().max(9).optional(), vessel_name: z.string().optional(), year_of_build: z.string().optional(), flag: z.string().optional(), grt: z.string().optional(), dwt: z.string().optional(), overall_length: z.string().optional(), beam: z.string().optional(), }); const fieldsNameHelper = { 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" }, }; export function VesselInfoForm() { const [imoChecked, setImoChecked] = useState(false); const [updateError, setUpdateError] = useState(null); const form = useForm({ resolver: zodResolver(formSchema), defaultValues: {}, }); const imoValue = form.watch("imo"); const { data: vesselData, isError, isLoading, } = useGetVesselFromIMO(imoValue); async function onSubmit(values) { setUpdateError(null); try { if (!imoChecked) { setImoChecked(true); if (vesselData?.length) { toast.error("Vessel already exists"); } } else { const response = await wretch("/api/form/insertVessel") .post(values) .res(); if (response.ok) { toast.success("Success!", { description: "Vessel details added.", }); form.reset(); setImoChecked(false); } else { throw new Error("Error submitting form"); } } } catch (error) { setUpdateError(error); } } return ( <div className={"mt-4"}> <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> <FormField control={form.control} name="imo" render={({ field }) => ( <FormItem className={"flex flex-row items-center"}> <FormLabel className={"w-64 text-lg font-light"}> {fieldsNameHelper.imo.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.imo.description}</p> </TooltipContent> </Tooltip> </TooltipProvider> </div> <FormControl className={"w-full"}> <Input {...field} className={"text-md font-light"} type="text" value={field.value ?? ""} /> </FormControl> <FormMessage /> </FormItem> )} /> {imoChecked && vesselData && vesselData.length > 0 ? ( <div className="vessel-info"> <h2 className="text-lg font-semibold">Vessel Information</h2> <ul> {Object.keys(fieldsNameHelper).map( (key) => vesselData[0][key] && ( <li key={key}> <strong>{fieldsNameHelper[key].name}:</strong>{" "} {vesselData[0][key]} </li> ), )} </ul> </div> ) : null} {imoChecked && (!vesselData || vesselData.length === 0) && Object.keys(formSchema.shape).map( (key, index) => key !== "imo" && ( <FormField key={key + index} control={form.control} name={key} render={({ field }) => ( <FormItem className={"flex flex-row items-center"}> <FormLabel className={"w-64 text-lg font-light"}> {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="text" value={field.value ?? ""} /> </FormControl> <FormMessage /> </FormItem> )} /> ), )} <div className="flex flex-row justify-end"> <DestructiveButton type="submit" className="mt-4"> <ButtonContent> {imoChecked ? "Add Vessel" : "Check IMO"} </ButtonContent> </DestructiveButton> </div> <Toaster /> </form> </Form> </div> ); }