# 73 — Garden care tracking ## Goal Implement the **care log** and **care schedule** systems. Users can log a care event for any plant (watered, fertilized, repotted, etc.), set up recurring schedules with an interval, and receive reminders when care is due. ## Depends on - 70 (schema), 72 (plants exist to attach care records to) - 41 (reminders system — `scheduleReminder` / `cancelReminder`) ## Scope ### Care log actions (`src/modules/garden/server/actions.ts`) - `logCare(input: { plantId, careType, notes?, performedAt? })` — Zod-validated; `performedAt` defaults to now(). Insert into `garden_care_logs`. After inserting: call `updateScheduleAfterCare(plantId, careType)`, call `logActivity`, `revalidatePath`. - `deleteCareLog(input: { id })` — household check, delete. ### Care schedule actions (`src/modules/garden/server/actions.ts`) - `upsertCareSchedule(input: { plantId, careType, intervalDays, enabled? })` — upsert on `(plant_id, care_type)`. Recompute `next_due_at`: if `last_performed_at` exists use `last_performed_at + intervalDays`, else `now() + intervalDays`. Wire reminder: `scheduleReminder({ entityType: "garden.schedule", entityId: scheduleRow.id, fireAt: next_due_at })`. - `deleteCareSchedule(input: { id })` — `cancelReminder("garden.schedule", id)`, delete. - `toggleCareSchedule(input: { id, enabled })` — flip `enabled`; cancel reminder if disabling, reschedule if enabling. ### Schedule update helper (`src/modules/garden/server/care-schedule.ts`) `updateScheduleAfterCare(plantId, careType)` — finds the schedule row, sets `last_performed_at = now()`, `next_due_at = now() + interval_days`, cancels old reminder, schedules new one. Uses `entityType = "garden.schedule"` + `entityId = schedule.id` to satisfy the unique constraint on `(entity_type, entity_id)` in the reminders table — one reminder per schedule row, not per plant. ### Queries (`src/modules/garden/server/queries.ts`) - `getCareLogs(plantId, limit?)` — most recent N logs ordered `performed_at desc`. - `getCareSchedules(plantId)` — all schedules with computed `daysUntilDue` and `isOverdue`. - `getOverduePlants(householdId)` — plants with at least one enabled schedule where `next_due_at < now()`, sorted most-overdue first. - `getCareDueSoon(householdId, withinDays)` — plants with care due within N days. ### UI (`src/modules/garden/components/`) **`care-log-form.tsx`** (client component) — plant picker + care type select + optional notes + optional performed-at datetime (defaults to now). Used as a sheet and inline in the plant detail Care tab. **`care-schedule-editor.tsx`** (client component) — list of active schedules per plant (care type, interval, next due, enabled toggle, delete). "Add schedule" form with care type + interval days. **`care-history-list.tsx`** (server component) — chronological log entries: care type icon, "X days ago", performed-by avatar, notes. ### Plant detail Care tab (update `plant-detail.tsx` from task 72) The Care tab (previously placeholder) renders: `` → "Log care" button → ``. ### Quick-add (update manifest) ```typescript { id: "garden.log-care", label: "Log plant care", icon: "droplets", url: "/garden", } ``` ## Out of scope - Calendar/lists integration (task 74). - Dashboard widget (task 75). ## Acceptance criteria - [ ] Logging care inserts a log row and updates `last_performed_at` + `next_due_at` on the matching schedule. - [ ] Creating a schedule with interval 7 sets `next_due_at` to 7 days from now; a reminder is scheduled. - [ ] After logging care, old reminder is cancelled and a new one scheduled. - [ ] Disabling a schedule cancels its reminder; re-enabling reschedules it. - [ ] Deleting a schedule cancels its reminder. - [ ] `getOverduePlants` returns correctly sorted results. - [ ] Care tab in plant detail shows schedule editor, log form, and history. - [ ] "Log plant care" appears in the quick-add sheet.