mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
Mostly table column normalisation under docs/audit/ + planning, object- literal expansion in src/lib/ai/coach/snapshot.ts after the W4 F6 Apple Health metric block landed, and small wrap/unwrap line adjustments in the device + APNs routes / tests touched across W3/W4/W5 sessions. No behavioural change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
18 KiB
18 KiB
v1.4.20 backlog — A8 deferred MED + LOW
Source: .planning/phase-A8-quality-findings.md (78 findings).
v1.4.19 Wave B applied 6/6 CRIT and 21/25 HIGH; this file is
the carry-over.
The strategic Insights redesign + AI Coach is the v1.4.20 headline. Pick winners from the list below before / after that work — most of these are 1–3 lines of i18n or a single component edit.
HIGH deferred (4)
- F-12 — User-management mobile cards, 5 icon buttons
(
src/components/admin/user-management-section.tsx). Spot check during Wave B showed every icon button already carriesaria-label+title(edit, reset password, force logout, role change). Treat as not-an-issue; revisit only if a concrete a11y audit re-flags it. - F-14 — Settings/Integrations status duplicated. Already shipped under v1.4.19 A5; keep an eye out for regressions but no new work here.
- F-23 — Mood / Achievements DE strings. Spot check showed
every mood label (
mood.levelLausig…mood.moodLabel5,mood.moodAwful…mood.moodGreat) is translated inmessages/de.json. The achievement-subtitle awkwardness was fixed by F-27. Treat as not-an-issue; revisit only with a fresh DE-locale screen-by-screen pass. - F-26 — Insights regenerate banner / refresh button conflict. Already partially in A3 scope (page-level Regenerate, per-recommendation Regenerate). The banner button copy was fixed in F-06. Per-tile refresh icons removal is a v1.4.20 Insights-redesign concern.
MEDIUM (31)
Layout / spacing
- F-32 —
/settings/dashboardtriple help blocks (subtitle + card help + "Adds a dimmed prior-period overlay…").messages/*.json:settings.sections.dashboard.descriptiondashboardLayout.compareCallout. S.
- F-39 —
/settings/dashboardcolumn headsTILE/CHARTin uppercase (src/components/settings/dashboard-layout-section.tsx). Sentence-case to match the rest of the app. S. - F-57 — Mobile settings tab strip clips
Notificat…with no scroll affordance (src/app/settings/[section]/page.tsx, the inline pill strip). Add a right-edge fade gradient or a chevron. M.
Copy nits
- F-33 —
/moodsubtitle "Mood tracker & entries" — drop ampersand + redundant words.messages/*.json:mood.subtitle. S. - F-34 —
/measurementssubtitle "Weight, blood pressure, pulse & more" — replace&withand/und.messages/*.json:measurements.subtitle. S. - F-35 — Send-test button label "Send test" vs "Test
message".
messages/*.json:settings.telegramTest,settings.notificationStatus.sendTest. S. - F-36 — Status-word inconsistency "Connected / Running /
Active / Configured" across system-status / integrations /
notifications. Reduce to two words:
Healthy/Disabled/Error. M. - F-37 — Form labels with trailing colon ("Username:" vs "Default language") — sweep across every settings page, pick the no-colon variant. M.
- F-38 —
/settings/thresholds"Auto:" pseudo-label trailing colon.src/components/settings/thresholds-editor-section.tsx,messages/*.json:thresholds.autoModeLabel. S. - F-44 —
/admin/app-logsreferences env varLOKI_ENDPOINTto end-users.messages/*.json:admin.appLogs.workerHint. S. - F-45 —
/admin/usersfirst column header is "Users" (the user-name column) — should be "Name" or "User".src/components/admin/user-management-section.tsxtable head. Date format already covered by F-04. S. - F-46 —
/admin/backupsupload help "JSON file matching the current backup schema. Max 10 MB." is a sentence fragment.messages/*.json:admin.section.backups.uploadHelp. S. - F-47 —
/notifications(per-event rules) and/settings/notifications(channels) share H1 "Notifications". Rename one to "Notification rules", the other to "Notification channels". S. - F-48 —
/insights"AI Health Analysis" + "Personal advisor" subtitle redundant. Drop the "Personal advisor" subtitle — but coordinate with v1.4.20 Insights redesign first. S. - F-49 — Decimal separator inconsistent on DE locale
(
88.6 kgvs88,6 kg). Sweepvalue.toFixed(1)patterns, replace withfmt.number()/Intl.NumberFormat(locale).format(). M. - F-50 — DE error-toast tone: 6 instances of
Bitte erneut versuchen(impersonal infinitive) vs the HealthLog-standard personalBitte versuche es erneut.messages/de.json:746, 937–940, 1172, 1222. S. - F-51 —
/settings/accountDOB hint "Used for automatic blood pressure target calculations" vs Gender hint "Used for gender-specific target values" — pick one phrasing.messages/*.json:settings.dateOfBirthHint,settings.genderHint. S. - F-53 —
/settings/aisubtitle "Provider, model, key." is a noun list, not a sentence.messages/*.json:settings.sections.ai.description. S. - F-54 —
/settings/aimixes "Codex", "ChatGPT", "OpenAI" — pick one user-facing brand. S (i18n) but with cross-component consequences. - F-55 —
/settings/export"Configure & generate" CTA uses ampersand.messages/*.json:settings.sections.export.cta. S. - F-56 —
/settings/advancedsubtitle says "danger zone" but card title is "Delete All Data". Rename section header to "Reset account data" / "Daten zurücksetzen" so the user-side surface is distinct from admin Danger Zone.messages/*.json:settings.sections.advanced.title. S. - F-58 —
/admin/reminders"Run reminder check" button uses wave/chart icon — change toRotateCw/Clockicon.src/components/admin/reminders-section.tsx. S. - F-62 — Mobile dashboard greeting "Hello Marc, welcome
back." in EN vs DE. Spot-check whether DE bundle renders;
fall-back-to-EN when missing was already audited.
messages/*.json:dashboard.greeting,dashboard.greetingSubtitle. S.
Typography / mobile / icons
- F-40 — Compliance bars on medication card uniform purple
regardless of % value. Threshold-coloured fill (≥80 % green,
50–80 % yellow, <50 % red).
src/components/medications/medication-card.tsxProgress. S. - F-41 — Targets page label inconsistency
("Normal", "Optimal", "Moderate", "On target"). Already
partly covered by A7. Standardise to a small set:
Optimal/On target/Watch/Off target.src/app/targets/page.tsx. S. - F-42 —
/auth/loginmobile vertical centering + missing app subtitle ("Sign in to your HealthLog account."). S. - F-43 —
/admin/api-tokens"Collapse" / "Einklappen" already removed by A7; F-43 also flags/admin/login-overview— same pattern, single-card page, drop the toggle.src/components/admin/login-overview-section.tsxexpandedtoggle +setExpanded. S. - F-59 — Mood entries show numeric score
2 (Bad)/3 (Okay)— paren label feels debug-y. Switch to coloured 1-5 badge + descriptor.src/components/mood/mood-list.tsx. S. - F-60 — Comment column shows
-(hyphen) instead of empty cell or em-dash.src/components/measurements/measurement-list.tsx,src/components/mood/mood-list.tsx. S. - F-61 — Empty IP / Location columns on /admin/login-overview
always render
—. Hide columns when no rows have the field populated.src/components/admin/login-overview-section.tsx. M.
LOW (16)
- F-63 —
/auth/logindivider "or" — keep as-is or "Or sign in with password". S. - F-64 — Achievement card "Idiot" / "Lazy Boy" badges share
a sparkle icon. (Titles already fixed via F-03; pick distinct
icons next pass.)
src/components/achievements/*. S. - F-65 — Targets page card-icons mixed colors (purple scale,
pink heart, green pulse) — pick a single muted Dracula
palette.
src/app/targets/page.tsx. S. - F-66 — Withings card "Save credentials" button stays
grey/muted; user doesn't know it's clickable. Make it
disableduntil dirty, primary purple when dirty.src/components/settings/withings-section.tsx. S. - F-67 — Sort indicators inconsistent on /measurements
table headers (some
↕, Date shows↓). Render a single arrow that flips on toggle.src/components/measurements/measurement-list.tsxtable header. S. - F-68 —
/medicationsbutton "Skipped" visually almost as prominent as "Taken". Demote to ghost / secondary.src/components/medications/medication-card.tsx. S. - F-69 — Achievements card "Next goal" inline format —
"Progress to unlock: 166 / 200 (83%)" then "320 points" on a
separate line. Inline both.
src/components/achievements/*. S. - F-70 —
/settings/integrationsWithings client-id placeholder gets truncated mid-word at 1280 px desktop. Use a shorter "Already saved".messages/*.json:settings.withingsCredentialsSavedPlaceholder. S. - F-71 —
/insights"Generated 57 minutes ago" — pick one convention (relative for recent, absolute on hover). S. - F-72 — Bare Next.js 404 ("This page could not be found.")
with no nav. Add custom
app/not-found.tsxwith logo + "Back to dashboard" CTA. S. - F-73 — Onboarding subtitle + footer say the same thing
("Skip this step — you can finish setup later from
Settings."). Drop one.
src/app/onboarding/page.tsx. S. - F-74 —
/settings/accountDOB hint mentions only blood pressure but BP target also uses gender — hoist explanation to section level. Already overlaps with F-51. S. - F-75 —
/insights"Based on your last 90 days" doesn't update with the active range tab. Tie the message to the selected range.src/components/insights/insight-advisor-card.tsx. M. - F-76 —
/admin/system-statuscards "Last Reminder Check" inconsistent capitalisation. Sentence-case throughout.messages/*.json:admin.section.system-status.*. S. - F-77 —
/admin/api-tokens"Last used: Never" / "Created: 05/05/2026" colon style + date format. Already covered by F-04 (date format) and F-37 (colon style). S. - F-78 —
/settings/account"Profile" sub-card heading repeats page-level "Account" framing — drop the inner heading.src/components/settings/account-section.tsx. S.
Phase D — v1.4.19 reconcile carry-over
HIGH deferred
- D-CR-H-05 —
/insights/page.tsxreadsdata?.moodSummary,data?.moodBpScatterDataetc. after theif (!data) returnguard at ~ line 820. TypeScript narrowsdatato non-null below that point, so the optional chains are dead. Hoist the early return above the*SectionStatusprecomputes (lines 720–790 still needdata?.) so the rest of the body can drop the redundant operators. Touches lots of references but is mechanical.src/app/insights/page.tsx:756,758,1036,1046,1064-1065,1235,1245, 1248-1252,1263-1273. Owner: v1.4.20 Insights redesign. - D-DSGN-H-01 — Truncate-with-tooltip on
/admin/api-tokensis not reachable on touch (Radix Tooltip is hover/focus only, nativetitle=is iOS-Safari-ignored). Droptruncateon the mobile card list and let long values wrap to two lines, OR switch to a Radix Popover. Desktop hover stays as-is.src/components/admin/api-token-overview-section.tsx:37-56,232. - D-DSGN-H-02 — Insights hero density on Pixel-5 (3+1 control
rows). Inline the
<CompareToggle>next to the Regenerate button on>=sminstead of stacking inside the title block. Folded into the v1.4.20 Insights redesign hero rebuild.src/components/insights/insights-page-hero.tsx:101-163. - D-SR-H-3 — Withings + Mood Log card chrome duplicated
verbatim (header row → divider → body). v1.5 Apple Health card
will copy-paste a third time. Extract
<IntegrationCard>shell alongside the existingIntegrationStatusPill.src/components/settings/integrations-section.tsx:199-531,533-831.
MED deferred (code-review M-01..M-07, senior-dev M-1..M-5,
design M-01..M-04)
- D-CR-M-01 —
/insightsper-section status queries carrystaleTime: 60_000but the top-levelcomprehensive/analyticsqueries have nostaleTimeoverride. Page can reconcile out-of-sync after 30 s. Unify under one staleTime.src/app/insights/page.tsx:553-643. - D-CR-M-02 —
<HealthChart>on/insightsmounts without achartKeyso the cog dropdown is invisible. Document the dashboard-only intent in the chart-header comment, OR add chart keys to the dashboard layout for/insightsconsumers.src/app/insights/page.tsx:948-1480. - D-CR-M-03 —
formatTokenNameregex requires trailingZ(UTC). Broaden to(?:Z|[+-]\d{2}:?\d{2})$for offset-based ISO.src/components/admin/api-token-overview-section.tsx:66-67. - D-CR-M-04 — Tabs
overflow-y-hiddencomment cites the strip height as the cause; the actual culprit is the<Badge>child insideTabsTrigger. Update the comment so a future cleanup pass keeps the context.src/components/ui/tabs.tsx:38-46. - D-CR-M-05 —
STATUS_CATEGORY_KEYmap duplicates every server classification string. Add a vitest case that diffs the union of the server's emitted strings against the map's keyset.src/app/targets/page.tsx:115-166. - D-CR-M-06 —
/api/analyticsfetches all paired BP rows for the all-time aggregate. For a 5-year power user that's ~9 000 rows × 2; annotatebpSysCount,bpDiaCounton the existinganalytics.getWide Event for slow-query attribution.src/app/api/analytics/route.ts:71-86. - D-CR-M-07 —
chooseTickIntervalreturns 0 for small datasets; Recharts'preserveStartEnddoesn't drop colliding labels at 360–480 px. Pin behaviour with a 393 px e2e smoke.src/lib/charts/x-axis-density.ts:80-87. - D-SR-M-1 — Chart-card mobile-stack header pattern repeated 3×
across
health-chart,mood-chart,medication-compliance-chart. Extract<ChartCardHeader>taking title / bucket / range controls / overlay-menu slots. - D-SR-M-2 —
TIME_RANGES_KEYSarray duplicated verbatim in health-chart + mood-chart. Move tosrc/lib/charts/time-ranges.tsalongsidex-axis-density.ts. - D-SR-M-4 — F-02 auth filter expressed in two places
(URL param + dropdown filter). Single named constant
AUTH_ACTION_PREFIX = "auth."+isAuthAction()helper.src/components/admin/login-overview-section.tsx:96,256. - D-SR-M-5 —
<InsightAdvisorCard>four-branch render ships{title && …}four times. Extract a local<AdvisorCardHeader>and have every branch mount it.src/components/insights/insight-advisor-card.tsx:344,377,485,552. - D-DSGN-M-01 —
/admin/api-tokensstill has the inner<div className="text-lg font-semibold">API Tokens</div>next to the SectionFrame<h1>API Tokens</h1>. F-08 sweep cleared the same dup on/admin/danger-zone+/admin/feedbackbut deferred this one.src/app/admin/[section]/renderer.tsx:123-131, 180-192+src/components/admin/api-token-overview-section.tsx:101-106. - D-DSGN-M-02 — Profile DOB still wrapped in a
grid sm:grid-cols-2with one cell, leaving an empty right column on>=sm. Replace withsm:max-w-md.src/components/settings/account-section.tsx:383-398. - D-DSGN-M-03 — Chart range tabs (
min-h-11, 44 px) read visually heavier than v1.4.19 Settings inputs (h-9, 36 px). Either accept (44 px touch targets matter on draggable cards) or shrink toh-9on>=sm. v1.4.20 chart redesign concern. - D-DSGN-M-04 — Mood Log "Copy webhook secret" button uses
t("common.copied").replace("!", "")as resting label. Addcommon.copykeys (en: "Copy", de: "Kopieren") for the resting state, keepcommon.copiedfor the toast.src/components/settings/integrations-section.tsx:715-725.
LOW deferred
- D-CR-L-01..L-05 — comment dup, IntegrationStatusPill chipClass clarity, e2e threshold tied to desktop default, formatTokenName regex doesn't permit ms-less ISO (currently fine), targets test mock isolation.
- D-DSGN-L-01..L-04 — relative-time abbreviation inconsistency (chips abbreviate, prose spells out), Galaxy Fold orphan dot separator on hero, api-tokens lastUsedAt cell may clip seconds at 1024 px (drop seconds in the formatter), IntegrationStatusPill aria-label generic across states.
- D-SR-L-1..L-8 —
ai-section.tsx(1730 lines),health- chart.tsx(1360),integrations-section.tsx(831) split candidates; Telegram badge concat could reuse the IntegrationStatusPill with apausedvariant;getViewportWidthSSR fallback1280should reference a named constant. - D-SEC-MED-1 —
<RecentAuditPreview>row exposesentry.ipAddressinline on>=sm. Admin-only, no privilege-escalation path; mention in v1.4.19 release brief.src/components/admin/recent-audit-preview.tsx:144-148. - D-SEC-LOW-1 — A4 prompt's
n<7caveat threshold differs from server-siden<3confidence clamp. Tighten to match if feedback showsn=4recommendations land too confidently.src/lib/ai/prompts/insight-generator.ts:86-95,219-229. - D-SEC-LOW-2 — IntegrationStatusPill inline error message
could in principle leak a Withings/MoodLog endpoint URL if a
future caller passes raw HTTP body into
recordSyncFailure. Whitelist before encryption when adding new sync helpers.src/lib/integrations/status.ts:367callers.
Notes for v1.4.20 picks
- The MED block is dominated by copy nits — running prettier
- a single i18n sweep would land 12+ of them in one commit.
- F-36 (status-word taxonomy) is a small refactor that pays off everywhere; consider doing it before the Insights redesign so the new surface inherits the canonical vocabulary.
- F-49 (decimal separator) wants a codemod or grep sweep, not hand-edits — touches many tile components.