The question fore CHAT GPT tomorrow (15.06.2024 rok)
Fri Jun 14 2024 23:32:00 GMT+0000 (Coordinated Universal Time)
Saved by @rafal_rydz
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
Comments