feat: garden care tracking - logs, schedules, reminders (task 73)

- logCare/deleteCareLog actions with schedule update and reminder wiring
- upsertCareSchedule/deleteCareSchedule/toggleCareSchedule actions
- updateScheduleAfterCare helper cancels old reminder, schedules new one
- getCareLogs/getCareSchedules/getOverduePlants/getCareDueSoon queries
- CareLogForm, CareScheduleEditor, CareHistoryList components
- Plant detail Care tab wired up with schedule editor + log form + history
- Log plant care quick-add added to garden manifest
This commit is contained in:
ginnoir
2026-06-01 20:23:43 -05:00
parent fe282ba470
commit 0fef3d4ab6
9 changed files with 714 additions and 9 deletions
+25 -4
View File
@@ -4,11 +4,18 @@ import { useState, useTransition } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { deletePlant, addPlantImage, removePlantImage, setPrimaryImage } from "../server/actions";
import type { PlantDetailDto } from "../server/queries";
import type { CareLogDto, CareScheduleDto, PlantDetailDto } from "../server/queries";
import { CareHistoryList } from "./care-history-list";
import { CareLogForm } from "./care-log-form";
import { CareScheduleEditor } from "./care-schedule-editor";
type Tab = "info" | "gallery" | "care";
type Props = { plant: PlantDetailDto };
type Props = {
plant: PlantDetailDto;
careLogs: CareLogDto[];
careSchedules: CareScheduleDto[];
};
function InfoRow({
label,
@@ -34,7 +41,7 @@ function healthBadgeClass(status: string): string {
return "badge-warning";
}
export function PlantDetail({ plant }: Props) {
export function PlantDetail({ plant, careLogs, careSchedules }: Props) {
const [tab, setTab] = useState<Tab>("info");
const [confirming, setConfirming] = useState(false);
const [isPending, startTransition] = useTransition();
@@ -252,7 +259,21 @@ export function PlantDetail({ plant }: Props) {
{/* Care */}
{tab === "care" && (
<p className="text-sm text-[var(--ink-mute)]">Care tracking coming soon.</p>
<div className="flex flex-col gap-6">
<CareScheduleEditor plantId={plant.id} schedules={careSchedules} />
<div className="border-t border-[var(--ink-faint)] pt-4">
<p className="text-sm font-semibold text-[var(--ink-mute)] uppercase tracking-wide mb-3">
Log care
</p>
<CareLogForm plantId={plant.id} onSuccess={() => router.refresh()} />
</div>
<div className="border-t border-[var(--ink-faint)] pt-4">
<p className="text-sm font-semibold text-[var(--ink-mute)] uppercase tracking-wide mb-3">
History
</p>
<CareHistoryList logs={careLogs} />
</div>
</div>
)}
</div>
);