style: apply prettier across the tree

One-shot prettier pass so the new format:check gate starts from a clean
baseline. Formatting only — no behaviour change. Generator-owned and
vendored artifacts stay untouched via .prettierignore.
This commit is contained in:
Marc-André Bombeck committed 2026-06-19 22:20:31 +02:00
1 parent b3fea2ef59
commit 1f4ba5939d
1000 files changed
+12130 -8385

No files matched your search

@@ -86,9 +86,7 @@ describe("BD-Zielbereich tile (v1.4.28 FB-C1/C2 rewrite)", () => {
);
// Same primitive slots on both tiles.
for (const slot of [
"trend-card-value-row",
]) {
for (const slot of ["trend-card-value-row"]) {
expect(bdHtml).toContain(`data-slot="${slot}"`);
expect(weightHtml).toContain(`data-slot="${slot}"`);
}
@@ -100,9 +100,8 @@ describe("chart isError rendering — error state, not empty state", () => {
mockQueryError();
const { I18nProvider } = await import("@/lib/i18n/context");
const { MedicationComplianceChart } = await import(
"../medication-compliance-chart"
);
const { MedicationComplianceChart } =
await import("../medication-compliance-chart");
const html = renderToStaticMarkup(
<I18nProvider initialLocale="de" initialMessages={deMessages}>
@@ -125,9 +124,7 @@ describe("<ChartErrorState> — announcement, sizing, accessible name", () => {
});
async function renderState(
props: Partial<
import("../chart-error-state").ChartErrorStateProps
> = {},
props: Partial<import("../chart-error-state").ChartErrorStateProps> = {},
) {
const { ChartErrorState } = await import("../chart-error-state");
return renderToStaticMarkup(
@@ -29,7 +29,6 @@ describe("<MedicationComplianceChart> — empty-state gate by raw count", () =>
vi.resetModules();
});
it("renders need-more-days copy when chartData.length < 3 but rawCount >= 3", async () => {
const data = [
{ date: "2026-05-19", scheduled: 10, taken: 8 },
@@ -48,9 +47,8 @@ describe("<MedicationComplianceChart> — empty-state gate by raw count", () =>
}));
const { I18nProvider } = await import("@/lib/i18n/context");
const { MedicationComplianceChart } = await import(
"../medication-compliance-chart"
);
const { MedicationComplianceChart } =
await import("../medication-compliance-chart");
const html = renderToStaticMarkup(
<I18nProvider initialLocale="de" initialMessages={deMessages}>
@@ -79,9 +77,8 @@ describe("<MedicationComplianceChart> — empty-state gate by raw count", () =>
}));
const { I18nProvider } = await import("@/lib/i18n/context");
const { MedicationComplianceChart } = await import(
"../medication-compliance-chart"
);
const { MedicationComplianceChart } =
await import("../medication-compliance-chart");
const html = renderToStaticMarkup(
<I18nProvider initialLocale="de" initialMessages={deMessages}>
@@ -28,7 +28,6 @@ describe("<MoodChart> — empty-state gate by raw count", () => {
vi.resetModules();
});
it("renders need-more-days copy when chartData.length < 3 but rawCount >= 3", async () => {
const data = {
entries: [
@@ -209,8 +209,10 @@ describe("dashboard.*Short keys exist across all six locales", () => {
.default;
const dashboard = messages.dashboard ?? {};
for (const key of REQUIRED_KEYS) {
expect(dashboard[key], `dashboard.${key} missing in ${locale}.json`)
.toBeTypeOf("string");
expect(
dashboard[key],
`dashboard.${key} missing in ${locale}.json`,
).toBeTypeOf("string");
expect(
(dashboard[key] as string).length,
`dashboard.${key} empty in ${locale}.json`,
@@ -36,12 +36,12 @@ const baseProps = {
describe("<TrendCard staleDays>", () => {
it("stays silent when the metric is fresh (<= 7 days)", () => {
const html = render(<TrendCard {...baseProps} staleDays={3} />);
expect(html).not.toContain("data-slot=\"tile-stale-hint\"");
expect(html).not.toContain('data-slot="tile-stale-hint"');
});
it("renders day-bucket copy when staleDays is in (7, 30]", () => {
const html = render(<TrendCard {...baseProps} staleDays={12} />, "en");
expect(html).toContain("data-slot=\"tile-stale-hint\"");
expect(html).toContain('data-slot="tile-stale-hint"');
expect(html).toContain("Last reading 12 d ago");
});
@@ -248,7 +248,7 @@ export function ChartOverlayControlsBody({
prefs.comparisonBaseline === value ? "default" : "outline"
}
size="sm"
className={`min-h-11 sm:min-h-9 px-2 text-[11px] ${isGreyed ? "opacity-50" : ""}`.trim()}
className={`min-h-11 px-2 text-[11px] sm:min-h-9 ${isGreyed ? "opacity-50" : ""}`.trim()}
onClick={() => setComparisonBaseline(value)}
aria-pressed={prefs.comparisonBaseline === value}
aria-disabled={isGreyed || undefined}
+1 -4
View File
@@ -69,10 +69,7 @@ export function ChartSkeleton({
const [showSlowHint, setShowSlowHint] = useState(false);
useEffect(() => {
if (mini) return undefined;
const handle = setTimeout(
() => setShowSlowHint(true),
SLOW_HINT_DELAY_MS,
);
const handle = setTimeout(() => setShowSlowHint(true), SLOW_HINT_DELAY_MS);
return () => clearTimeout(handle);
}, [mini]);
+8 -2
View File
@@ -259,7 +259,11 @@ export function ComplianceHeatmap({
only kicks in for the non-stretch (static 18 px cell) case
when the parent column is narrower than `weeks * 21 px`. */}
<div
className={stretch ? "w-full sm:w-full overflow-x-auto sm:overflow-visible" : "overflow-x-auto"}
className={
stretch
? "w-full overflow-x-auto sm:w-full sm:overflow-visible"
: "overflow-x-auto"
}
>
<svg
width={svgWidth}
@@ -269,7 +273,9 @@ export function ComplianceHeatmap({
// off `containerWidth`, so a full window still fills the row) rather
// than CSS-stretching ~5 columns of capped cells into wide rectangles.
className={stretch ? "block max-w-full" : "block"}
onMouseLeave={() => setTooltip((prev) => (prev?.pinned ? prev : null))}
onMouseLeave={() =>
setTooltip((prev) => (prev?.pinned ? prev : null))
}
>
{/* Month labels */}
{monthMarkers.map((m, i) => (
+27 -22
View File
@@ -740,7 +740,9 @@ export function HealthChart({
// request so a longer comparison window still resolves.
sleepParams.set(
"days",
String(Math.max(1, Math.min(3650, Math.ceil(fetchWindow.windowDays)))),
String(
Math.max(1, Math.min(3650, Math.ceil(fetchWindow.windowDays))),
),
);
// v1.16.8 — a failed fetch rejects the whole query instead of
// silently resolving an empty series: the swallowed-catch
@@ -872,9 +874,13 @@ export function HealthChart({
const scaledMin = measurement.minValue * valueScale;
const scaledMax = measurement.maxValue * valueScale;
current.min =
current.min === null ? scaledMin : Math.min(current.min, scaledMin);
current.min === null
? scaledMin
: Math.min(current.min, scaledMin);
current.max =
current.max === null ? scaledMax : Math.max(current.max, scaledMax);
current.max === null
? scaledMax
: Math.max(current.max, scaledMax);
}
bucket.values[type] = current;
dailyAggregates.set(dayKey, bucket);
@@ -1063,20 +1069,20 @@ export function HealthChart({
// recomputes whenever the range tab changes the visible slice, so the
// `<MetricStatStrip>` a sub-page lifts the callback into always reflects the
// same window the chart paints. Skipped in mini mode (no stat strip).
const visibleStatsByType = useMemo<Record<string, MetricWindowStats> | null>(
() => {
if (mini || !chartData?.length) return null;
const out: Record<string, MetricWindowStats> = {};
for (const type of types) {
const stats = computeWindowStats(
chartData.map((point) => point[type] as number | undefined),
);
if (stats.count > 0) out[type] = stats;
}
return Object.keys(out).length > 0 ? out : null;
},
[mini, chartData, types],
);
const visibleStatsByType = useMemo<Record<
string,
MetricWindowStats
> | null>(() => {
if (mini || !chartData?.length) return null;
const out: Record<string, MetricWindowStats> = {};
for (const type of types) {
const stats = computeWindowStats(
chartData.map((point) => point[type] as number | undefined),
);
if (stats.count > 0) out[type] = stats;
}
return Object.keys(out).length > 0 ? out : null;
}, [mini, chartData, types]);
// Report the visible-range stats up to the sub-page so the shared
// `<MetricStatStrip>` can read them. Effect (not render-time call) so the
@@ -1674,10 +1680,7 @@ export function HealthChart({
// positions through the `ticks` prop so the legacy
// day-aware density policy stays effective on the
// pulse chart.
ticks={computeTickPositions(
chartData ?? [],
viewportWidth,
)}
ticks={computeTickPositions(chartData ?? [], viewportWidth)}
padding={{ left: 10, right: 10 }}
tickMargin={10}
/>
@@ -1690,7 +1693,9 @@ export function HealthChart({
domain={yDomain}
tickFormatter={(value) =>
typeof value === "number"
? formatAxisValue(useDecimalAxis ? value : Math.round(value))
? formatAxisValue(
useDecimalAxis ? value : Math.round(value),
)
: String(value)
}
unit={
@@ -246,7 +246,9 @@ export function MedicationComplianceChart({
const { data, isLoading, isError, refetch } = useQuery({
queryKey: queryKeys.dashboardMedicationCompliance(days),
queryFn: async (): Promise<DailyCompliancePoint[]> => {
return apiGet<DailyCompliancePoint[]>(`/api/medications/intake?scope=compliance&days=${days}`);
return apiGet<DailyCompliancePoint[]>(
`/api/medications/intake?scope=compliance&days=${days}`,
);
},
enabled: isAuthenticated,
});
@@ -452,7 +454,7 @@ export function MedicationComplianceChart({
/>
)
) : (
<div className="h-[var(--chart-height,240px)] md:h-[var(--chart-height-md,280px)] touch-pan-y">
<div className="h-[var(--chart-height,240px)] touch-pan-y md:h-[var(--chart-height-md,280px)]">
<ResponsiveContainer width="100%" height="100%">
<ComposedChart
data={chartData}
+19 -6
View File
@@ -207,7 +207,7 @@ export function MoodHeatmap({
<div
className={
stretch
? "w-full sm:w-full overflow-x-auto sm:overflow-visible"
? "w-full overflow-x-auto sm:w-full sm:overflow-visible"
: "overflow-x-auto"
}
>
@@ -218,7 +218,9 @@ export function MoodHeatmap({
// natural, square, left-aligned grid rather than CSS-stretching a few
// capped columns into wide rectangles. Mirrors `compliance-heatmap`.
className={stretch ? "block max-w-full" : "block"}
onMouseLeave={() => setTooltip((prev) => (prev?.pinned ? prev : null))}
onMouseLeave={() =>
setTooltip((prev) => (prev?.pinned ? prev : null))
}
>
{monthMarkers.map((m, i) => (
<text
@@ -254,7 +256,9 @@ export function MoodHeatmap({
if (!cell.cell) {
return `${formatDateDE(cell.dateKey)}: ${t("insights.mood.heatmapNoEntry")}`;
}
const labelKey = moodLabelKeyForScore(Math.round(cell.cell.score));
const labelKey = moodLabelKeyForScore(
Math.round(cell.cell.score),
);
const moodLabel = labelKey ? t(labelKey) : "";
return `${formatDateDE(cell.dateKey)}: ${cell.cell.score.toFixed(1)}${moodLabel ? ` · ${moodLabel}` : ""}`;
};
@@ -310,9 +314,18 @@ export function MoodHeatmap({
style={{ marginLeft: stretch ? 0 : labelWidth }}
>
{[
{ color: "var(--dracula-green)", label: t("insights.mood.legendGreat") },
{ color: "var(--dracula-yellow)", label: t("insights.mood.legendGood") },
{ color: "var(--dracula-orange)", label: t("insights.mood.legendOkay") },
{
color: "var(--dracula-green)",
label: t("insights.mood.legendGreat"),
},
{
color: "var(--dracula-yellow)",
label: t("insights.mood.legendGood"),
},
{
color: "var(--dracula-orange)",
label: t("insights.mood.legendOkay"),
},
{ color: "var(--dracula-red)", label: t("insights.mood.legendLow") },
].map(({ color, label }) => (
<span key={label} className="flex items-center gap-1">
@@ -97,7 +97,7 @@ export function ScatterCorrelationChart<T extends Record<string, number>>({
// shape once layout settles; this floor only prevents the brief
// zero-height window that fires Recharts' width(-1)/height(-1)
// console warning when the chart swaps in after the skeleton.
className="touch-pan-y aspect-square min-h-[180px] sm:aspect-[3/2] sm:h-auto"
className="aspect-square min-h-[180px] touch-pan-y sm:aspect-[3/2] sm:h-auto"
style={{ height: undefined }}
data-explicit-height={height}
>
+40 -44
View File
@@ -134,11 +134,7 @@ export function TrendCard({
// appeared on the same tile because slope30 and trend7Delta could
// legitimately disagree (30-day downward arc, 7-day uptick).
const primarySignal: number | null =
trend7Delta != null
? trend7Delta
: slope30
? slope30.slope * 7
: null;
trend7Delta != null ? trend7Delta : slope30 ? slope30.slope * 7 : null;
const TrendIcon = ((): typeof ArrowUp => {
if (primarySignal == null) return Minus;
@@ -233,51 +229,51 @@ export function TrendCard({
// deterministic height. No unit; the arrow slot below still
// renders its muted placeholder so the row width stays stable.
<span
className="text-muted-foreground min-w-0 truncate text-base font-medium leading-none"
className="text-muted-foreground min-w-0 truncate text-base leading-none font-medium"
data-slot="trend-card-empty-hint"
>
{emptyHint}
</span>
) : (
<>
<span
className={cn(
"shrink-0 whitespace-nowrap font-semibold tracking-tight tabular-nums",
// v1.8.7 — the value NEVER truncates, clips, or wraps
// mid-number. The maintainer is emphatic: every digit of
// the reading must render in full ("130 mmHg" must read as
// "130", never "13" then "3 mmHg"). The headline value span
// is `shrink-0 whitespace-nowrap` so it keeps its full
// intrinsic width and wins the horizontal-space contest
// against the unit. When the strip is dense (many tiles →
// narrow column) the UNIT yields — it shrinks (`min-w-0
// truncate`) and may ellipsis — rather than losing any
// digit of the number. The earlier `min-w-0 truncate` on
// this span was the bug: it let the value shrink below its
// content width and clip the number.
//
// v1.4.49.4 — paired values (BP systolic/diastolic) render
// as `131/85` and outgrow the `text-3xl` footprint on the
// narrowest grid columns. Paired tiles drop one font step
// (text-3xl → text-2xl) so the full pair fits; single-value
// tiles (weight, pulse, glucose, …) keep text-3xl.
secondary ? "text-2xl" : "text-3xl",
// `leading-none` must come AFTER the font-size class in the
// cn() arg list. Tailwind v4 `text-3xl` / `text-2xl` ship
// their own default `line-height`, so `twMerge` would
// otherwise drop the explicit `leading-none` per the
// last-wins rule and break the W20a across-tile baseline
// alignment (digits line up at the same y-coordinate
// across every tile in the strip).
"leading-none",
)}
data-slot="trend-card-value"
>
{latest !== null ? renderPair(latest, secondary?.latest) : "—"}
</span>
<span className="text-muted-foreground min-w-0 truncate text-sm tabular-nums">
{unit}
</span>
<span
className={cn(
"shrink-0 font-semibold tracking-tight whitespace-nowrap tabular-nums",
// v1.8.7 — the value NEVER truncates, clips, or wraps
// mid-number. The maintainer is emphatic: every digit of
// the reading must render in full ("130 mmHg" must read as
// "130", never "13" then "3 mmHg"). The headline value span
// is `shrink-0 whitespace-nowrap` so it keeps its full
// intrinsic width and wins the horizontal-space contest
// against the unit. When the strip is dense (many tiles →
// narrow column) the UNIT yields — it shrinks (`min-w-0
// truncate`) and may ellipsis — rather than losing any
// digit of the number. The earlier `min-w-0 truncate` on
// this span was the bug: it let the value shrink below its
// content width and clip the number.
//
// v1.4.49.4 — paired values (BP systolic/diastolic) render
// as `131/85` and outgrow the `text-3xl` footprint on the
// narrowest grid columns. Paired tiles drop one font step
// (text-3xl → text-2xl) so the full pair fits; single-value
// tiles (weight, pulse, glucose, …) keep text-3xl.
secondary ? "text-2xl" : "text-3xl",
// `leading-none` must come AFTER the font-size class in the
// cn() arg list. Tailwind v4 `text-3xl` / `text-2xl` ship
// their own default `line-height`, so `twMerge` would
// otherwise drop the explicit `leading-none` per the
// last-wins rule and break the W20a across-tile baseline
// alignment (digits line up at the same y-coordinate
// across every tile in the strip).
"leading-none",
)}
data-slot="trend-card-value"
>
{latest !== null ? renderPair(latest, secondary?.latest) : "—"}
</span>
<span className="text-muted-foreground min-w-0 truncate text-sm tabular-nums">
{unit}
</span>
</>
)}
<span