mirror of
https://github.com/ForFarmTeam/ForFarm.git
synced 2025-12-19 22:14:08 +01:00
ui: modify new crop dialog
This commit is contained in:
parent
215c178249
commit
20c1efa325
@ -4,9 +4,10 @@ import { Crop } from "@/types";
|
||||
|
||||
interface CropCardProps {
|
||||
crop: Crop;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
export function CropCard({ crop }: CropCardProps) {
|
||||
export function CropCard({ crop, onClick }: CropCardProps) {
|
||||
const statusColors = {
|
||||
growing: "text-green-500",
|
||||
harvested: "text-yellow-500",
|
||||
@ -14,8 +15,10 @@ export function CropCard({ crop }: CropCardProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="w-full bg-muted/50 hover:bg-muted/80 transition-all cursor-pointer group hover:shadow-lg">
|
||||
<CardHeader className="p-4 pb-2">
|
||||
<Card
|
||||
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="h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center">
|
||||
<Sprout className="h-4 w-4 text-primary" />
|
||||
@ -24,10 +27,10 @@ export function CropCard({ crop }: CropCardProps) {
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-4">
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-lg font-medium truncate">{crop.name}</h3>
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-xl font-medium truncate">{crop.name}</h3>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
131
frontend/app/(sidebar)/farms/[farmId]/crop-dialog.tsx
Normal file
131
frontend/app/(sidebar)/farms/[farmId]/crop-dialog.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@ -6,29 +6,28 @@ import { ArrowLeft, MapPin, Plus, Sprout } from "lucide-react";
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
|
||||
import { AddCropForm } from "./add-crop-form";
|
||||
import { CropDialog } from "./crop-dialog";
|
||||
import { CropCard } from "./crop-card";
|
||||
import { Farm, Crop } from "@/types";
|
||||
import React from "react";
|
||||
|
||||
const crops: Crop[] = [
|
||||
{
|
||||
id: "crop1",
|
||||
id: "1",
|
||||
farmId: "1",
|
||||
name: "Monthong Durian",
|
||||
plantedDate: new Date("2023-03-15"),
|
||||
status: "growing",
|
||||
},
|
||||
{
|
||||
id: "crop2",
|
||||
id: "2",
|
||||
farmId: "1",
|
||||
name: "Chanee Durian",
|
||||
plantedDate: new Date("2023-02-20"),
|
||||
status: "planned",
|
||||
},
|
||||
{
|
||||
id: "crop3",
|
||||
id: "3",
|
||||
farmId: "2",
|
||||
name: "Kradum Durian",
|
||||
plantedDate: new Date("2022-11-05"),
|
||||
@ -76,6 +75,7 @@ export default function FarmDetailPage({ params }: { params: Promise<{ farmId: s
|
||||
status: data.status!,
|
||||
};
|
||||
setCrops((prevCrops) => [...prevCrops, newCrop]);
|
||||
// When the crop gets added, close the dialog
|
||||
setIsDialogOpen(false);
|
||||
};
|
||||
|
||||
@ -121,7 +121,7 @@ export default function FarmDetailPage({ params }: { params: Promise<{ farmId: s
|
||||
<h2 className="text-xl font-bold mb-4">Crops</h2>
|
||||
<Separator className="my-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
|
||||
className="w-full bg-muted/50 hover:bg-muted/80 transition-all cursor-pointer group hover:shadow-lg"
|
||||
onClick={() => setIsDialogOpen(true)}>
|
||||
@ -137,17 +137,18 @@ export default function FarmDetailPage({ params }: { params: Promise<{ farmId: s
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add New Crop</DialogTitle>
|
||||
<DialogDescription>Fill out the form to add a new crop to your farm.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<AddCropForm onSubmit={handleAddCrop} onCancel={() => setIsDialogOpen(false)} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* New Crop Dialog */}
|
||||
<CropDialog open={isDialogOpen} onOpenChange={setIsDialogOpen} onSubmit={handleAddCrop} />
|
||||
|
||||
{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>
|
||||
|
||||
@ -4,12 +4,14 @@ import { useState } from "react";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Search } from "lucide-react";
|
||||
import { Link, Search } from "lucide-react";
|
||||
import { FarmCard } from "./farm-card";
|
||||
import { AddFarmForm } from "./add-farm-form";
|
||||
import { useRouter } from "next/navigation";
|
||||
import type { Farm } from "@/types";
|
||||
|
||||
export default function FarmSetupPage() {
|
||||
const router = useRouter();
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [farms, setFarms] = useState<Farm[]>([
|
||||
@ -17,7 +19,7 @@ export default function FarmSetupPage() {
|
||||
id: "1",
|
||||
name: "Green Valley Farm",
|
||||
location: "Bangkok",
|
||||
type: "durian",
|
||||
type: "Durian",
|
||||
createdAt: new Date(),
|
||||
},
|
||||
]);
|
||||
@ -70,7 +72,14 @@ export default function FarmSetupPage() {
|
||||
</Dialog>
|
||||
|
||||
{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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user