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

@@ -147,8 +147,6 @@ describe("Settings — DisableCoachCard", () => {
const html = render();
// v1.18.1 (D7) — polarity flipped to activate/default-on.
expect(html).toContain("Activate Coach");
expect(html).toContain(
"Show the Coach button and drawer. On by default",
);
expect(html).toContain("Show the Coach button and drawer. On by default");
});
});
@@ -7,10 +7,7 @@
*/
import { describe, it, expect } from "vitest";
import {
parseOAuthOutcome,
oauthReasonKey,
} from "../integrations-section";
import { parseOAuthOutcome, oauthReasonKey } from "../integrations-section";
describe("parseOAuthOutcome", () => {
it("reads a connected outcome for every OAuth provider", () => {
+3 -9
View File
@@ -140,9 +140,7 @@ function ResearchModeCard() {
}
return (
<SettingsCard
data-slot="settings-research-mode-card"
>
<SettingsCard data-slot="settings-research-mode-card">
<SettingsCardHeader
icon={BookOpenCheck}
title={t("settings.researchMode.sectionTitle")}
@@ -254,9 +252,7 @@ function DataResetCard() {
}
return (
<SettingsCard
data-slot="settings-data-reset-card"
>
<SettingsCard data-slot="settings-data-reset-card">
{/* v1.4.43 QoL (L5) — dropped the `AlertTriangle` icon and
neutralised the title colour so the danger-zone shaping is
GitHub-style (red CTA only) rather than red-on-red-on-red.
@@ -401,9 +397,7 @@ function AccountDeleteCard() {
}
return (
<SettingsCard
data-slot="settings-account-delete-card"
>
<SettingsCard data-slot="settings-account-delete-card">
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between sm:gap-2">
<div className="space-y-1">
<h2 className="text-foreground text-lg font-semibold">
@@ -95,7 +95,9 @@ export function DisableCoachCard({
// the activated-state view of it. The SSR default is ON (checked) so the
// default-on contract holds before the wire value resolves.
const mounted = useMounted();
const activated = mounted ? (optimistic ?? !(user?.disableCoach ?? false)) : true;
const activated = mounted
? (optimistic ?? !(user?.disableCoach ?? false))
: true;
const mutation = useMutation({
// `next` is the desired ACTIVATED state; the column stores the inverse.
@@ -250,11 +250,7 @@ export function FallbackChainCard({
</Button>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
size="sm"
variant="outline"
className="min-h-11 sm:min-h-9"
>
<Button size="sm" variant="outline" className="min-h-11 sm:min-h-9">
<RotateCcw className="h-4 w-4" />
{t("settings.ai.providerChain.resetDefaults")}
</Button>
@@ -107,9 +107,7 @@ export function CoachPrefsSection({ isAuthenticated }: CoachPrefsSectionProps) {
const isLoading = isAuthenticated && !persisted;
return (
<SettingsCard
data-slot="coach-prefs-section"
>
<SettingsCard data-slot="coach-prefs-section">
<SettingsCardHeader
icon={SlidersHorizontal}
title={t("insights.coach.settingsTitle")}
@@ -317,10 +317,7 @@ export function DashboardLayoutSection({ id }: { id: string }) {
const dirty = draft !== null && layout !== null;
return (
<SettingsCard
id={id}
className="scroll-mt-28 space-y-4"
>
<SettingsCard id={id} className="scroll-mt-28 space-y-4">
{/* v1.4.19 A6 — title / action row uses the same stack-on-mobile,
right-align-on-desktop contract as Account → Password +
Restart onboarding tour. Avoids the long German "Auf Standard
+5 -1
View File
@@ -129,7 +129,11 @@ export function EmailCard({ isAuthenticated }: { isAuthenticated: boolean }) {
endpoint="/api/settings/email/test"
disabled={!settings?.enabled}
/>
<Button type="submit" disabled={save.isPending} className="min-h-11">
<Button
type="submit"
disabled={save.isPending}
className="min-h-11"
>
{save.isPending && (
<Loader2 className="h-3.5 w-3.5 animate-spin motion-reduce:animate-none" />
)}
+10 -10
View File
@@ -103,10 +103,7 @@ function ImportCardShell({
children,
}: ImportCardShellProps) {
return (
<SettingsCard
data-testid={testId}
className="flex h-full flex-col"
>
<SettingsCard data-testid={testId} className="flex h-full flex-col">
<div className="flex items-center gap-2">
<Icon
className="text-muted-foreground h-5 w-5 shrink-0"
@@ -727,12 +724,15 @@ function CsvImportCard() {
}
setBusy(true);
try {
const res = await apiFetchRaw(`/api/import/csv${dryRun ? "?dryRun=1" : ""}`, {
method: "POST",
headers: { "Content-Type": "text/csv" },
credentials: "include",
body: text,
});
const res = await apiFetchRaw(
`/api/import/csv${dryRun ? "?dryRun=1" : ""}`,
{
method: "POST",
headers: { "Content-Type": "text/csv" },
credentials: "include",
body: text,
},
);
if (res.status === 429) {
setError(t("settings.sections.export.import.csv.rateLimited"));
return;
@@ -106,7 +106,11 @@ export function parseOAuthOutcome(search: string): OAuthOutcome | null {
const v = params.get(provider);
if (v === "connected") return { provider, kind: "connected" };
if (v === "error") {
return { provider, kind: "error", reason: params.get("reason") ?? "unknown" };
return {
provider,
kind: "error",
reason: params.get("reason") ?? "unknown",
};
}
}
return null;
@@ -218,7 +222,9 @@ export function ConnectionsPanel() {
toast.success(t(`settings.${provider}OauthConnected`));
// Polar/Oura own a per-card status query; WHOOP/Fitbit read off the
// consolidated envelope — invalidate both so the card repaints either way.
queryClient.invalidateQueries({ queryKey: OAUTH_OUTCOME_KEYS[provider]() });
queryClient.invalidateQueries({
queryKey: OAUTH_OUTCOME_KEYS[provider](),
});
queryClient.invalidateQueries({
queryKey: queryKeys.integrationsStatus(),
});
@@ -189,9 +189,7 @@ export function FitbitCard({
: null;
return (
<SettingsCard
data-testid="fitbit-card"
>
<SettingsCard data-testid="fitbit-card">
<SettingsCardHeader
icon={HeartPulse}
title={t("settings.fitbit")}
@@ -10,7 +10,14 @@
import { useRef, useState } from "react";
import Link from "next/link";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { ArrowRight, Droplet, Link2, Loader2, Save, Unlink } from "lucide-react";
import {
ArrowRight,
Droplet,
Link2,
Loader2,
Save,
Unlink,
} from "lucide-react";
import {
AlertDialog,
@@ -37,7 +44,11 @@ import {
import { TestConnectionButton } from "@/components/settings/test-connection-button";
import { apiFetchRaw, apiGet, apiPost } from "@/lib/api/api-fetch";
import { useTranslations } from "@/lib/i18n/context";
import { invalidateKeys, measurementDependentKeys, queryKeys } from "@/lib/query-keys";
import {
invalidateKeys,
measurementDependentKeys,
queryKeys,
} from "@/lib/query-keys";
import { IntegrationErrorMessage } from "./shared";
import { IntegrationCardDescription } from "./setup-guide-link";
@@ -47,14 +58,21 @@ interface NightscoutStatus {
configured: boolean;
hasToken?: boolean;
allowPrivateHost?: boolean;
state?: "connected" | "error_transient" | "error_reauth" | "disconnected" | "parked";
state?:
| "connected"
| "error_transient"
| "error_reauth"
| "disconnected"
| "parked";
lastSuccessAt?: string | null;
lastAttemptAt?: string | null;
lastError?: string | null;
}
/** Map the shared ledger state onto the pill's display state. */
function pillStateFor(status: NightscoutStatus | undefined): IntegrationPillState {
function pillStateFor(
status: NightscoutStatus | undefined,
): IntegrationPillState {
if (!status?.connected) return "disconnected";
switch (status.state) {
case "parked":
@@ -159,9 +177,7 @@ export function NightscoutCard({ enabled = true }: { enabled?: boolean }) {
: null;
return (
<SettingsCard
data-testid="nightscout-card"
>
<SettingsCard data-testid="nightscout-card">
<SettingsCardHeader
icon={Droplet}
title={t("settings.nightscout")}
@@ -226,7 +242,9 @@ export function NightscoutCard({ enabled = true }: { enabled?: boolean }) {
<form ref={formRef} onSubmit={handleConnect} className="space-y-3">
<div className="space-y-1.5">
<Label htmlFor="nightscout-url">{t("settings.nightscoutUrl")}</Label>
<Label htmlFor="nightscout-url">
{t("settings.nightscoutUrl")}
</Label>
<Input
id="nightscout-url"
type="url"
@@ -11,7 +11,14 @@
import { useState } from "react";
import Link from "next/link";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { ArrowRight, Link2, Loader2, Save, Unlink, type LucideIcon } from "lucide-react";
import {
ArrowRight,
Link2,
Loader2,
Save,
Unlink,
type LucideIcon,
} from "lucide-react";
import {
AlertDialog,
@@ -64,7 +71,9 @@ export interface OAuthProviderStatus {
lastError?: string | null;
}
function pillStateFor(status: OAuthProviderStatus | undefined): IntegrationPillState {
function pillStateFor(
status: OAuthProviderStatus | undefined,
): IntegrationPillState {
if (!status?.connected) return "disconnected";
switch (status.state) {
case "parked":
@@ -202,9 +211,7 @@ export function OAuthProviderCard({
}
return (
<SettingsCard
data-testid={`${provider}-card`}
>
<SettingsCard data-testid={`${provider}-card`}>
<SettingsCardHeader
icon={icon}
title={t(`${i18nPrefix}`)}
@@ -20,8 +20,7 @@ import { useTranslations } from "@/lib/i18n/context";
* path segment, e.g. `https://docs.healthlog.dev/integrations/whoop`. Kept as
* a single constant so the host never drifts across cards.
*/
export const INTEGRATION_DOCS_BASE =
"https://docs.healthlog.dev/integrations";
export const INTEGRATION_DOCS_BASE = "https://docs.healthlog.dev/integrations";
export type IntegrationDocsProvider =
| "whoop"
+2 -1
View File
@@ -101,7 +101,8 @@ export function LowStockCard({
prefs?.medication?.reorderLeadDays === undefined
? DEFAULT_LEAD
: prefs.medication.reorderLeadDays;
const leadDays = leadOptimistic === undefined ? persistedLead : leadOptimistic;
const leadDays =
leadOptimistic === undefined ? persistedLead : leadOptimistic;
async function patchPrefs(
body: Record<string, unknown>,
@@ -80,10 +80,7 @@ export function MedicationsSection() {
<div className="space-y-6">
{/* View preference — cards vs table. The shared header toggle
writes optimistically, so there is no Save button here. */}
<SettingsCard
id="medications-view"
className="scroll-mt-28 space-y-4"
>
<SettingsCard id="medications-view" className="scroll-mt-28 space-y-4">
<SettingsCardHeader
icon={LayoutGrid}
title={t("medications.viewToggleLabel")}
@@ -101,10 +98,7 @@ export function MedicationsSection() {
</SettingsCard>
{/* Manual order — applies to both list views. */}
<SettingsCard
id="medications-order"
className="scroll-mt-28 space-y-4"
>
<SettingsCard id="medications-order" className="scroll-mt-28 space-y-4">
<SettingsCardHeader
icon={Pill}
title={t("medications.reorderTitle")}
@@ -156,10 +156,7 @@ export function MoodReminderCard({
}
return (
<SettingsCard
as="section"
aria-labelledby="settings-mood-reminder-title"
>
<SettingsCard as="section" aria-labelledby="settings-mood-reminder-title">
<SettingsCardHeader
icon={SmilePlus}
title={t("notifications.moodReminder.title")}
+3 -12
View File
@@ -46,10 +46,7 @@ export function MoodSection() {
return (
<div className="space-y-6">
{/* Groups — picker group order + own groups. */}
<SettingsCard
id="mood-groups"
className="scroll-mt-28 space-y-4"
>
<SettingsCard id="mood-groups" className="scroll-mt-28 space-y-4">
<SettingsCardHeader
icon={Folders}
title={t("mood.manage.groupsTitle")}
@@ -58,19 +55,13 @@ export function MoodSection() {
</SettingsCard>
{/* Tags — visibility, order, edit, move, create. */}
<SettingsCard
id="mood-tags"
className="scroll-mt-28 space-y-4"
>
<SettingsCard id="mood-tags" className="scroll-mt-28 space-y-4">
<SettingsCardHeader icon={Tags} title={t("mood.manage.tagsTitle")} />
{isLoading || !catalog ? loading : <TagManagerCard catalog={catalog} />}
</SettingsCard>
{/* Archived custom tags — restore / hard delete. */}
<SettingsCard
id="mood-archived"
className="scroll-mt-28 space-y-4"
>
<SettingsCard id="mood-archived" className="scroll-mt-28 space-y-4">
<SettingsCardHeader
icon={Archive}
title={t("mood.manage.archivedTitle")}
@@ -129,9 +129,7 @@ export function NotificationStatusCard() {
const channels = Array.isArray(data) ? data : [];
if (channels.length === 0) {
return (
<SettingsCard
data-testid="notification-status-empty"
>
<SettingsCard data-testid="notification-status-empty">
<SettingsCardHeader
icon={Bell}
title={t("settings.notificationStatus.title")}
@@ -59,8 +59,7 @@ interface SettingsSectionFrameSlugProps extends SettingsSectionFrameBaseProps {
* an optional heading id. This lets `ModuleSettingsFrame` delegate here so
* every settings page shares one heading frame.
*/
interface SettingsSectionFrameExplicitProps
extends SettingsSectionFrameBaseProps {
interface SettingsSectionFrameExplicitProps extends SettingsSectionFrameBaseProps {
title: string;
subtitle: string;
/** Heading element id (defaults to a stable slug-less id). */
+3 -1
View File
@@ -430,7 +430,9 @@ export function SettingsShell({
{/* v1.18.6.1 — on mobile the heading sits above the chip strip; on
desktop it is rendered inside the grid (row 1 / content column) so
it does not paint twice. */}
{headingBlock ? <div className="mb-4 md:hidden">{headingBlock}</div> : null}
{headingBlock ? (
<div className="mb-4 md:hidden">{headingBlock}</div>
) : null}
{/* Mobile section strip — horizontal scroll, hidden on md+.
`no-scrollbar` (defined in `globals.css`) suppresses the
+1 -3
View File
@@ -270,9 +270,7 @@ function ShareLinksCard() {
</p>
</div>
<div className="space-y-1.5">
<Label htmlFor="share-expiry">
{t("settings.sharing.expiry")}
</Label>
<Label htmlFor="share-expiry">{t("settings.sharing.expiry")}</Label>
<Input
id="share-expiry"
type="number"
@@ -116,10 +116,7 @@ export function ThresholdsEditorSection({ id }: { id: string }) {
});
return (
<SettingsCard
id={id}
className="scroll-mt-28 space-y-4"
>
<SettingsCard id={id} className="scroll-mt-28 space-y-4">
{/* v1.4.19 A8 / F-07: page header `settings.sections.thresholds.*`
already provides the title + description for this route, so the
card-level title + subtitle were a duplicate of the page header.
+8 -2
View File
@@ -43,7 +43,9 @@ export function WebhookCard({ isAuthenticated }: { isAuthenticated: boolean }) {
});
// React-recommended sync-from-server pattern (no setState-in-effect).
const settingsKey = settings ? `${settings.url}|${settings.headerName}` : null;
const settingsKey = settings
? `${settings.url}|${settings.headerName}`
: null;
const [seededKey, setSeededKey] = useState<string | null>(null);
if (settingsKey && settingsKey !== seededKey) {
setSeededKey(settingsKey);
@@ -161,7 +163,11 @@ export function WebhookCard({ isAuthenticated }: { isAuthenticated: boolean }) {
endpoint="/api/settings/webhook/test"
disabled={!settings?.enabled}
/>
<Button type="submit" disabled={save.isPending} className="min-h-11">
<Button
type="submit"
disabled={save.isPending}
className="min-h-11"
>
{save.isPending && (
<Loader2 className="h-3.5 w-3.5 animate-spin motion-reduce:animate-none" />
)}