Spaces:
Sleeping
Sleeping
| import { useEffect, useMemo, useState } from "react"; | |
| import { useNavigate } from "react-router-dom"; | |
| import { useAuth } from "@/contexts/AuthContext"; | |
| import { Input } from "@/components/ui/input"; | |
| import { Label } from "@/components/ui/label"; | |
| import { StepWizard, StepConfig } from "@/components/forms/StepWizard"; | |
| import { | |
| createFarmApplicationForUser, | |
| NewFarmApplicationInput, | |
| } from "@/lib/farmLocal"; | |
| import { Alert, AlertDescription } from "@/components/ui/alert"; | |
| import { Card } from "@/components/ui/card"; | |
| const STORAGE_KEY = "farm_new_application_draft"; | |
| const emptyForm: NewFarmApplicationInput = { | |
| farmName: "", | |
| farmerName: "", | |
| waterArea: "", | |
| species: "", | |
| state: "", | |
| district: "", | |
| address: "", | |
| enrollmentId: "", | |
| email: "", | |
| phone: "", | |
| }; | |
| export default function NewFarmApplication() { | |
| const { user } = useAuth(); | |
| const navigate = useNavigate(); | |
| const [form, setForm] = useState<NewFarmApplicationInput>(emptyForm); | |
| const [step, setStep] = useState(0); | |
| const [submitting, setSubmitting] = useState(false); | |
| const [error, setError] = useState<string | null>(null); | |
| useEffect(() => { | |
| try { | |
| const raw = localStorage.getItem(STORAGE_KEY); | |
| if (raw) { | |
| const parsed = JSON.parse(raw); | |
| setForm({ ...emptyForm, ...parsed }); | |
| } | |
| } catch { | |
| // ignore | |
| } | |
| }, []); | |
| useEffect(() => { | |
| try { | |
| localStorage.setItem(STORAGE_KEY, JSON.stringify(form)); | |
| } catch { | |
| // ignore | |
| } | |
| }, [form]); | |
| const updateField = (field: keyof NewFarmApplicationInput, value: string) => { | |
| setForm((prev) => ({ ...prev, [field]: value })); | |
| }; | |
| const steps: StepConfig[] = useMemo( | |
| () => [ | |
| { | |
| id: "entity", | |
| title: "Farm details", | |
| description: "Basic farm information.", | |
| render: () => ( | |
| <div className="grid gap-4 md:grid-cols-2"> | |
| <div className="space-y-2"> | |
| <Label htmlFor="farmName">Farm name *</Label> | |
| <Input | |
| id="farmName" | |
| value={form.farmName} | |
| onChange={(e) => updateField("farmName", e.target.value)} | |
| placeholder="e.g. Vijay Aqua Farm" | |
| required | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="farmerName">Farmer name *</Label> | |
| <Input | |
| id="farmerName" | |
| value={form.farmerName} | |
| onChange={(e) => updateField("farmerName", e.target.value)} | |
| placeholder="e.g. Vijay Prasad" | |
| required | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="state">State *</Label> | |
| <Input | |
| id="state" | |
| value={form.state} | |
| onChange={(e) => updateField("state", e.target.value)} | |
| placeholder="e.g. Kerala" | |
| required | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="district">District *</Label> | |
| <Input | |
| id="district" | |
| value={form.district} | |
| onChange={(e) => updateField("district", e.target.value)} | |
| placeholder="e.g. Alappuzha" | |
| required | |
| /> | |
| </div> | |
| <div className="md:col-span-2 space-y-2"> | |
| <Label htmlFor="address">Address *</Label> | |
| <Input | |
| id="address" | |
| value={form.address} | |
| onChange={(e) => updateField("address", e.target.value)} | |
| placeholder="Village / Post / Taluk" | |
| required | |
| /> | |
| </div> | |
| </div> | |
| ), | |
| }, | |
| { | |
| id: "specs", | |
| title: "Farm specifications", | |
| description: "Key technical details.", | |
| render: () => ( | |
| <div className="grid gap-4 md:grid-cols-2"> | |
| <div className="space-y-2"> | |
| <Label htmlFor="waterArea">Water area *</Label> | |
| <Input | |
| id="waterArea" | |
| value={form.waterArea} | |
| onChange={(e) => updateField("waterArea", e.target.value)} | |
| placeholder="e.g. 5 Hectares" | |
| required | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="species">Species *</Label> | |
| <Input | |
| id="species" | |
| value={form.species} | |
| onChange={(e) => updateField("species", e.target.value)} | |
| placeholder="e.g. Litopenaeus vannamei" | |
| required | |
| /> | |
| </div> | |
| </div> | |
| ), | |
| }, | |
| { | |
| id: "contact", | |
| title: "Contact & enrollment", | |
| description: "Primary contact and enrollment details.", | |
| render: () => ( | |
| <div className="grid gap-4 md:grid-cols-2"> | |
| <div className="space-y-2"> | |
| <Label htmlFor="email">Email *</Label> | |
| <Input | |
| id="email" | |
| type="email" | |
| value={form.email} | |
| onChange={(e) => updateField("email", e.target.value)} | |
| placeholder="e.g. vijay@farms.com" | |
| required | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="phone">Phone *</Label> | |
| <Input | |
| id="phone" | |
| value={form.phone} | |
| onChange={(e) => updateField("phone", e.target.value)} | |
| placeholder="e.g. 9876543210" | |
| required | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="enrollmentId">Enrollment ID *</Label> | |
| <Input | |
| id="enrollmentId" | |
| value={form.enrollmentId} | |
| onChange={(e) => updateField("enrollmentId", e.target.value)} | |
| placeholder="e.g. ENR/F/KL/2025/XXXX" | |
| required | |
| /> | |
| </div> | |
| </div> | |
| ), | |
| }, | |
| ], | |
| [form], | |
| ); | |
| if (!user) { | |
| return ( | |
| <Card className="p-4"> | |
| <Alert> | |
| <AlertDescription> | |
| You must be logged in to create a new application. | |
| </AlertDescription> | |
| </Alert> | |
| </Card> | |
| ); | |
| } | |
| const currentStep = steps[step]; | |
| const canGoNext = (() => { | |
| if (currentStep.id === "entity") { | |
| return ( | |
| !!form.farmName && | |
| !!form.farmerName && | |
| !!form.state && | |
| !!form.district && | |
| !!form.address | |
| ); | |
| } | |
| if (currentStep.id === "specs") { | |
| return !!form.waterArea && !!form.species; | |
| } | |
| if (currentStep.id === "contact") { | |
| return !!form.email && !!form.phone && !!form.enrollmentId; | |
| } | |
| return true; | |
| })(); | |
| const handleNext = () => { | |
| setError(null); | |
| if (step < steps.length - 1 && canGoNext) { | |
| setStep((s) => s + 1); | |
| } | |
| }; | |
| const handleBack = () => { | |
| setError(null); | |
| if (step > 0) { | |
| setStep((s) => s - 1); | |
| } | |
| }; | |
| const handleSubmit = async () => { | |
| setError(null); | |
| setSubmitting(true); | |
| try { | |
| const app = createFarmApplicationForUser(user, form); | |
| localStorage.removeItem(STORAGE_KEY); | |
| navigate(`/farm/applications/${app.id}`); | |
| } catch (e) { | |
| setError("Failed to create application in local storage."); | |
| } finally { | |
| setSubmitting(false); | |
| } | |
| }; | |
| return ( | |
| <div className="space-y-4 animate-fade-in"> | |
| {error && ( | |
| <Alert variant="destructive"> | |
| <AlertDescription>{error}</AlertDescription> | |
| </Alert> | |
| )} | |
| <StepWizard | |
| steps={steps} | |
| currentIndex={step} | |
| onNext={handleNext} | |
| onBack={handleBack} | |
| onSubmit={handleSubmit} | |
| isSubmitting={submitting} | |
| canGoNext={canGoNext} | |
| /> | |
| </div> | |
| ); | |
| } | |