- Add MinIO service to compose.yaml with named volume - Add generic /api/uploads POST+GET route with auth, 5 MB, image/* guards - Add src/lib/minio.ts singleton client with ensureBucket helper - Add garden Drizzle schema: containers, plants, care_logs, care_schedules, species_cache - Register garden module in src/modules/index.ts and src/lib/db.ts - Apply migration 0015_garden_schema.sql - Add MINIO_* and PERENUAL_API_KEY to .env.example - Add task briefs 70-75 for the full garden feature arc - Add uploads.spec.ts E2E test (RED → GREEN on route auth guard)
3.9 KiB
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;performedAtdefaults to now(). Insert intogarden_care_logs. After inserting: callupdateScheduleAfterCare(plantId, careType), calllogActivity,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). Recomputenext_due_at: iflast_performed_atexists uselast_performed_at + intervalDays, elsenow() + 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 })— flipenabled; 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 orderedperformed_at desc.getCareSchedules(plantId)— all schedules with computeddaysUntilDueandisOverdue.getOverduePlants(householdId)— plants with at least one enabled schedule wherenext_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: <CareScheduleEditor /> → "Log care" button → <CareHistoryList />.
Quick-add (update manifest)
{
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_aton the matching schedule. - Creating a schedule with interval 7 sets
next_due_atto 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.
getOverduePlantsreturns correctly sorted results.- Care tab in plant detail shows schedule editor, log form, and history.
- "Log plant care" appears in the quick-add sheet.