Settle the four remaining layout deviations from the audit

- Vorsorge dashboard tile title joins the dashboard heading ladder
  (titleAs=h2 like its sibling tiles).
- A user's own note on the mobile measurement card renders in the
  foreground colour; user data is never muted.
- The compact Vorsorge list row expresses its density on the Card
  instead of overriding the content slot's padding with an off-scale
  step.
- The AI-consent card holds its space with a skeleton while the receipt
  loads instead of popping in and shifting the section below.
This commit is contained in:
Marc-André Bombeck committed 2026-08-14 05:07:14 +02:00
1 parent 487eb6970c
commit 6b3a5a4182
4 files changed
+25 -4

No files matched your search

@@ -147,6 +147,7 @@ export function VorsorgeDashboardCard() {
size="sm"
icon={CalendarClock}
title={t("measurementReminders.sectionTitle")}
titleAs="h2"
/>
</CardHeader>
<CardContent className="space-y-2">
@@ -1011,8 +1011,10 @@ function VorsorgeCard({
if (view === "list") {
return (
<>
<Card>
<CardContent className="flex items-center justify-between gap-3 px-4 py-2.5">
{/* Density lives on the Card (py-3 vs the default py-4 md:py-6);
the content slot keeps its own px-4 md:px-6 contract. */}
<Card className="py-3 md:py-3">
<CardContent className="flex items-center justify-between gap-3">
<div className="min-w-0 space-y-0.5">
<div className="flex flex-wrap items-center gap-x-2 text-sm">
<span className="truncate font-medium">
@@ -1391,7 +1391,9 @@ export function MeasurementList({
)}
</p>
{m.notes && (
<p className="text-muted-foreground truncate text-xs">
// User data is never muted — the desktop table
// renders the same note in the foreground colour.
<p className="text-foreground truncate text-xs">
{truncateComment(m.notes)}
</p>
)}
+17 -1
View File
@@ -25,6 +25,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Loader2, ShieldCheck, ShieldOff } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { apiFetchRaw } from "@/lib/api/api-fetch";
import { formatDateTime } from "@/lib/format";
import { useTranslations } from "@/lib/i18n/context";
@@ -101,9 +102,24 @@ export function AiConsentCard({
},
});
if (!isAuthenticated) return null;
// Say nothing until the state is known: a card that flashes "withdrawn"
// before the receipt arrives would misreport the user's own decision.
if (!isAuthenticated || isLoading) return null;
// But hold the block's space with a skeleton mirroring the final shape —
// returning null here made the section pop in and shift everything
// below it once the receipt arrived.
if (isLoading) {
return (
<section className="space-y-3" data-slot="ai-consent">
<div className="space-y-1">
<Skeleton className="h-5 w-40" />
<Skeleton className="h-4 w-56" />
</div>
<Skeleton className="h-8 w-32" />
</section>
);
}
// Narrow to the receipt itself rather than a boolean, so the branches
// below can read its fields without an assertion.