Add account settings

This commit is contained in:
2024-11-05 21:03:25 +01:00
parent 9581e32e06
commit 8b8bfaa8c8
2 changed files with 240 additions and 81 deletions

View 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;

View File

@@ -10,99 +10,108 @@ import {
} from '@mantine/core'; } from '@mantine/core';
import { IconUser, IconLogout, IconUserCircle } from '@tabler/icons-react'; import { IconUser, IconLogout, IconUserCircle } from '@tabler/icons-react';
import { useAuth } from '../contexts/AuthContext'; import { useAuth } from '../contexts/AuthContext';
import AccountSettings from './AccountSettings';
const UserMenu = () => { const UserMenu = () => {
const [accountSettingsOpened, setAccountSettingsOpened] = useState(false);
const [opened, setOpened] = useState(false); const [opened, setOpened] = useState(false);
const { logout } = useAuth(); const { user, logout } = useAuth();
const handleLogout = () => { const handleLogout = () => {
logout(); logout();
}; };
return ( return (
<Popover <>
width={200} <Popover
position="bottom-end" width={200}
withArrow position="bottom-end"
shadow="md" withArrow
opened={opened} shadow="md"
onChange={setOpened} opened={opened}
> onChange={setOpened}
<Popover.Target> >
<Avatar <Popover.Target>
radius="xl" <Avatar
style={{ cursor: 'pointer' }} radius="xl"
onClick={() => setOpened((o) => !o)} 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],
},
})}
> >
<Group> <IconUser size={24} />
<IconUserCircle size={16} /> </Avatar>
<Text size="sm">Account Settings</Text> </Popover.Target>
</Group>
</UnstyledButton>
<UnstyledButton <Popover.Dropdown>
onClick={handleLogout} <Stack gap="sm">
px="sm" {/* User Info Section */}
py="xs" <Group gap="sm">
color="red" <Avatar radius="xl" size="md">
style={(theme) => ({ <IconUser size={24} />
borderRadius: theme.radius.sm, </Avatar>
'&:hover': { <div>
backgroundColor: <Text size="sm" fw={500}>
theme.colorScheme === 'dark' {user.displayName || user.email}
? theme.colors.dark[5] </Text>
: theme.colors.gray[0], </div>
},
})}
>
<Group>
<IconLogout size={16} color="red" />
<Text size="sm" c="red">
Logout
</Text>
</Group> </Group>
</UnstyledButton>
</Stack> <Divider />
</Popover.Dropdown>
</Popover> {/* 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)}
/>
</>
); );
}; };