import { useState, useEffect } from 'react'; import { Title, Text, Card, Stack, Group, SimpleGrid, Badge, ThemeIcon, Divider, Tabs, Button, Switch, Loader, } from '@mantine/core'; import { IconBuilding, IconUser, IconSettings, IconShieldLock, IconFingerprint, IconLink, IconLogout, IconCreditCard, } from '@tabler/icons-react'; import { notifications } from '@mantine/notifications'; import { useAuthStore } from '../../stores/authStore'; import { usePreferencesStore } from '../../stores/preferencesStore'; import { MfaSettings } from './MfaSettings'; import { PasskeySettings } from './PasskeySettings'; import { LinkedAccounts } from './LinkedAccounts'; import api from '../../services/api'; interface SubscriptionInfo { plan: string; planName: string; billingInterval: string; status: string; collectionMethod: string; trialEndsAt: string | null; currentPeriodEnd: string | null; cancelAtPeriodEnd: boolean; } const statusColors: Record = { active: 'green', trial: 'blue', past_due: 'orange', archived: 'red', suspended: 'red', }; export function SettingsPage() { const { user, currentOrg } = useAuthStore(); const { compactView, toggleCompactView } = usePreferencesStore(); const [loggingOutAll, setLoggingOutAll] = useState(false); const [subscription, setSubscription] = useState(null); const [subLoading, setSubLoading] = useState(true); const [portalLoading, setPortalLoading] = useState(false); useEffect(() => { api.get('/billing/subscription') .then(({ data }) => setSubscription(data)) .catch(() => { /* billing not configured or no subscription */ }) .finally(() => setSubLoading(false)); }, []); const handleLogoutEverywhere = async () => { setLoggingOutAll(true); try { await api.post('/auth/logout-everywhere'); notifications.show({ message: 'All other sessions have been logged out', color: 'green' }); } catch { notifications.show({ message: 'Failed to log out other sessions', color: 'red' }); } finally { setLoggingOutAll(false); } }; const handleManageBilling = async () => { setPortalLoading(true); try { const { data } = await api.post('/billing/portal'); if (data.url) { window.location.href = data.url; } } catch { notifications.show({ message: 'Unable to open billing portal', color: 'red' }); } finally { setPortalLoading(false); } }; const formatInterval = (interval: string) => { return interval === 'year' ? 'Annual' : 'Monthly'; }; const formatDate = (iso: string | null) => { if (!iso) return null; return new Date(iso).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', }); }; return (
Settings Organization and account settings
{/* Organization Info */}
Organization Current organization details
Name {currentOrg?.name || 'N/A'} Your Role {currentOrg?.role || 'N/A'}
{/* Billing / Subscription */}
Billing Subscription and payment
{subLoading ? ( ) : subscription ? ( Plan {subscription.planName} {formatInterval(subscription.billingInterval)} Status {subscription.status === 'past_due' ? 'Past Due' : subscription.status} {subscription.cancelAtPeriodEnd ? ' (Canceling)' : ''} {subscription.trialEndsAt && subscription.status === 'trial' && ( Trial Ends {formatDate(subscription.trialEndsAt)} )} {subscription.currentPeriodEnd && subscription.status !== 'trial' && ( Current Period Ends {formatDate(subscription.currentPeriodEnd)} )} {subscription.collectionMethod === 'send_invoice' && ( Payment Invoice / ACH )} ) : ( No active subscription )}
{/* User Profile */}
Your Profile Account information
Name {user?.firstName} {user?.lastName} Email {user?.email} User ID {user?.id?.slice(0, 8)}...
{/* System Info */}
System Platform information
Platform HOA LedgerIQ Version 2026.03.18 API /api/docs
Compact View Reduce spacing in tables and lists
{/* Sessions */}
Sessions Manage active sessions
Current Session Active
{/* Security Settings */}
Security Manage authentication methods and security settings
}> Two-Factor Auth }> Passkeys }> Linked Accounts
); }