"use client"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import * as z from "zod"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { useState, useCallback } from "react"; import { Loader2 } from "lucide-react"; import type { Farm } from "@/types"; import GoogleMapWithDrawing, { type ShapeData } from "@/components/google-map-with-drawing"; // =================================================================== // Schema Definition: Validates form inputs using Zod // See: https://zod.dev // =================================================================== const farmFormSchema = z.object({ name: z.string().min(2, "Farm name must be at least 2 characters"), latitude: z .number({ invalid_type_error: "Latitude must be a number" }) .min(-90, "Invalid latitude") .max(90, "Invalid latitude") .refine((val) => val !== 0, { message: "Please select a location on the map." }), longitude: z .number({ invalid_type_error: "Longitude must be a number" }) .min(-180, "Invalid longitude") .max(180, "Invalid longitude") .refine((val) => val !== 0, { message: "Please select a location on the map." }), type: z.string().min(1, "Please select a farm type"), area: z.string().optional(), }); // =================================================================== // Component Props Declaration // =================================================================== export interface AddFarmFormProps { onSubmit: (data: Partial) => Promise; onCancel: () => void; } // =================================================================== // Component: AddFarmForm // - Manages the creation of new farm records. // - Uses React Hook Form with Zod for form validation. // - Includes a map component for coordinate selection. // =================================================================== export function AddFarmForm({ onSubmit, onCancel }: AddFarmFormProps) { // --------------------------------------------------------------- // State and Form Setup // --------------------------------------------------------------- const [isSubmitting, setIsSubmitting] = useState(false); const form = useForm>({ resolver: zodResolver(farmFormSchema), defaultValues: { name: "", latitude: 0, // Defaults handled by validation (marker must be selected) longitude: 0, type: "", area: "", }, }); // --------------------------------------------------------------- // Form Submission Handler // - Converts form data to the expected Farm shape. // --------------------------------------------------------------- const handleSubmit = async (values: z.infer) => { try { setIsSubmitting(true); const farmData: Partial = { Name: values.name, Lat: values.latitude, Lon: values.longitude, FarmType: values.type, TotalSize: values.area, }; await onSubmit(farmData); form.reset(); } catch (error) { console.error("Error submitting form:", error); } finally { setIsSubmitting(false); } }; // --------------------------------------------------------------- // Map-to-Form Coordination: Update coordinates from the map // - Uses useCallback to preserve reference and optimize re-renders. // --------------------------------------------------------------- const handleShapeDrawn = useCallback( (data: ShapeData) => { // Log incoming shape data for debugging console.log("Shape drawn in form:", data); // Only update the form if a single marker (i.e. point) is used if (data.type === "marker") { const { lat, lng } = data.position; form.setValue("latitude", lat, { shouldValidate: true }); form.setValue("longitude", lng, { shouldValidate: true }); console.log(`Set form lat: ${lat}, lng: ${lng}`); } else { // Note: Only markers update coordinates. Other shapes could be handled later. console.log(`Received shape type '${data.type}', but only 'marker' updates the form coordinates.`); } }, [form] ); // =================================================================== // Render: Split into two main sections - Form and Map // =================================================================== return (
{/* ============================== Start of Form Section ============================== */}
{/* Farm Name Field */} ( Farm Name This is your farm's display name. )} /> {/* Coordinate Fields (Latitude & Longitude) */}
( Latitude )} /> ( Longitude )} />
{/* Farm Type Selection */} ( Farm Type )} /> {/* Total Area Field */} ( Total Area (optional) The total size of your farm (e.g., "15 rai", "10 hectares"). )} /> {/* Submit and Cancel Buttons */}
{/* ============================== End of Form Section ============================== */} {/* ============================== Start of Map Section - Renders an interactive map for coordinate selection. ============================== */}
Farm Location (Draw marker on map)
Select the marker tool above the map and click a location to set the latitude and longitude for your farm. Only markers will update the coordinates.
{/* ============================== End of Map Section ============================== */}
); }