"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { motion, AnimatePresence } from "framer-motion"; import { Search, Plus, Filter, SlidersHorizontal, Leaf, Calendar, AlertTriangle, Loader2 } from "lucide-react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"; import { Separator } from "@/components/ui/separator"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuLabel, } from "@/components/ui/dropdown-menu"; import { Badge } from "@/components/ui/badge"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { FarmCard } from "./farm-card"; import { AddFarmForm } from "./add-farm-form"; import { EditFarmForm } from "./edit-farm-form"; import type { Farm } from "@/types"; import { fetchFarms, createFarm, updateFarm, deleteFarm } from "@/api/farm"; import { toast } from "sonner"; import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; export default function FarmSetupPage() { const router = useRouter(); const queryClient = useQueryClient(); const [searchQuery, setSearchQuery] = useState(""); const [activeFilter, setActiveFilter] = useState("all"); const [sortOrder, setSortOrder] = useState<"newest" | "oldest" | "alphabetical">("newest"); const [isAddDialogOpen, setIsAddDialogOpen] = useState(false); const [isEditDialogOpen, setIsEditDialogOpen] = useState(false); // State for edit dialog const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); // State for delete dialog const [selectedFarm, setSelectedFarm] = useState(null); // Farm to edit/delete // --- Fetch Farms --- const { data: farms, isLoading, isError, error, } = useQuery({ queryKey: ["farms"], queryFn: fetchFarms, staleTime: 60 * 1000, }); // --- Create Farm Mutation --- const createMutation = useMutation({ mutationFn: (data: Partial>) => createFarm(data), onSuccess: (newFarm) => { queryClient.invalidateQueries({ queryKey: ["farms"] }); setIsAddDialogOpen(false); toast.success(`Farm "${newFarm.name}" created successfully!`); }, onError: (error) => { toast.error(`Failed to create farm: ${(error as Error).message}`); }, }); // --- Update Farm Mutation --- const updateMutation = useMutation({ mutationFn: (data: { farmId: string; payload: Partial>; }) => updateFarm(data.farmId, data.payload), onSuccess: (updatedFarm) => { queryClient.invalidateQueries({ queryKey: ["farms"] }); setIsEditDialogOpen(false); setSelectedFarm(null); toast.success(`Farm "${updatedFarm.name}" updated successfully!`); }, onError: (error) => { toast.error(`Failed to update farm: ${(error as Error).message}`); }, }); // --- Delete Farm Mutation --- const deleteMutation = useMutation({ mutationFn: (farmId: string) => deleteFarm(farmId), onSuccess: (_, farmId) => { // Second arg is the variable passed to mutate queryClient.invalidateQueries({ queryKey: ["farms"] }); // Optionally remove specific farm query if cached elsewhere: queryClient.removeQueries({ queryKey: ["farm", farmId] }); setIsDeleteDialogOpen(false); setSelectedFarm(null); toast.success(`Farm deleted successfully.`); }, onError: (error) => { toast.error(`Failed to delete farm: ${(error as Error).message}`); setIsDeleteDialogOpen(false); // Close dialog even on error }, }); // export interface Farm { // CreatedAt: string; // FarmType: string; // Lat: number; // Lon: number; // Name: string; // OwnerID: string; // TotalSize: string; // UUID: string; // UpdatedAt: string; // } const handleAddFarmSubmit = async (data: Partial) => { await createMutation.mutateAsync(data); }; const handleEditFarmSubmit = async ( data: Partial> ) => { if (!selectedFarm) return; await updateMutation.mutateAsync({ farmId: selectedFarm.uuid, payload: data }); }; const openEditDialog = (farm: Farm, e: React.MouseEvent) => { e.stopPropagation(); // Prevent card click setSelectedFarm(farm); setIsEditDialogOpen(true); }; const openDeleteDialog = (farm: Farm, e: React.MouseEvent) => { e.stopPropagation(); // Prevent card click setSelectedFarm(farm); setIsDeleteDialogOpen(true); }; const confirmDelete = () => { if (!selectedFarm) return; deleteMutation.mutate(selectedFarm.uuid); }; // --- Filtering and Sorting Logic --- const filteredAndSortedFarms = (farms || []) .filter( (farm) => (activeFilter === "all" || farm.farmType === activeFilter) && // Use camelCase farmType (farm.name.toLowerCase().includes(searchQuery.toLowerCase()) || // Use camelCase name // farm.location is no longer a single string, use lat/lon if needed for search farm.farmType.toLowerCase().includes(searchQuery.toLowerCase())) // Use camelCase farmType ) .sort((a, b) => { if (sortOrder === "newest") { return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); // Use camelCase createdAt } else if (sortOrder === "oldest") { return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(); // Use camelCase createdAt } else { return a.name.localeCompare(b.name); // Use camelCase name } }); // Get distinct farm types. const farmTypes = ["all", ...new Set((farms || []).map((farm) => farm.farmType))]; // Use camelCase farmType return (
{/* Header */}

Your Farms

Manage and monitor all your agricultural properties

setSearchQuery(e.target.value)} />
{/* Filtering and sorting controls */}
{farmTypes.map((type) => ( setActiveFilter(type)}> {type === "all" ? "All Farms" : type} ))}
{/* DropdownMenu remains the same, Check icon was missing */} Sort by setSortOrder("newest")}> Newest first {sortOrder === "newest" && } setSortOrder("oldest")}> Oldest first {sortOrder === "oldest" && } setSortOrder("alphabetical")}> Alphabetical {sortOrder === "alphabetical" && }
{/* Error state */} {isError && ( Error Loading Farms {(error as Error)?.message} )} {/* Loading state */} {isLoading && (
{[...Array(4)].map( ( _, i // Render skeleton cards ) => ( ) )}
)} {/* Empty state */} {!isLoading && !isError && filteredAndSortedFarms.length === 0 && ( // ... (Empty state remains the same) ...

No farms found

{searchQuery || activeFilter !== "all" ? (

No farms match your current filters. Try adjusting your search or filters.

) : (

You haven't added any farms yet. Get started by adding your first farm.

)}
)} {/* Grid of farm cards */} {!isLoading && !isError && filteredAndSortedFarms.length > 0 && (
{/* Add Farm Card */} setIsAddDialogOpen(true)} /> {/* Existing Farm Cards */} {filteredAndSortedFarms.map((farm, index) => ( router.push(`/farms/${farm.uuid}`)} onEditClick={(e) => openEditDialog(farm, e)} // Pass handler onDeleteClick={(e) => openDeleteDialog(farm, e)} // Pass handler /> ))}
)}
{/* Add Farm Dialog */} Add New Farm Fill out the details below to add a new farm to your account. setIsAddDialogOpen(false)} /> {/* Edit Farm Dialog */} Edit Farm: {selectedFarm?.name} Update the details for this farm. {/* Create or use an EditFarmForm component */} {selectedFarm && ( setIsEditDialogOpen(false)} isSubmitting={updateMutation.isPending} // Pass submitting state /> )} {/* Delete Confirmation Dialog */} Are you absolutely sure? This action cannot be undone. This will permanently delete the farm "{selectedFarm?.name}" and all associated crops and data. Cancel {deleteMutation.isPending && } Delete Farm
); } /** * A helper component for the Check icon. */ function Check({ className }: { className?: string }) { return ( ); }