ui: modify new crop dialog

This commit is contained in:
Sosokker 2025-02-14 04:16:09 +07:00
parent 215c178249
commit 20c1efa325
4 changed files with 182 additions and 38 deletions

View File

@ -4,9 +4,10 @@ import { Crop } from "@/types";
interface CropCardProps { interface CropCardProps {
crop: Crop; crop: Crop;
onClick?: () => void;
} }
export function CropCard({ crop }: CropCardProps) { export function CropCard({ crop, onClick }: CropCardProps) {
const statusColors = { const statusColors = {
growing: "text-green-500", growing: "text-green-500",
harvested: "text-yellow-500", harvested: "text-yellow-500",
@ -14,8 +15,10 @@ export function CropCard({ crop }: CropCardProps) {
}; };
return ( return (
<Card className="w-full bg-muted/50 hover:bg-muted/80 transition-all cursor-pointer group hover:shadow-lg"> <Card
<CardHeader className="p-4 pb-2"> onClick={onClick}
className="w-full bg-muted/50 hover:bg-muted/80 transition-all cursor-pointer group hover:shadow-lg">
<CardHeader className="p-4 pb-0">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center"> <div className="h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center">
<Sprout className="h-4 w-4 text-primary" /> <Sprout className="h-4 w-4 text-primary" />
@ -24,10 +27,10 @@ export function CropCard({ crop }: CropCardProps) {
</div> </div>
</CardHeader> </CardHeader>
<CardContent className="p-4"> <CardContent className="p-4">
<div className="space-y-2"> <div className="space-y-4">
<h3 className="text-lg font-medium truncate">{crop.name}</h3> <h3 className="text-xl font-medium truncate">{crop.name}</h3>
<div className="flex items-center gap-1 text-sm text-muted-foreground"> <div className="flex items-center gap-1 text-sm text-muted-foreground">
<Calendar className="h-3 w-3" /> <Calendar className="h-4 w-4" />
<p>Planted: {crop.plantedDate.toLocaleDateString()}</p> <p>Planted: {crop.plantedDate.toLocaleDateString()}</p>
</div> </div>
</div> </div>

View File

@ -0,0 +1,131 @@
"use client";
import { useState } from "react";
import { Dialog, DialogContent } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Check, MapPin } from "lucide-react";
import { cn } from "@/lib/utils";
import type { Crop } from "@/types";
interface Plant {
id: string;
name: string;
image: string;
growthTime: string;
}
const plants: Plant[] = [
{
id: "durian",
name: "Durian",
image: "/placeholder.svg?height=80&width=80",
growthTime: "4-5 months",
},
{
id: "mango",
name: "Mango",
image: "/placeholder.svg?height=80&width=80",
growthTime: "3-4 months",
},
{
id: "coconut",
name: "Coconut",
image: "/placeholder.svg?height=80&width=80",
growthTime: "5-6 months",
},
];
interface CropDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onSubmit: (data: Partial<Crop>) => Promise<void>;
}
export function CropDialog({ open, onOpenChange, onSubmit }: CropDialogProps) {
const [selectedPlant, setSelectedPlant] = useState<string | null>(null);
const [location, setLocation] = useState({ lat: 13.7563, lng: 100.5018 }); // Bangkok coordinates
const handleSubmit = async () => {
if (!selectedPlant) return;
await onSubmit({
name: plants.find((p) => p.id === selectedPlant)?.name || "",
plantedDate: new Date(),
status: "planned",
});
setSelectedPlant(null);
onOpenChange(false);
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[900px] p-0">
<div className="grid md:grid-cols-2 h-[600px]">
{/* Left side - Plant Selection */}
<div className="p-6 overflow-y-auto border-r">
<h2 className="text-lg font-semibold mb-4">Select Plant to Grow</h2>
<div className="space-y-4">
{plants.map((plant) => (
<Card
key={plant.id}
className={cn(
"p-4 cursor-pointer hover:bg-muted/50 transition-colors",
selectedPlant === plant.id && "border-primary bg-primary/5"
)}
onClick={() => setSelectedPlant(plant.id)}>
<div className="flex items-center gap-4">
<img
src={plant.image || "/placeholder.svg"}
alt={plant.name}
className="w-20 h-20 rounded-lg object-cover"
/>
<div className="flex-1">
<div className="flex items-center justify-between">
<h3 className="font-medium">{plant.name}</h3>
{selectedPlant === plant.id && <Check className="h-4 w-4 text-primary" />}
</div>
<p className="text-sm text-muted-foreground">Growth time: {plant.growthTime}</p>
</div>
</div>
</Card>
))}
</div>
</div>
{/* Right side - Map */}
<div className="relative">
<div className="absolute inset-0 bg-muted/10">
{/* Placeholder map - Replace with your map component */}
<div className="h-full w-full bg-muted/20 flex items-center justify-center">
<div className="text-center space-y-2">
<MapPin className="h-8 w-8 mx-auto text-muted-foreground" />
<p className="text-sm text-muted-foreground">
Map placeholder
<br />
Lat: {location.lat.toFixed(4)}
<br />
Lng: {location.lng.toFixed(4)}
</p>
</div>
</div>
</div>
</div>
{/* Footer */}
<div className="absolute bottom-0 left-0 right-0 p-4 bg-background border-t">
<div className="flex justify-end gap-2">
<Button variant="outline" onClick={() => onOpenChange(false)}>
Cancel
</Button>
<Button onClick={handleSubmit} disabled={!selectedPlant}>
Plant Crop
</Button>
</div>
</div>
</div>
</DialogContent>
</Dialog>
);
}

View File

@ -6,29 +6,28 @@ import { ArrowLeft, MapPin, Plus, Sprout } from "lucide-react";
import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"; import { CropDialog } from "./crop-dialog";
import { AddCropForm } from "./add-crop-form";
import { CropCard } from "./crop-card"; import { CropCard } from "./crop-card";
import { Farm, Crop } from "@/types"; import { Farm, Crop } from "@/types";
import React from "react"; import React from "react";
const crops: Crop[] = [ const crops: Crop[] = [
{ {
id: "crop1", id: "1",
farmId: "1", farmId: "1",
name: "Monthong Durian", name: "Monthong Durian",
plantedDate: new Date("2023-03-15"), plantedDate: new Date("2023-03-15"),
status: "growing", status: "growing",
}, },
{ {
id: "crop2", id: "2",
farmId: "1", farmId: "1",
name: "Chanee Durian", name: "Chanee Durian",
plantedDate: new Date("2023-02-20"), plantedDate: new Date("2023-02-20"),
status: "planned", status: "planned",
}, },
{ {
id: "crop3", id: "3",
farmId: "2", farmId: "2",
name: "Kradum Durian", name: "Kradum Durian",
plantedDate: new Date("2022-11-05"), plantedDate: new Date("2022-11-05"),
@ -76,6 +75,7 @@ export default function FarmDetailPage({ params }: { params: Promise<{ farmId: s
status: data.status!, status: data.status!,
}; };
setCrops((prevCrops) => [...prevCrops, newCrop]); setCrops((prevCrops) => [...prevCrops, newCrop]);
// When the crop gets added, close the dialog
setIsDialogOpen(false); setIsDialogOpen(false);
}; };
@ -121,33 +121,34 @@ export default function FarmDetailPage({ params }: { params: Promise<{ farmId: s
<h2 className="text-xl font-bold mb-4">Crops</h2> <h2 className="text-xl font-bold mb-4">Crops</h2>
<Separator className="my-4" /> <Separator className="my-4" />
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}> {/* Clickable "Add Crop" Card */}
<Card <Card
className="w-full bg-muted/50 hover:bg-muted/80 transition-all cursor-pointer group hover:shadow-lg" className="w-full bg-muted/50 hover:bg-muted/80 transition-all cursor-pointer group hover:shadow-lg"
onClick={() => setIsDialogOpen(true)}> onClick={() => setIsDialogOpen(true)}>
<CardContent className="p-6"> <CardContent className="p-6">
<div className="flex flex-col gap-6"> <div className="flex flex-col gap-6">
<div className="h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center group-hover:bg-primary/20 transition-colors"> <div className="h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center group-hover:bg-primary/20 transition-colors">
<Plus className="h-5 w-5 text-primary" /> <Plus className="h-5 w-5 text-primary" />
</div>
<div className="space-y-1">
<h3 className="text-xl font-medium">Add Crop</h3>
<p className="text-sm text-muted-foreground">Plant a new crop</p>
</div>
</div> </div>
</CardContent> <div className="space-y-1">
</Card> <h3 className="text-xl font-medium">Add Crop</h3>
<DialogContent className="sm:max-w-[425px]"> <p className="text-sm text-muted-foreground">Plant a new crop</p>
<DialogHeader> </div>
<DialogTitle>Add New Crop</DialogTitle> </div>
<DialogDescription>Fill out the form to add a new crop to your farm.</DialogDescription> </CardContent>
</DialogHeader> </Card>
<AddCropForm onSubmit={handleAddCrop} onCancel={() => setIsDialogOpen(false)} />
</DialogContent> {/* New Crop Dialog */}
</Dialog> <CropDialog open={isDialogOpen} onOpenChange={setIsDialogOpen} onSubmit={handleAddCrop} />
{crops.map((crop) => ( {crops.map((crop) => (
<CropCard key={crop.id} crop={crop} /> <CropCard
key={crop.id}
crop={crop}
onClick={() => {
router.push(`/farms/${crop.farmId}/crops/${crop.id}`);
}}
/>
))} ))}
</div> </div>
</div> </div>

View File

@ -4,12 +4,14 @@ import { useState } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Search } from "lucide-react"; import { Link, Search } from "lucide-react";
import { FarmCard } from "./farm-card"; import { FarmCard } from "./farm-card";
import { AddFarmForm } from "./add-farm-form"; import { AddFarmForm } from "./add-farm-form";
import { useRouter } from "next/navigation";
import type { Farm } from "@/types"; import type { Farm } from "@/types";
export default function FarmSetupPage() { export default function FarmSetupPage() {
const router = useRouter();
const [isDialogOpen, setIsDialogOpen] = useState(false); const [isDialogOpen, setIsDialogOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [farms, setFarms] = useState<Farm[]>([ const [farms, setFarms] = useState<Farm[]>([
@ -17,7 +19,7 @@ export default function FarmSetupPage() {
id: "1", id: "1",
name: "Green Valley Farm", name: "Green Valley Farm",
location: "Bangkok", location: "Bangkok",
type: "durian", type: "Durian",
createdAt: new Date(), createdAt: new Date(),
}, },
]); ]);
@ -70,7 +72,14 @@ export default function FarmSetupPage() {
</Dialog> </Dialog>
{filteredFarms.map((farm) => ( {filteredFarms.map((farm) => (
<FarmCard key={farm.id} variant="farm" farm={farm} /> <FarmCard
key={farm.id}
variant="farm"
farm={farm}
onClick={() => {
router.push(`/farms/${farm.id}`);
}}
/>
))} ))}
</div> </div>
</div> </div>