diff --git a/src/app/garden/plants/[id]/page.tsx b/src/app/garden/plants/[id]/page.tsx index 2cd02bd..cf42cdb 100644 --- a/src/app/garden/plants/[id]/page.tsx +++ b/src/app/garden/plants/[id]/page.tsx @@ -1,15 +1,19 @@ import { notFound } from "next/navigation"; -import { getPlant } from "@/modules/garden/server/queries"; +import { getCareLogs, getCareSchedules, getPlant } from "@/modules/garden/server/queries"; import { PlantDetail } from "@/modules/garden/components/plant-detail"; export default async function PlantPage({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; - const plant = await getPlant(id); + const [plant, careLogs, careSchedules] = await Promise.all([ + getPlant(id), + getCareLogs(id), + getCareSchedules(id), + ]); if (!plant) notFound(); return (
- +
); } diff --git a/src/modules/garden/components/care-history-list.tsx b/src/modules/garden/components/care-history-list.tsx new file mode 100644 index 0000000..f7d481b --- /dev/null +++ b/src/modules/garden/components/care-history-list.tsx @@ -0,0 +1,45 @@ +import type { CareLogDto } from "../server/queries"; + +const CARE_ICONS: Record = { + watering: "πŸ’§", + fertilizing: "🌱", + repotting: "πŸͺ΄", + pruning: "βœ‚οΈ", + "pest-control": "πŸ›", + other: "πŸ“‹", +}; + +function timeAgo(iso: string): string { + const diff = Date.now() - new Date(iso).getTime(); + const days = Math.floor(diff / (1000 * 60 * 60 * 24)); + if (days === 0) return "Today"; + if (days === 1) return "Yesterday"; + return `${days} days ago`; +} + +type Props = { + logs: CareLogDto[]; +}; + +export function CareHistoryList({ logs }: Props) { + if (logs.length === 0) { + return

No care events logged yet.

; + } + + return ( + + ); +} diff --git a/src/modules/garden/components/care-log-form.tsx b/src/modules/garden/components/care-log-form.tsx new file mode 100644 index 0000000..7c7d870 --- /dev/null +++ b/src/modules/garden/components/care-log-form.tsx @@ -0,0 +1,97 @@ +"use client"; + +import { useState, useTransition } from "react"; +import { logCare } from "../server/actions"; + +const CARE_TYPES = ["watering", "fertilizing", "repotting", "pruning", "pest-control", "other"]; + +type Props = { + plantId: string; + defaultCareType?: string; + onSuccess?: () => void; +}; + +export function CareLogForm({ plantId, defaultCareType = "watering", onSuccess }: Props) { + const [careType, setCareType] = useState(defaultCareType); + const [notes, setNotes] = useState(""); + const [performedAt, setPerformedAt] = useState(""); + const [error, setError] = useState(null); + const [isPending, startTransition] = useTransition(); + + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + setError(null); + startTransition(async () => { + try { + await logCare({ + plantId, + careType, + notes: notes || null, + performedAt: performedAt || undefined, + }); + setNotes(""); + setPerformedAt(""); + onSuccess?.(); + } catch { + setError("Failed to log care. Please try again."); + } + }); + } + + return ( +
+
+ + +
+ +
+ + setPerformedAt(e.target.value)} + className="input input-sm" + /> +
+ +
+ +