mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
v1.4.33 — polish and reliability
Quality-leap release between two HealthKit milestones. The headline is a P0 hotfix for the `/api/analytics` 500 that broke the Insights mother page for any account with more than a few thousand measurements: the six per-metric status helpers were spreading the entire numeric history into `Math.min` / `Math.max`, which trips a stack overflow once a single argument list exceeds the V8 spread cap. Both the surfaced symptom and the latent risk in five sibling helpers were folded onto a reduce-based min/max path. Around that hotfix landed a deep polish pass: the Insights mother page now defers three below-the-fold blocks behind `next/dynamic` to trim the cold mount cost, the analytics endpoint gained a `?slice=summaries` slim slice that the per-metric sub-pages now ride, the Coach snapshot builder picked up a 60 s LRU keyed on `(userId, scope)`, the Settings shell consolidated three duplicate copies of the about / notifications / about-dropdown surfaces, the navigation strip dropped a redundant "Home" group label and a colliding "Notifications" sibling, every icon-only button on the medications and admin surfaces gained an accessible name, every Progress bar gained one too, three pages had their heading hierarchy repaired to a sequential h1 → h2 → h3, the mobile Coach FAB now hides while a chart tooltip is open so it cannot occlude the read-out, and the auth shell normalised every authenticated route to a single `max-w-screen-xl` container. Also lands the Apple App Site Association handler at `/.well-known/apple-app-site-association` on every host that fronts the app, advertising the iOS bundle's App ID prefix (S8WDX4W5KX.dev.healthlog.app) under `webcredentials.apps` so the passkey ceremony shares cleanly between the web origin and the iOS app. The release closes nineteen issues from a five-surface audit + a runtime bug-hunt pass, plus six follow-up tracks of polish across the affected surfaces.
This commit is contained in:
1 parent
c7a0ff214b
commit
7bef199039
186 files changed
+9358
-946
No files matched your search
@@ -57,7 +57,9 @@ describe("<AiQualitySection>", () => {
|
||||
mockQueryState.isLoading = false;
|
||||
mockQueryState.isError = false;
|
||||
const html = render(<AiQualitySection />);
|
||||
expect(html).toContain("AI Quality");
|
||||
// v1.4.33 IW7 — admin section renamed from "AI Quality" to
|
||||
// "Insights Quality" per the Marc-Voice rule.
|
||||
expect(html).toContain("Insights Quality");
|
||||
expect(html).toContain("No feedback yet");
|
||||
});
|
||||
|
||||
@@ -118,6 +120,6 @@ describe("<AiQualitySection>", () => {
|
||||
mockQueryState.isLoading = false;
|
||||
mockQueryState.isError = true;
|
||||
const html = render(<AiQualitySection />);
|
||||
expect(html).toContain("Failed to load AI quality summary");
|
||||
expect(html).toContain("Failed to load Insights quality summary");
|
||||
});
|
||||
});
|
||||
@@ -148,7 +148,10 @@ describe("admin sections — SSR smoke", () => {
|
||||
// ai-quality-section test.
|
||||
it("<AiQualitySection> renders the empty-state when no summary exists", () => {
|
||||
const html = render(<AiQualitySection />);
|
||||
expect(html).toContain("AI Quality");
|
||||
// v1.4.33 IW7 — section renamed from "AI Quality" to
|
||||
// "Insights Quality" per the Marc-Voice rule (no "KI"/"AI" prefix
|
||||
// in user-facing copy).
|
||||
expect(html).toContain("Insights Quality");
|
||||
expect(html).toContain("No feedback yet");
|
||||
});
|
||||
|
||||
|
||||
@@ -434,9 +434,11 @@ function FeedbackDetailDialog({
|
||||
|
||||
{(url || locale || userAgent || appVersion) && (
|
||||
<div>
|
||||
<h4 className="text-muted-foreground text-xs font-semibold tracking-wider uppercase">
|
||||
{/* v1.4.33 IW9 — h4 -> h3 so the sheet outline stays
|
||||
sequential beneath the ResponsiveSheet's h2 title. */}
|
||||
<h3 className="text-muted-foreground text-xs font-semibold tracking-wider uppercase">
|
||||
{t("admin.feedback.metadataHeading")}
|
||||
</h4>
|
||||
</h3>
|
||||
<dl className="mt-2 grid grid-cols-[max-content_1fr] gap-x-3 gap-y-1 text-xs">
|
||||
{url && (
|
||||
<>
|
||||
@@ -476,9 +478,9 @@ function FeedbackDetailDialog({
|
||||
|
||||
{item.screenshotBase64 && (
|
||||
<div>
|
||||
<h4 className="text-muted-foreground mb-2 text-xs font-semibold tracking-wider uppercase">
|
||||
<h3 className="text-muted-foreground mb-2 text-xs font-semibold tracking-wider uppercase">
|
||||
{t("admin.feedback.screenshotHeading")}
|
||||
</h4>
|
||||
</h3>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={item.screenshotBase64}
|
||||
|
||||
@@ -252,9 +252,11 @@ export function RemindersSection() {
|
||||
{reminderCheck.data?.medications &&
|
||||
reminderCheck.data.medications.length > 0 && (
|
||||
<div className="mt-4 space-y-2">
|
||||
<h4 className="text-sm font-medium">
|
||||
{/* v1.4.33 IW9 — h4 -> h2 so the page outline stays
|
||||
sequential (parent admin SectionFrame ships <h1>). */}
|
||||
<h2 className="text-sm font-medium">
|
||||
{t("admin.reminderCheckResults")}
|
||||
</h4>
|
||||
</h2>
|
||||
<div className="space-y-2">
|
||||
{reminderCheck.data.medications.map((med, i) => (
|
||||
<div key={i} className="bg-muted/50 space-y-1.5 rounded-lg p-3">
|
||||
|
||||
Reference in new issue
Block a user