diff --git a/client/components/admin/OnboardingWizard.tsx b/client/components/admin/OnboardingWizard.tsx index a870e42..63cedd0 100644 --- a/client/components/admin/OnboardingWizard.tsx +++ b/client/components/admin/OnboardingWizard.tsx @@ -1,5 +1,5 @@ -import { useState } from 'react'; -import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { useState, type ComponentType, type ReactNode } from 'react'; +import { Check, ChevronLeft, ChevronRight, KeyRound, LockKeyhole, Settings2, ShieldCheck, UserPlus, X } from 'lucide-react'; import { toast } from 'sonner'; import { api } from '@/api'; import { errMessage } from '@/lib/utils'; @@ -7,6 +7,30 @@ import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'; +import { BRAND } from '@/lib/brand'; +import { BrandGlyph, BrandMark } from '@/components/brand/Brand'; + +function PromiseItem({ + icon: Icon, + title, + children, +}: { + icon: ComponentType<{ className?: string }>; + title: string; + children: ReactNode; +}) { + return ( +
+ + +
+

{title}

+

{children}

+
+
+ ); +} export default function OnboardingWizard({ onComplete }: { onComplete: () => void }) { const [step, setStep] = useState(0); @@ -48,24 +72,54 @@ export default function OnboardingWizard({ onComplete }: { onComplete: () => voi }; return ( -
-
-
- {[0, 1].map(i => ( - - ))} -
+
+
+
+
+ +

+ Set up {BRAND.name} with a clean privacy line. +

+

+ The first admin keeps the app healthy. The first user owns the money data. Those roles stay separate from the start. +

+
+ +
+ + Create accounts, reset passwords, notification plumbing, and login mode settings. + + + Admin tools do not expose bills, payments, spending history, or personal settings. + + + A restrained setup flow that matches the tracker, settings, and security surfaces. + +
+
+ +
+
+ {[0, 1].map(i => ( + + ))} +
{step === 0 && ( - + - Welcome, Administrator -

- Before creating your first user, please understand what your admin account can and cannot do. -

+
+ +
+ Welcome, Administrator +

+ Before creating your first user, review the admin boundary. +

+
+
@@ -78,8 +132,8 @@ export default function OnboardingWizard({ onComplete }: { onComplete: () => voi { can: false, text: 'Cannot access user settings or history' }, ].map(({ can, text }) => (
- - {can ? '✓' : '✗'} + + {can ? {text}
@@ -87,7 +141,7 @@ export default function OnboardingWizard({ onComplete }: { onComplete: () => voi
@@ -96,12 +150,17 @@ export default function OnboardingWizard({ onComplete }: { onComplete: () => voi )} {step === 1 && ( - + - Create first user -

- This account will be used to access the bill tracker. -

+
+ +
+ Create first user +

+ This account will own the tracker, bills, and personal settings. +

+
+
@@ -148,13 +207,23 @@ export default function OnboardingWizard({ onComplete }: { onComplete: () => voi Back
+
+
)} +
); diff --git a/client/pages/LoginPage.tsx b/client/pages/LoginPage.tsx index bd7ed5a..c01a87a 100644 --- a/client/pages/LoginPage.tsx +++ b/client/pages/LoginPage.tsx @@ -1,5 +1,6 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, type ComponentType, type ReactNode } from 'react'; import { Link, useNavigate, useLocation } from 'react-router-dom'; +import { Gauge, KeyRound, LockKeyhole, ShieldCheck } from 'lucide-react'; import { toast } from 'sonner'; import { api } from '@/api'; import { errMessage } from '@/lib/utils'; @@ -9,7 +10,7 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { APP_VERSION } from '@/lib/version'; import { BRAND } from '@/lib/brand'; -import { BrandMark } from '@/components/brand/Brand'; +import { BrandGlyph, BrandMark } from '@/components/brand/Brand'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '@/components/ui/dialog'; @@ -28,6 +29,28 @@ const LANDING_ROUTES: Record = { tracker: '/', calendar: '/calendar', summary: '/summary', spending: '/spending', }; +function TrustItem({ + icon: Icon, + title, + children, +}: { + icon: ComponentType<{ className?: string }>; + title: string; + children: ReactNode; +}) { + return ( +
+ + +
+

{title}

+

{children}

+
+
+ ); +} + export default function LoginPage() { const navigate = useNavigate(); const location = useLocation(); @@ -193,12 +216,35 @@ export default function LoginPage() { }; return ( -
+
+
+
+
+
+ +

+ {BRAND.tagline} Built for fast bill scanning, clear household decisions, and private defaults. +

+
-
+
+ + Admins can manage access, but they cannot inspect personal bills or spending history. + + + Dense tracker views, tabular money, and calm status cues stay front and center. + + + Local login, SSO, and two-factor flows share one clean entry point. + +
+
+
+ +
{/* Logo / Brand */} -
+

{BRAND.tagline} @@ -208,11 +254,14 @@ export default function LoginPage() { {/* TOTP step — shown after password is accepted */} {totpChallenge && (

-
-

Two-factor authentication

-

- {useRecovery ? 'Enter one of your recovery codes.' : 'Enter the 6-digit code from your authenticator app.'} -

+
+ +
+

Two-factor authentication

+

+ {useRecovery ? 'Enter one of your recovery codes.' : 'Enter the 6-digit code from your authenticator app.'} +

+
@@ -272,6 +321,10 @@ export default function LoginPage() {
+
+

Sign in

{localEnabled ? 'Enter your credentials to continue.' : `Continue with ${providerName}.`} @@ -369,15 +422,21 @@ export default function LoginPage() {

))} {/* end !totpChallenge + authMode check */}
+
{/* Change Password Dialog */} e.preventDefault()}> - Change your password - - You must set a new password before continuing. - +
+ +
+ Change your password + + Set a new password before continuing. + +
+
@@ -416,26 +475,31 @@ export default function LoginPage() { e.preventDefault()}> - Privacy notice - - Please read before continuing. - +
+ +
+ Privacy notice + + A quick boundary check before your first session. + +
+

Your financial data is stored privately and is accessible only to you.

-
+

What your administrator can do:

  • - +
  • - +
diff --git a/client/pages/SettingsPage.tsx b/client/pages/SettingsPage.tsx index ee330e3..5ca30f6 100644 --- a/client/pages/SettingsPage.tsx +++ b/client/pages/SettingsPage.tsx @@ -143,7 +143,7 @@ function AppearanceSection() { label={Theme} description="Choose your preferred color scheme." > -
+
diff --git a/e2e/smoke.spec.js-snapshots/login-chromium-desktop-linux.png b/e2e/smoke.spec.js-snapshots/login-chromium-desktop-linux.png index 68ca334..42dda35 100644 Binary files a/e2e/smoke.spec.js-snapshots/login-chromium-desktop-linux.png and b/e2e/smoke.spec.js-snapshots/login-chromium-desktop-linux.png differ diff --git a/e2e/smoke.spec.js-snapshots/login-chromium-mobile-linux.png b/e2e/smoke.spec.js-snapshots/login-chromium-mobile-linux.png index a0ee201..f2d684e 100644 Binary files a/e2e/smoke.spec.js-snapshots/login-chromium-mobile-linux.png and b/e2e/smoke.spec.js-snapshots/login-chromium-mobile-linux.png differ