mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 14:32:03 +00:00
Replace the SectionPlaceholder fallbacks for Account, AI, Integrations, Notifications, Dashboard, API, Advanced, and About with real per-section components. Every /settings/<slug> URL now renders working content; the placeholder only fires for unknown slugs. A2-content extraction - Account: profile + passkeys + password change (account-section.tsx) - AI: insights + per-user provider override (ai-section.tsx) - Integrations: Withings + moodLog (integrations-section.tsx) - Notifications: Telegram + ntfy + Web Push (split into telegram-card, ntfy-card, web-push-card to keep each file under ~600 LOC) - Dashboard: layout + thresholds wrappers (dashboard-section.tsx) - API: endpoints + tokens (api-section.tsx) - Advanced: export + danger zone (advanced-section.tsx) - About (greenfield): version, license, build SHA, repo/changelog/docs links + "Check for updates" against GitHub releases A2-about - Reads /api/version via TanStack Query, surfaces app version, AGPL-3.0 badge, short build SHA, build timestamp, repo/changelog/docs links. - "Check for updates" button compares against api.github.com latest release tag with up-to-date / newer-available / failure feedback. A8-UI test buttons - Shared TestConnectionButton primitive that POSTs to a test endpoint, surfaces ok-with-latency or translated meta.errorCode failures. - Wired into Withings + moodLog (Integrations) and Web Push (Notifications). Glitchtip + Umami remain admin-only. i18n - New settings.about.* and settings.testConnection.* key groups in en.json and de.json. Cleanup - Delete src/app/settings/page.legacy.tsx (3230 LOC monolith). - Convert sync-from-server patterns to the React-recommended prev-payload-id render-time pattern so the strict react-hooks/set-state-in-effect rule passes without a file-level disable. Tests - New src/components/settings/__tests__/sections.test.tsx with 9 SSR smoke tests (one per section) — total suite 514 (was 505).
30 lines
1008 B
TypeScript
30 lines
1008 B
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { Eye, EyeOff } from "lucide-react";
|
|
|
|
import { Input } from "@/components/ui/input";
|
|
|
|
/**
|
|
* Password input with a built-in show/hide toggle. Extracted from the legacy
|
|
* settings monolith so every section that needs a masked secret (Withings,
|
|
* moodLog, ntfy, Telegram, AI provider keys, account password) can share the
|
|
* same UX without duplicating the visibility-toggle plumbing.
|
|
*/
|
|
export function PasswordInput(props: React.ComponentProps<typeof Input>) {
|
|
const [visible, setVisible] = useState(false);
|
|
return (
|
|
<div className="relative">
|
|
<Input {...props} type={visible ? "text" : "password"} />
|
|
<button
|
|
type="button"
|
|
tabIndex={-1}
|
|
onClick={() => setVisible((v) => !v)}
|
|
className="text-muted-foreground hover:text-foreground absolute top-1/2 right-3 -translate-y-1/2"
|
|
>
|
|
{visible ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|