Sprint 5: User profile menu, preferences, org member management, v0.2.0
- Move Settings from sidebar Admin section to User Profile dropdown menu
- Add User Preferences page (placeholder for future: dark mode, timezone,
notifications, feature visibility)
- Add Manage Members page for tenant admins to invite/manage board members:
- List all org members with roles, status, join date, last login
- Add new members (creates user account + org membership)
- Change member roles (president, treasurer, secretary, board member,
property manager, viewer)
- Remove members (soft-deactivate)
- Role-gated: only president, admin, treasurer can manage members
- Backend: new org member management endpoints on OrganizationsController
- GET /organizations/members
- POST /organizations/members
- PUT /organizations/members/:id/role
- DELETE /organizations/members/:id
- Bump version to 0.2.0 MVP_P2 (package.json + Settings page)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,9 @@ import {
|
||||
IconLogout,
|
||||
IconSwitchHorizontal,
|
||||
IconChevronDown,
|
||||
IconSettings,
|
||||
IconUserCog,
|
||||
IconUsersGroup,
|
||||
} from '@tabler/icons-react';
|
||||
import { Outlet, useNavigate } from 'react-router-dom';
|
||||
import { useAuthStore } from '../../stores/authStore';
|
||||
@@ -20,6 +23,9 @@ export function AppLayout() {
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
// Tenant admins (president role) can manage org members
|
||||
const isTenantAdmin = currentOrg?.role === 'president' || currentOrg?.role === 'admin';
|
||||
|
||||
return (
|
||||
<AppShell
|
||||
header={{ height: 60 }}
|
||||
@@ -36,7 +42,7 @@ export function AppLayout() {
|
||||
{currentOrg && (
|
||||
<Text size="sm" c="dimmed">{currentOrg.name}</Text>
|
||||
)}
|
||||
<Menu shadow="md" width={200}>
|
||||
<Menu shadow="md" width={220}>
|
||||
<Menu.Target>
|
||||
<UnstyledButton>
|
||||
<Group gap="xs">
|
||||
@@ -49,6 +55,28 @@ export function AppLayout() {
|
||||
</UnstyledButton>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
<Menu.Label>Account</Menu.Label>
|
||||
<Menu.Item
|
||||
leftSection={<IconUserCog size={14} />}
|
||||
onClick={() => navigate('/preferences')}
|
||||
>
|
||||
User Preferences
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
leftSection={<IconSettings size={14} />}
|
||||
onClick={() => navigate('/settings')}
|
||||
>
|
||||
Settings
|
||||
</Menu.Item>
|
||||
{isTenantAdmin && (
|
||||
<Menu.Item
|
||||
leftSection={<IconUsersGroup size={14} />}
|
||||
onClick={() => navigate('/org-members')}
|
||||
>
|
||||
Manage Members
|
||||
</Menu.Item>
|
||||
)}
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
leftSection={<IconSwitchHorizontal size={14} />}
|
||||
onClick={() => navigate('/select-org')}
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
IconShieldCheck,
|
||||
IconBuildingBank,
|
||||
IconUsers,
|
||||
IconSettings,
|
||||
IconCrown,
|
||||
IconCategory,
|
||||
IconChartAreaLine,
|
||||
@@ -74,12 +73,6 @@ const navSections = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Admin',
|
||||
items: [
|
||||
{ label: 'Settings', icon: IconSettings, path: '/settings' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export function Sidebar() {
|
||||
|
||||
Reference in New Issue
Block a user