* replace next with vite
* disable strictmode (it interferes with collaboration in dev mode)
This commit is contained in:
Philipinho
2023-10-20 17:12:08 +01:00
parent a86991e3d7
commit 9b682c8af5
96 changed files with 645 additions and 505 deletions
@@ -0,0 +1,3 @@
import { atom } from "jotai";
export const settingsModalAtom = atom<boolean>(false);
@@ -0,0 +1,76 @@
.sidebar {
max-height: rem(700px);
width: rem(180px);
padding: var(--mantine-spacing-sm);
display: flex;
flex-direction: column;
border-right: rem(1px) solid
light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
}
.sidebarFlex {
display: flex;
}
.sidebarMain {
flex: 1;
}
.sidebarRightSection {
flex: 1;
padding: rem(16px) rem(40px);
}
.sidebarItemHeader {
padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm);
font-size: var(--mantine-font-size-sm);
color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1));
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
}
.sidebarItem {
cursor: pointer;
display: flex;
align-items: center;
text-decoration: none;
font-size: var(--mantine-font-size-sm);
color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1));
padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm);
border-radius: var(--mantine-radius-sm);
font-weight: 500;
user-select: none;
@mixin hover {
background-color: light-dark(
var(--mantine-color-gray-1),
var(--mantine-color-dark-6)
);
color: light-dark(var(--mantine-color-black), var(--mantine-color-white));
.sidebarItemIcon {
color: light-dark(var(--mantine-color-black), var(--mantine-color-white));
}
}
&[data-active] {
&,
& :hover {
background-color: var(--mantine-color-blue-light);
color: var(--mantine-color-blue-light-color);
.sidebarItemIcon {
color: var(--mantine-color-blue-light-color);
}
}
}
}
.sidebarItemIcon {
color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-dark-2));
margin-right: var(--mantine-spacing-sm);
width: rem(20px);
height: rem(20px);
}
@@ -0,0 +1,30 @@
import { Modal, Text } from '@mantine/core';
import React from 'react';
import SettingsSidebar from '@/features/settings/modal/settings-sidebar';
import { useAtom } from 'jotai';
import { settingsModalAtom } from '@/features/settings/modal/atoms/settings-modal-atom';
export default function SettingsModal() {
const [isModalOpen, setModalOpen] = useAtom(settingsModalAtom);
return (
<>
<Modal.Root size={1000} opened={isModalOpen} onClose={() => setModalOpen(false)}>
<Modal.Overlay />
<Modal.Content>
<Modal.Header>
<Modal.Title>
<Text size="xl" fw={500}>Settings</Text>
</Modal.Title>
<Modal.CloseButton />
</Modal.Header>
<Modal.Body>
<SettingsSidebar />
</Modal.Body>
</Modal.Content>
</Modal.Root>
</>
);
}
@@ -0,0 +1,101 @@
import React, { useState } from 'react';
import classes from '@/features/settings/modal/modal.module.css';
import { IconBell, IconFingerprint, IconReceipt, IconSettingsCog, IconUser, IconUsers } from '@tabler/icons-react';
import { Loader, ScrollArea, Text } from '@mantine/core';
const AccountSettings = React.lazy(() => import('@/features/settings/account/settings/account-settings'));
const WorkspaceSettings = React.lazy(() => import('@/features/settings/workspace/settings/workspace-settings'));
const WorkspaceMembers = React.lazy(() => import('@/features/settings/workspace/members/workspace-members'));
interface DataItem {
label: string;
icon: React.ElementType;
}
interface DataGroup {
heading: string;
items: DataItem[];
}
const groupedData: DataGroup[] = [
{
heading: 'Account',
items: [
{ label: 'Account', icon: IconUser },
{ label: 'Notifications', icon: IconBell },
],
},
{
heading: 'Workspace',
items: [
{ label: 'General', icon: IconSettingsCog },
{ label: 'Members', icon: IconUsers },
{ label: 'Security', icon: IconFingerprint },
{ label: 'Billing', icon: IconReceipt },
],
},
];
export default function SettingsSidebar() {
const [active, setActive] = useState('Account');
const menu = groupedData.map((group) => (
<div key={group.heading}>
<Text c="dimmed" className={classes.sidebarItemHeader}>{group.heading}</Text>
{group.items.map((item) => (
<div
className={classes.sidebarItem}
data-active={item.label === active || undefined}
key={item.label}
onClick={(event) => {
event.preventDefault();
setActive(item.label);
}}
>
<item.icon className={classes.sidebarItemIcon} stroke={1.5} />
<span>{item.label}</span>
</div>
))}
</div>
));
let ActiveComponent;
switch (active) {
case 'Account':
ActiveComponent = AccountSettings;
break;
case 'General':
ActiveComponent = WorkspaceSettings;
break;
case 'Members':
ActiveComponent = WorkspaceMembers;
break;
default:
ActiveComponent = null;
}
return (
<div className={classes.sidebarFlex}>
<nav className={classes.sidebar}>
<div className={classes.sidebarMain}>
{menu}
</div>
</nav>
<ScrollArea h="650" w="100%" scrollbarSize={4}>
<div className={classes.sidebarRightSection}>
<React.Suspense fallback={<Loader size="sm" color="gray" />}>
{ActiveComponent && <ActiveComponent />}
</React.Suspense>
</div>
</ScrollArea>
</div>
);
}