Files
HealthLog/src/components/settings/dashboard-section.tsx
T
Marc-André Bombeck b99a015266 feat(medications): make injection-site tracking and rotation real
The injection_site column on intake events was read across several
surfaces but never written, so site tracking was effectively dead. Wire
it end-to-end as a per-medication opt-in, gated on an INJECTION delivery
form and default off.

- Schema: add medications.track_injection_sites + allowed_injection_sites
  and users.global_excluded_injection_sites (migrations 0099, 0100;
  additive, defaulted, no backfill).
- Intake write path: accept an optional injectionSite on the per-med,
  status-toggle, and bulk intake routes. Persist it only on a taken
  injection with tracking enabled, validated against the medication's
  effective allowed set (per-med allowed sites minus the user-level
  global exclusion, deny wins) — a disallowed site returns 422 (the bulk
  route skips the entry).
- Rotation: extend the least-recently-used recommender with an allowed
  filter; the picker disables sites outside the effective set.
- UI: per-medication tracking toggle + allowed-sites editor in the dose
  wizard step, a skippable post-dose site prompt on both medication
  cards, and a Settings card for the user-level global exclusion.
- Contract: injectionSite is additive on the intake request; OpenAPI
  regenerated. New GET/PATCH /api/auth/me/injection-site-prefs.

The site capture is always optional and never blocks logging a dose.
2026-06-01 20:25:34 +02:00

38 lines
1.1 KiB
TypeScript

"use client";
import { DashboardLayoutSection } from "@/components/settings/dashboard-layout-section";
import { UnitPreferenceCard } from "@/components/settings/unit-preference-card";
import { InjectionSitesCard } from "@/components/settings/injection-sites-card";
import { useAuth } from "@/hooks/use-auth";
import { useTranslations } from "@/lib/i18n/context";
export function DashboardSection() {
const { t } = useTranslations();
const { isAuthenticated } = useAuth();
return (
<section
aria-labelledby="settings-section-dashboard-title"
className="space-y-6"
>
<header className="space-y-1">
<h1
id="settings-section-dashboard-title"
className="text-2xl font-semibold tracking-tight"
>
{t("settings.sections.dashboard.title")}
</h1>
<p className="text-muted-foreground text-sm">
{t("settings.sections.dashboard.description")}
</p>
</header>
<UnitPreferenceCard isAuthenticated={isAuthenticated} />
<InjectionSitesCard isAuthenticated={isAuthenticated} />
<DashboardLayoutSection id="dashboard-layout" />
</section>
);
}