- Remove redundant Settings link from sidebar (accessible via user menu) - Move Transactions section below Board Reference for better grouping - Promote Investment Scenarios to its own top-level sidebar item - Add Compact View preference with tighter spacing theme - Wire compact theme into MantineProvider with dynamic switching - Enable Compact View toggle in both Preferences and Settings pages - Install missing @simplewebauthn/browser package (lock file update) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
195 lines
6.7 KiB
TypeScript
195 lines
6.7 KiB
TypeScript
import { useState } from 'react';
|
|
import {
|
|
Title, Text, Card, Stack, Group, SimpleGrid, Badge, ThemeIcon, Divider,
|
|
Tabs, Button, Switch,
|
|
} from '@mantine/core';
|
|
import {
|
|
IconBuilding, IconUser, IconSettings, IconShieldLock,
|
|
IconFingerprint, IconLink, IconLogout,
|
|
} 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';
|
|
|
|
export function SettingsPage() {
|
|
const { user, currentOrg } = useAuthStore();
|
|
const { compactView, toggleCompactView } = usePreferencesStore();
|
|
const [loggingOutAll, setLoggingOutAll] = useState(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);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Stack>
|
|
<div>
|
|
<Title order={2}>Settings</Title>
|
|
<Text c="dimmed" size="sm">Organization and account settings</Text>
|
|
</div>
|
|
|
|
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
|
{/* Organization Info */}
|
|
<Card withBorder padding="lg">
|
|
<Group mb="md">
|
|
<ThemeIcon color="blue" variant="light" size={40} radius="md">
|
|
<IconBuilding size={24} />
|
|
</ThemeIcon>
|
|
<div>
|
|
<Text fw={600} size="lg">Organization</Text>
|
|
<Text c="dimmed" size="sm">Current organization details</Text>
|
|
</div>
|
|
</Group>
|
|
<Stack gap="xs">
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">Name</Text>
|
|
<Text size="sm" fw={500}>{currentOrg?.name || 'N/A'}</Text>
|
|
</Group>
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">Your Role</Text>
|
|
<Badge variant="light">{currentOrg?.role || 'N/A'}</Badge>
|
|
</Group>
|
|
</Stack>
|
|
</Card>
|
|
|
|
{/* User Profile */}
|
|
<Card withBorder padding="lg">
|
|
<Group mb="md">
|
|
<ThemeIcon color="green" variant="light" size={40} radius="md">
|
|
<IconUser size={24} />
|
|
</ThemeIcon>
|
|
<div>
|
|
<Text fw={600} size="lg">Your Profile</Text>
|
|
<Text c="dimmed" size="sm">Account information</Text>
|
|
</div>
|
|
</Group>
|
|
<Stack gap="xs">
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">Name</Text>
|
|
<Text size="sm" fw={500}>{user?.firstName} {user?.lastName}</Text>
|
|
</Group>
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">Email</Text>
|
|
<Text size="sm" fw={500}>{user?.email}</Text>
|
|
</Group>
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">User ID</Text>
|
|
<Text size="sm" ff="monospace" c="dimmed">{user?.id?.slice(0, 8)}...</Text>
|
|
</Group>
|
|
</Stack>
|
|
</Card>
|
|
|
|
{/* System Info */}
|
|
<Card withBorder padding="lg">
|
|
<Group mb="md">
|
|
<ThemeIcon color="violet" variant="light" size={40} radius="md">
|
|
<IconSettings size={24} />
|
|
</ThemeIcon>
|
|
<div>
|
|
<Text fw={600} size="lg">System</Text>
|
|
<Text c="dimmed" size="sm">Platform information</Text>
|
|
</div>
|
|
</Group>
|
|
<Stack gap="xs">
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">Platform</Text>
|
|
<Text size="sm" fw={500}>HOA LedgerIQ</Text>
|
|
</Group>
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">Version</Text>
|
|
<Badge variant="light">2026.03.17</Badge>
|
|
</Group>
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">API</Text>
|
|
<Text size="sm" ff="monospace" c="dimmed">/api/docs</Text>
|
|
</Group>
|
|
<Divider />
|
|
<Group justify="space-between">
|
|
<div>
|
|
<Text size="sm">Compact View</Text>
|
|
<Text size="xs" c="dimmed">Reduce spacing in tables and lists</Text>
|
|
</div>
|
|
<Switch checked={compactView} onChange={toggleCompactView} />
|
|
</Group>
|
|
</Stack>
|
|
</Card>
|
|
|
|
{/* Sessions */}
|
|
<Card withBorder padding="lg">
|
|
<Group mb="md">
|
|
<ThemeIcon color="orange" variant="light" size={40} radius="md">
|
|
<IconLogout size={24} />
|
|
</ThemeIcon>
|
|
<div>
|
|
<Text fw={600} size="lg">Sessions</Text>
|
|
<Text c="dimmed" size="sm">Manage active sessions</Text>
|
|
</div>
|
|
</Group>
|
|
<Stack gap="xs">
|
|
<Group justify="space-between">
|
|
<Text size="sm" c="dimmed">Current Session</Text>
|
|
<Badge color="green" variant="light">Active</Badge>
|
|
</Group>
|
|
<Button
|
|
variant="light"
|
|
color="orange"
|
|
size="sm"
|
|
leftSection={<IconLogout size={16} />}
|
|
onClick={handleLogoutEverywhere}
|
|
loading={loggingOutAll}
|
|
mt="xs"
|
|
>
|
|
Log Out All Other Sessions
|
|
</Button>
|
|
</Stack>
|
|
</Card>
|
|
</SimpleGrid>
|
|
|
|
<Divider my="md" />
|
|
|
|
{/* Security Settings */}
|
|
<div>
|
|
<Title order={3} mb="sm">Security</Title>
|
|
<Text c="dimmed" size="sm" mb="md">Manage authentication methods and security settings</Text>
|
|
</div>
|
|
|
|
<Tabs defaultValue="mfa">
|
|
<Tabs.List>
|
|
<Tabs.Tab value="mfa" leftSection={<IconShieldLock size={16} />}>
|
|
Two-Factor Auth
|
|
</Tabs.Tab>
|
|
<Tabs.Tab value="passkeys" leftSection={<IconFingerprint size={16} />}>
|
|
Passkeys
|
|
</Tabs.Tab>
|
|
<Tabs.Tab value="linked" leftSection={<IconLink size={16} />}>
|
|
Linked Accounts
|
|
</Tabs.Tab>
|
|
</Tabs.List>
|
|
|
|
<Tabs.Panel value="mfa" pt="md">
|
|
<MfaSettings />
|
|
</Tabs.Panel>
|
|
|
|
<Tabs.Panel value="passkeys" pt="md">
|
|
<PasskeySettings />
|
|
</Tabs.Panel>
|
|
|
|
<Tabs.Panel value="linked" pt="md">
|
|
<LinkedAccounts />
|
|
</Tabs.Panel>
|
|
</Tabs>
|
|
</Stack>
|
|
);
|
|
}
|