diff --git a/src/components/sidebar.tsx b/src/components/sidebar.tsx index 59f975d..71dfc2b 100644 --- a/src/components/sidebar.tsx +++ b/src/components/sidebar.tsx @@ -1,5 +1,5 @@ import { useNavigate, useLocation } from "@tanstack/react-router"; -import { Search } from "lucide-react"; +import { Search, ChevronDown, ChevronUp } from "lucide-react"; import { Stack, Group, @@ -9,7 +9,9 @@ import { NavLink as MantineNavLink, Box, useMantineColorScheme, + Collapse, } from "@mantine/core"; +import { useState } from "react"; interface SidebarProps { className?: string; @@ -21,6 +23,11 @@ export function Sidebar({ className }: SidebarProps) { const { colorScheme } = useMantineColorScheme(); const isActiveBg = colorScheme === 'dark' ? "#182949" : "#E6F0FF"; const isActiveBorder = colorScheme === 'dark' ? "#00398D" : "#1F41AE"; + + // State for settings submenu collapse + const [settingsOpen, setSettingsOpen] = useState( + location.pathname.startsWith('/dashboard/pengaturan') + ); // Define menu items with their paths const menuItems = [ @@ -34,9 +41,21 @@ export function Sidebar({ className }: SidebarProps) { { name: "Sosial", path: "/dashboard/sosial" }, { name: "Keamanan", path: "/dashboard/keamanan" }, { name: "Bantuan", path: "/dashboard/bantuan" }, - { name: "Pengaturan", path: "/dashboard/pengaturan" }, ]; + // Settings submenu items + const settingsItems = [ + { name: "Umum", path: "/dashboard/pengaturan/umum" }, + { name: "Notifikasi", path: "/dashboard/pengaturan/notifikasi" }, + { name: "Keamanan", path: "/dashboard/pengaturan/keamanan" }, + { name: "Akses & Tim", path: "/dashboard/pengaturan/akses-dan-tim" }, + ]; + + // Check if any settings submenu is active + const isSettingsActive = settingsItems.some(item => + location.pathname === item.path + ); + return ( {/* Logo */} @@ -78,7 +97,7 @@ export function Sidebar({ className }: SidebarProps) { {/* Menu Items */} - + {menuItems.map((item, index) => { const isActive = location.pathname === item.path; return ( @@ -107,6 +126,65 @@ export function Sidebar({ className }: SidebarProps) { /> ); })} + + {/* Settings with submenu */} + + setSettingsOpen(!settingsOpen)} + rightSection={settingsOpen ? : } + label="Pengaturan" + active={isSettingsActive} + variant="subtle" + color="blue" + style={{ + background: isSettingsActive ? isActiveBg : "transparent", + fontWeight: isSettingsActive ? "bold" : "normal", + borderLeft: isSettingsActive ? `4px solid ${isActiveBorder}` : "4px solid transparent", + borderRadius: "8px", + transition: "all 200ms ease", + margin: "2px 0", + }} + styles={{ + body: { + "&:hover": { + background: "#F1F5F9", + } + } + }} + /> + + + {settingsItems.map((item, index) => { + const isActive = location.pathname === item.path; + return ( + navigate({ to: item.path })} + label={item.name} + active={isActive} + variant="subtle" + color="blue" + style={{ + background: isActive ? isActiveBg : "transparent", + fontWeight: isActive ? "bold" : "normal", + borderLeft: isActive ? `4px solid ${isActiveBorder}` : "4px solid transparent", + borderRadius: "8px", + transition: "all 200ms ease", + margin: "2px 0", + }} + styles={{ + body: { + "&:hover": { + background: "#F1F5F9", + } + } + }} + /> + ); + })} + + + ); diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index 0bc961b..03af19d 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -21,6 +21,7 @@ import { Route as AdminIndexRouteImport } from './routes/admin/index' import { Route as UsersIdRouteImport } from './routes/users/$id' import { Route as ProfileEditRouteImport } from './routes/profile/edit' import { Route as DashboardSosialRouteImport } from './routes/dashboard/sosial' +import { Route as DashboardPengaturanRouteImport } from './routes/dashboard/pengaturan' import { Route as DashboardPengaduanLayananPublikRouteImport } from './routes/dashboard/pengaduan-layanan-publik' import { Route as DashboardKinerjaDivisiRouteImport } from './routes/dashboard/kinerja-divisi' import { Route as DashboardKeuanganAnggaranRouteImport } from './routes/dashboard/keuangan-anggaran' @@ -32,6 +33,10 @@ import { Route as DashboardBantuanRouteImport } from './routes/dashboard/bantuan import { Route as AdminUsersRouteImport } from './routes/admin/users' import { Route as AdminSettingsRouteImport } from './routes/admin/settings' import { Route as AdminApikeyRouteImport } from './routes/admin/apikey' +import { Route as DashboardPengaturanUmumRouteRouteImport } from './routes/dashboard/pengaturan/umum.route' +import { Route as DashboardPengaturanNotifikasiRouteRouteImport } from './routes/dashboard/pengaturan/notifikasi.route' +import { Route as DashboardPengaturanKeamananRouteRouteImport } from './routes/dashboard/pengaturan/keamanan.route' +import { Route as DashboardPengaturanAksesDanTimRouteRouteImport } from './routes/dashboard/pengaturan/akses-dan-tim.route' const SignupRoute = SignupRouteImport.update({ id: '/signup', @@ -93,6 +98,11 @@ const DashboardSosialRoute = DashboardSosialRouteImport.update({ path: '/sosial', getParentRoute: () => DashboardRouteRoute, } as any) +const DashboardPengaturanRoute = DashboardPengaturanRouteImport.update({ + id: '/pengaturan', + path: '/pengaturan', + getParentRoute: () => DashboardRouteRoute, +} as any) const DashboardPengaduanLayananPublikRoute = DashboardPengaduanLayananPublikRouteImport.update({ id: '/pengaduan-layanan-publik', @@ -151,6 +161,30 @@ const AdminApikeyRoute = AdminApikeyRouteImport.update({ path: '/apikey', getParentRoute: () => AdminRouteRoute, } as any) +const DashboardPengaturanUmumRouteRoute = + DashboardPengaturanUmumRouteRouteImport.update({ + id: '/umum', + path: '/umum', + getParentRoute: () => DashboardPengaturanRoute, + } as any) +const DashboardPengaturanNotifikasiRouteRoute = + DashboardPengaturanNotifikasiRouteRouteImport.update({ + id: '/notifikasi', + path: '/notifikasi', + getParentRoute: () => DashboardPengaturanRoute, + } as any) +const DashboardPengaturanKeamananRouteRoute = + DashboardPengaturanKeamananRouteRouteImport.update({ + id: '/keamanan', + path: '/keamanan', + getParentRoute: () => DashboardPengaturanRoute, + } as any) +const DashboardPengaturanAksesDanTimRouteRoute = + DashboardPengaturanAksesDanTimRouteRouteImport.update({ + id: '/akses-dan-tim', + path: '/akses-dan-tim', + getParentRoute: () => DashboardPengaturanRoute, + } as any) export interface FileRoutesByFullPath { '/': typeof IndexRoute @@ -169,6 +203,7 @@ export interface FileRoutesByFullPath { '/dashboard/keuangan-anggaran': typeof DashboardKeuanganAnggaranRoute '/dashboard/kinerja-divisi': typeof DashboardKinerjaDivisiRoute '/dashboard/pengaduan-layanan-publik': typeof DashboardPengaduanLayananPublikRoute + '/dashboard/pengaturan': typeof DashboardPengaturanRouteWithChildren '/dashboard/sosial': typeof DashboardSosialRoute '/profile/edit': typeof ProfileEditRoute '/users/$id': typeof UsersIdRoute @@ -176,6 +211,10 @@ export interface FileRoutesByFullPath { '/dashboard/': typeof DashboardIndexRoute '/profile/': typeof ProfileIndexRoute '/users/': typeof UsersIndexRoute + '/dashboard/pengaturan/akses-dan-tim': typeof DashboardPengaturanAksesDanTimRouteRoute + '/dashboard/pengaturan/keamanan': typeof DashboardPengaturanKeamananRouteRoute + '/dashboard/pengaturan/notifikasi': typeof DashboardPengaturanNotifikasiRouteRoute + '/dashboard/pengaturan/umum': typeof DashboardPengaturanUmumRouteRoute } export interface FileRoutesByTo { '/': typeof IndexRoute @@ -192,6 +231,7 @@ export interface FileRoutesByTo { '/dashboard/keuangan-anggaran': typeof DashboardKeuanganAnggaranRoute '/dashboard/kinerja-divisi': typeof DashboardKinerjaDivisiRoute '/dashboard/pengaduan-layanan-publik': typeof DashboardPengaduanLayananPublikRoute + '/dashboard/pengaturan': typeof DashboardPengaturanRouteWithChildren '/dashboard/sosial': typeof DashboardSosialRoute '/profile/edit': typeof ProfileEditRoute '/users/$id': typeof UsersIdRoute @@ -199,6 +239,10 @@ export interface FileRoutesByTo { '/dashboard': typeof DashboardIndexRoute '/profile': typeof ProfileIndexRoute '/users': typeof UsersIndexRoute + '/dashboard/pengaturan/akses-dan-tim': typeof DashboardPengaturanAksesDanTimRouteRoute + '/dashboard/pengaturan/keamanan': typeof DashboardPengaturanKeamananRouteRoute + '/dashboard/pengaturan/notifikasi': typeof DashboardPengaturanNotifikasiRouteRoute + '/dashboard/pengaturan/umum': typeof DashboardPengaturanUmumRouteRoute } export interface FileRoutesById { __root__: typeof rootRouteImport @@ -218,6 +262,7 @@ export interface FileRoutesById { '/dashboard/keuangan-anggaran': typeof DashboardKeuanganAnggaranRoute '/dashboard/kinerja-divisi': typeof DashboardKinerjaDivisiRoute '/dashboard/pengaduan-layanan-publik': typeof DashboardPengaduanLayananPublikRoute + '/dashboard/pengaturan': typeof DashboardPengaturanRouteWithChildren '/dashboard/sosial': typeof DashboardSosialRoute '/profile/edit': typeof ProfileEditRoute '/users/$id': typeof UsersIdRoute @@ -225,6 +270,10 @@ export interface FileRoutesById { '/dashboard/': typeof DashboardIndexRoute '/profile/': typeof ProfileIndexRoute '/users/': typeof UsersIndexRoute + '/dashboard/pengaturan/akses-dan-tim': typeof DashboardPengaturanAksesDanTimRouteRoute + '/dashboard/pengaturan/keamanan': typeof DashboardPengaturanKeamananRouteRoute + '/dashboard/pengaturan/notifikasi': typeof DashboardPengaturanNotifikasiRouteRoute + '/dashboard/pengaturan/umum': typeof DashboardPengaturanUmumRouteRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath @@ -245,6 +294,7 @@ export interface FileRouteTypes { | '/dashboard/keuangan-anggaran' | '/dashboard/kinerja-divisi' | '/dashboard/pengaduan-layanan-publik' + | '/dashboard/pengaturan' | '/dashboard/sosial' | '/profile/edit' | '/users/$id' @@ -252,6 +302,10 @@ export interface FileRouteTypes { | '/dashboard/' | '/profile/' | '/users/' + | '/dashboard/pengaturan/akses-dan-tim' + | '/dashboard/pengaturan/keamanan' + | '/dashboard/pengaturan/notifikasi' + | '/dashboard/pengaturan/umum' fileRoutesByTo: FileRoutesByTo to: | '/' @@ -268,6 +322,7 @@ export interface FileRouteTypes { | '/dashboard/keuangan-anggaran' | '/dashboard/kinerja-divisi' | '/dashboard/pengaduan-layanan-publik' + | '/dashboard/pengaturan' | '/dashboard/sosial' | '/profile/edit' | '/users/$id' @@ -275,6 +330,10 @@ export interface FileRouteTypes { | '/dashboard' | '/profile' | '/users' + | '/dashboard/pengaturan/akses-dan-tim' + | '/dashboard/pengaturan/keamanan' + | '/dashboard/pengaturan/notifikasi' + | '/dashboard/pengaturan/umum' id: | '__root__' | '/' @@ -293,6 +352,7 @@ export interface FileRouteTypes { | '/dashboard/keuangan-anggaran' | '/dashboard/kinerja-divisi' | '/dashboard/pengaduan-layanan-publik' + | '/dashboard/pengaturan' | '/dashboard/sosial' | '/profile/edit' | '/users/$id' @@ -300,6 +360,10 @@ export interface FileRouteTypes { | '/dashboard/' | '/profile/' | '/users/' + | '/dashboard/pengaturan/akses-dan-tim' + | '/dashboard/pengaturan/keamanan' + | '/dashboard/pengaturan/notifikasi' + | '/dashboard/pengaturan/umum' fileRoutesById: FileRoutesById } export interface RootRouteChildren { @@ -400,6 +464,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DashboardSosialRouteImport parentRoute: typeof DashboardRouteRoute } + '/dashboard/pengaturan': { + id: '/dashboard/pengaturan' + path: '/pengaturan' + fullPath: '/dashboard/pengaturan' + preLoaderRoute: typeof DashboardPengaturanRouteImport + parentRoute: typeof DashboardRouteRoute + } '/dashboard/pengaduan-layanan-publik': { id: '/dashboard/pengaduan-layanan-publik' path: '/pengaduan-layanan-publik' @@ -477,6 +548,34 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AdminApikeyRouteImport parentRoute: typeof AdminRouteRoute } + '/dashboard/pengaturan/umum': { + id: '/dashboard/pengaturan/umum' + path: '/umum' + fullPath: '/dashboard/pengaturan/umum' + preLoaderRoute: typeof DashboardPengaturanUmumRouteRouteImport + parentRoute: typeof DashboardPengaturanRoute + } + '/dashboard/pengaturan/notifikasi': { + id: '/dashboard/pengaturan/notifikasi' + path: '/notifikasi' + fullPath: '/dashboard/pengaturan/notifikasi' + preLoaderRoute: typeof DashboardPengaturanNotifikasiRouteRouteImport + parentRoute: typeof DashboardPengaturanRoute + } + '/dashboard/pengaturan/keamanan': { + id: '/dashboard/pengaturan/keamanan' + path: '/keamanan' + fullPath: '/dashboard/pengaturan/keamanan' + preLoaderRoute: typeof DashboardPengaturanKeamananRouteRouteImport + parentRoute: typeof DashboardPengaturanRoute + } + '/dashboard/pengaturan/akses-dan-tim': { + id: '/dashboard/pengaturan/akses-dan-tim' + path: '/akses-dan-tim' + fullPath: '/dashboard/pengaturan/akses-dan-tim' + preLoaderRoute: typeof DashboardPengaturanAksesDanTimRouteRouteImport + parentRoute: typeof DashboardPengaturanRoute + } } } @@ -498,6 +597,25 @@ const AdminRouteRouteWithChildren = AdminRouteRoute._addFileChildren( AdminRouteRouteChildren, ) +interface DashboardPengaturanRouteChildren { + DashboardPengaturanAksesDanTimRouteRoute: typeof DashboardPengaturanAksesDanTimRouteRoute + DashboardPengaturanKeamananRouteRoute: typeof DashboardPengaturanKeamananRouteRoute + DashboardPengaturanNotifikasiRouteRoute: typeof DashboardPengaturanNotifikasiRouteRoute + DashboardPengaturanUmumRouteRoute: typeof DashboardPengaturanUmumRouteRoute +} + +const DashboardPengaturanRouteChildren: DashboardPengaturanRouteChildren = { + DashboardPengaturanAksesDanTimRouteRoute: + DashboardPengaturanAksesDanTimRouteRoute, + DashboardPengaturanKeamananRouteRoute: DashboardPengaturanKeamananRouteRoute, + DashboardPengaturanNotifikasiRouteRoute: + DashboardPengaturanNotifikasiRouteRoute, + DashboardPengaturanUmumRouteRoute: DashboardPengaturanUmumRouteRoute, +} + +const DashboardPengaturanRouteWithChildren = + DashboardPengaturanRoute._addFileChildren(DashboardPengaturanRouteChildren) + interface DashboardRouteRouteChildren { DashboardBantuanRoute: typeof DashboardBantuanRoute DashboardBumdesRoute: typeof DashboardBumdesRoute @@ -507,6 +625,7 @@ interface DashboardRouteRouteChildren { DashboardKeuanganAnggaranRoute: typeof DashboardKeuanganAnggaranRoute DashboardKinerjaDivisiRoute: typeof DashboardKinerjaDivisiRoute DashboardPengaduanLayananPublikRoute: typeof DashboardPengaduanLayananPublikRoute + DashboardPengaturanRoute: typeof DashboardPengaturanRouteWithChildren DashboardSosialRoute: typeof DashboardSosialRoute DashboardIndexRoute: typeof DashboardIndexRoute } @@ -520,6 +639,7 @@ const DashboardRouteRouteChildren: DashboardRouteRouteChildren = { DashboardKeuanganAnggaranRoute: DashboardKeuanganAnggaranRoute, DashboardKinerjaDivisiRoute: DashboardKinerjaDivisiRoute, DashboardPengaduanLayananPublikRoute: DashboardPengaduanLayananPublikRoute, + DashboardPengaturanRoute: DashboardPengaturanRouteWithChildren, DashboardSosialRoute: DashboardSosialRoute, DashboardIndexRoute: DashboardIndexRoute, } diff --git a/src/routes/dashboard/pengaturan.tsx b/src/routes/dashboard/pengaturan.tsx new file mode 100644 index 0000000..09e2000 --- /dev/null +++ b/src/routes/dashboard/pengaturan.tsx @@ -0,0 +1,9 @@ +import { createFileRoute, Outlet } from '@tanstack/react-router'; + +export const Route = createFileRoute('/dashboard/pengaturan')({ + component: () => ( +
+ +
+ ), +}); \ No newline at end of file diff --git a/src/routes/dashboard/pengaturan/akses-dan-tim.route.tsx b/src/routes/dashboard/pengaturan/akses-dan-tim.route.tsx new file mode 100644 index 0000000..62f6d43 --- /dev/null +++ b/src/routes/dashboard/pengaturan/akses-dan-tim.route.tsx @@ -0,0 +1,6 @@ +import { createFileRoute } from '@tanstack/react-router'; +import AksesDanTimSettings from './akses-dan-tim'; + +export const Route = createFileRoute('/dashboard/pengaturan/akses-dan-tim')({ + component: AksesDanTimSettings, +}); \ No newline at end of file diff --git a/src/routes/dashboard/pengaturan/akses-dan-tim.tsx b/src/routes/dashboard/pengaturan/akses-dan-tim.tsx new file mode 100644 index 0000000..912388d --- /dev/null +++ b/src/routes/dashboard/pengaturan/akses-dan-tim.tsx @@ -0,0 +1,123 @@ +import { Card, Title, Text, Space, Button, Group, Alert, Table, ActionIcon, Modal, TextInput, Select } from '@mantine/core'; +import { IconInfoCircle, IconUserPlus, IconTrash, IconEdit, IconUser } from '@tabler/icons-react'; +import { useState } from 'react'; + +const AksesDanTimSettings = () => { + const [opened, setOpened] = useState(false); + + // Sample team members data + const teamMembers = [ + { id: 1, name: 'Admin Utama', email: 'admin@desa.go.id', role: 'Administrator', status: 'Aktif' }, + { id: 2, name: 'Operator Desa', email: 'operator@desa.go.id', role: 'Operator', status: 'Aktif' }, + { id: 3, name: 'Staff Keuangan', email: 'keuangan@desa.go.id', role: 'Keuangan', status: 'Aktif' }, + { id: 4, name: 'Staff Umum', email: 'umum@desa.go.id', role: 'Umum', status: 'Nonaktif' }, + ]; + + const roles = [ + { value: 'administrator', label: 'Administrator' }, + { value: 'operator', label: 'Operator' }, + { value: 'keuangan', label: 'Keuangan' }, + { value: 'umum', label: 'Umum' }, + { value: 'keamanan', label: 'Keamanan' }, + ]; + + return ( + + setOpened(false)} + title="Tambah Anggota Tim" + size="lg" + > + + + + +