mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-05 15:44:21 +00:00
Add account settings
This commit is contained in:
150
frontend/src/components/AccountSettings.jsx
Normal file
150
frontend/src/components/AccountSettings.jsx
Normal file
@@ -0,0 +1,150 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Modal,
|
||||
Badge,
|
||||
Button,
|
||||
Group,
|
||||
Title,
|
||||
Stack,
|
||||
Accordion,
|
||||
TextInput,
|
||||
Text,
|
||||
PasswordInput,
|
||||
Box,
|
||||
} from '@mantine/core';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
|
||||
const AccordionControl = ({ children }) => (
|
||||
<Accordion.Control>
|
||||
<Title order={4}>{children}</Title>
|
||||
</Accordion.Control>
|
||||
);
|
||||
|
||||
const ProfileSettings = ({ displayName, email }) => (
|
||||
<Stack spacing="md">
|
||||
<TextInput label="Display Name" defaultValue={displayName || ''} disabled />
|
||||
<TextInput label="Email" defaultValue={email} disabled />
|
||||
</Stack>
|
||||
);
|
||||
|
||||
const SecuritySettings = () => (
|
||||
<Stack spacing="md">
|
||||
<PasswordInput
|
||||
label="Current Password"
|
||||
placeholder="Enter current password"
|
||||
disabled
|
||||
/>
|
||||
<PasswordInput
|
||||
label="New Password"
|
||||
placeholder="Enter new password"
|
||||
disabled
|
||||
/>
|
||||
<PasswordInput
|
||||
label="Confirm New Password"
|
||||
placeholder="Confirm new password"
|
||||
disabled
|
||||
/>
|
||||
<Text size="xs" c="dimmed">
|
||||
Password must be at least 8 characters long and contain at least one
|
||||
uppercase letter, one lowercase letter, one number, and one special
|
||||
character.
|
||||
</Text>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
const DangerZone = () => (
|
||||
<Stack spacing="md">
|
||||
<Box mb="md">
|
||||
<Button
|
||||
color="red"
|
||||
variant="light"
|
||||
onClick={() => console.log('Delete Account')}
|
||||
fullWidth
|
||||
disabled
|
||||
>
|
||||
Delete Account
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
const AccountSettings = ({ opened, onClose }) => {
|
||||
const { user } = useAuth();
|
||||
return (
|
||||
<Modal
|
||||
opened={opened}
|
||||
onClose={onClose}
|
||||
title={<Title order={2}>Account Settings</Title>}
|
||||
centered
|
||||
size="lg"
|
||||
>
|
||||
<Stack spacing="xl">
|
||||
<Badge color="yellow" variant="light">
|
||||
Changes are currently disabled
|
||||
</Badge>
|
||||
|
||||
<Accordion
|
||||
defaultValue={['profile', 'security', 'danger']}
|
||||
multiple
|
||||
styles={(theme) => ({
|
||||
control: {
|
||||
paddingTop: theme.spacing.md,
|
||||
paddingBottom: theme.spacing.md,
|
||||
},
|
||||
item: {
|
||||
borderBottom: `1px solid ${
|
||||
theme.colorScheme === 'dark'
|
||||
? theme.colors.dark[4]
|
||||
: theme.colors.gray[3]
|
||||
}`,
|
||||
'&[data-active]': {
|
||||
backgroundColor:
|
||||
theme.colorScheme === 'dark'
|
||||
? theme.colors.dark[7]
|
||||
: theme.colors.gray[0],
|
||||
},
|
||||
},
|
||||
chevron: {
|
||||
'&[data-rotate]': {
|
||||
transform: 'rotate(180deg)',
|
||||
},
|
||||
},
|
||||
})}
|
||||
>
|
||||
<Accordion.Item value="profile">
|
||||
<AccordionControl>Profile</AccordionControl>
|
||||
<Accordion.Panel>
|
||||
<ProfileSettings
|
||||
displayName={user.displayName}
|
||||
email={user.email}
|
||||
/>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
|
||||
<Accordion.Item value="security">
|
||||
<AccordionControl>Security</AccordionControl>
|
||||
<Accordion.Panel>
|
||||
<SecuritySettings />
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
|
||||
<Accordion.Item value="danger">
|
||||
<AccordionControl>Danger Zone</AccordionControl>
|
||||
<Accordion.Panel>
|
||||
<DangerZone />
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
|
||||
<Group justify="flex-end">
|
||||
<Button variant="default" onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button disabled>Save Changes</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccountSettings;
|
||||
@@ -10,99 +10,108 @@ import {
|
||||
} from '@mantine/core';
|
||||
import { IconUser, IconLogout, IconUserCircle } from '@tabler/icons-react';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import AccountSettings from './AccountSettings';
|
||||
|
||||
const UserMenu = () => {
|
||||
const [accountSettingsOpened, setAccountSettingsOpened] = useState(false);
|
||||
const [opened, setOpened] = useState(false);
|
||||
const { logout } = useAuth();
|
||||
const { user, logout } = useAuth();
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
width={200}
|
||||
position="bottom-end"
|
||||
withArrow
|
||||
shadow="md"
|
||||
opened={opened}
|
||||
onChange={setOpened}
|
||||
>
|
||||
<Popover.Target>
|
||||
<Avatar
|
||||
radius="xl"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setOpened((o) => !o)}
|
||||
>
|
||||
<IconUser size={24} />
|
||||
</Avatar>
|
||||
</Popover.Target>
|
||||
|
||||
<Popover.Dropdown>
|
||||
<Stack gap="sm">
|
||||
{/* User Info Section */}
|
||||
<Group gap="sm">
|
||||
<Avatar radius="xl" size="md">
|
||||
<IconUser size={24} />
|
||||
</Avatar>
|
||||
<div>
|
||||
<Text size="sm" fw={500}>
|
||||
John Doe
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
john.doe@example.com
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
|
||||
<Divider />
|
||||
|
||||
{/* Menu Items */}
|
||||
<UnstyledButton
|
||||
onClick={() => console.log('Account settings')}
|
||||
px="sm"
|
||||
py="xs"
|
||||
style={(theme) => ({
|
||||
borderRadius: theme.radius.sm,
|
||||
'&:hover': {
|
||||
backgroundColor:
|
||||
theme.colorScheme === 'dark'
|
||||
? theme.colors.dark[5]
|
||||
: theme.colors.gray[0],
|
||||
},
|
||||
})}
|
||||
<>
|
||||
<Popover
|
||||
width={200}
|
||||
position="bottom-end"
|
||||
withArrow
|
||||
shadow="md"
|
||||
opened={opened}
|
||||
onChange={setOpened}
|
||||
>
|
||||
<Popover.Target>
|
||||
<Avatar
|
||||
radius="xl"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setOpened((o) => !o)}
|
||||
>
|
||||
<Group>
|
||||
<IconUserCircle size={16} />
|
||||
<Text size="sm">Account Settings</Text>
|
||||
</Group>
|
||||
</UnstyledButton>
|
||||
<IconUser size={24} />
|
||||
</Avatar>
|
||||
</Popover.Target>
|
||||
|
||||
<UnstyledButton
|
||||
onClick={handleLogout}
|
||||
px="sm"
|
||||
py="xs"
|
||||
color="red"
|
||||
style={(theme) => ({
|
||||
borderRadius: theme.radius.sm,
|
||||
'&:hover': {
|
||||
backgroundColor:
|
||||
theme.colorScheme === 'dark'
|
||||
? theme.colors.dark[5]
|
||||
: theme.colors.gray[0],
|
||||
},
|
||||
})}
|
||||
>
|
||||
<Group>
|
||||
<IconLogout size={16} color="red" />
|
||||
<Text size="sm" c="red">
|
||||
Logout
|
||||
</Text>
|
||||
<Popover.Dropdown>
|
||||
<Stack gap="sm">
|
||||
{/* User Info Section */}
|
||||
<Group gap="sm">
|
||||
<Avatar radius="xl" size="md">
|
||||
<IconUser size={24} />
|
||||
</Avatar>
|
||||
<div>
|
||||
<Text size="sm" fw={500}>
|
||||
{user.displayName || user.email}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</UnstyledButton>
|
||||
</Stack>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
|
||||
<Divider />
|
||||
|
||||
{/* Menu Items */}
|
||||
<UnstyledButton
|
||||
onClick={() => {
|
||||
setAccountSettingsOpened(true);
|
||||
setOpened(false);
|
||||
}}
|
||||
px="sm"
|
||||
py="xs"
|
||||
style={(theme) => ({
|
||||
borderRadius: theme.radius.sm,
|
||||
'&:hover': {
|
||||
backgroundColor:
|
||||
theme.colorScheme === 'dark'
|
||||
? theme.colors.dark[5]
|
||||
: theme.colors.gray[0],
|
||||
},
|
||||
})}
|
||||
>
|
||||
<Group>
|
||||
<IconUserCircle size={16} />
|
||||
<Text size="sm">Account Settings</Text>
|
||||
</Group>
|
||||
</UnstyledButton>
|
||||
|
||||
<UnstyledButton
|
||||
onClick={handleLogout}
|
||||
px="sm"
|
||||
py="xs"
|
||||
color="red"
|
||||
style={(theme) => ({
|
||||
borderRadius: theme.radius.sm,
|
||||
'&:hover': {
|
||||
backgroundColor:
|
||||
theme.colorScheme === 'dark'
|
||||
? theme.colors.dark[5]
|
||||
: theme.colors.gray[0],
|
||||
},
|
||||
})}
|
||||
>
|
||||
<Group>
|
||||
<IconLogout size={16} color="red" />
|
||||
<Text size="sm" c="red">
|
||||
Logout
|
||||
</Text>
|
||||
</Group>
|
||||
</UnstyledButton>
|
||||
</Stack>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
|
||||
<AccountSettings
|
||||
opened={accountSettingsOpened}
|
||||
onClose={() => setAccountSettingsOpened(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user