diff --git a/src/components/header.tsx b/src/components/header.tsx index cea0dd9..aa77820 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -9,11 +9,18 @@ import { Title, useMantineColorScheme, } from "@mantine/core"; -import { IconUserShield } from "@tabler/icons-react"; +import { + IconLayoutSidebarLeftCollapse, + IconUserShield, +} from "@tabler/icons-react"; import { useLocation, useNavigate } from "@tanstack/react-router"; -import { Bell, Moon, Sun, User as UserIcon } from "lucide-react"; // Renamed User to UserIcon to avoid conflict with Mantine's User component if it exists +import { Bell, Moon, Sun, User as UserIcon } from "lucide-react"; -export function Header() { +interface HeaderProps { + onSidebarToggle?: () => void; +} + +export function Header({ onSidebarToggle }: HeaderProps) { const location = useLocation(); const { colorScheme, toggleColorScheme } = useMantineColorScheme(); const dark = colorScheme === "dark"; @@ -56,9 +63,24 @@ export function Header() { return ( {/* Title */} - - {getPageTitle()} - + + + + + {/* + {getPageTitle()} + */} + {/* Right Section */} diff --git a/src/components/umkm/summary-cards.tsx b/src/components/umkm/summary-cards.tsx index a986ddd..8e103c5 100644 --- a/src/components/umkm/summary-cards.tsx +++ b/src/components/umkm/summary-cards.tsx @@ -1,19 +1,18 @@ import { - Badge, + Avatar, Card, Grid, GridCol, Group, Stack, Text, - useMantineColorScheme, + useMantineColorScheme } from "@mantine/core"; import { - IconBuildingStore, IconCategory, - IconCurrency, IconCurrencyDollar, - IconUsers, + IconTrendingUp, + IconUsers } from "@tabler/icons-react"; interface KpiCardProps { @@ -22,9 +21,10 @@ interface KpiCardProps { subtitle?: string; icon: React.ReactNode; color: string; + backgroundColor: string; } -const KpiCard = ({ title, value, subtitle, icon, color }: KpiCardProps) => { +const KpiCard = ({ title, value, subtitle, icon, color, backgroundColor }: KpiCardProps) => { const { colorScheme } = useMantineColorScheme(); const dark = colorScheme === "dark"; @@ -64,10 +64,10 @@ const KpiCard = ({ title, value, subtitle, icon, color }: KpiCardProps) => { )} - { }} > {icon} - + ); @@ -106,29 +106,33 @@ export const SummaryCards = ({ data }: SummaryCardsProps) => { title: "UMKM Aktif", value: displayData.umkmAktif, subtitle: "Beroperasi", - icon: , - color: "darmasaba-blue", + icon: , + color: "white", + backgroundColor: "#1E3A5F" }, { title: "UMKM Terdaftar", value: displayData.umkmTerdaftar, subtitle: "Total registrasi", - icon: , - color: "darmasaba-success", + icon: , + color: "white", + backgroundColor: "#1E3A5F" }, { title: "Omzet", value: displayData.omzet, subtitle: "Omzet BUMDes per bulan", - icon: , - color: "darmasaba-warning", + icon: , + color: "white", + backgroundColor: "#1E3A5F" }, { title: "UMKM Terbanyak", value: displayData.kategoriTerbanyak.count, subtitle: `Kategori ${displayData.kategoriTerbanyak.name}`, - icon: , - color: "darmasaba-danger", + icon: , + color: "white", + backgroundColor: "#1E3A5F" }, ]; diff --git a/src/hooks/use-sidebar-fullscreen.ts b/src/hooks/use-sidebar-fullscreen.ts new file mode 100644 index 0000000..cc16cc6 --- /dev/null +++ b/src/hooks/use-sidebar-fullscreen.ts @@ -0,0 +1,25 @@ +import { useDisclosure } from "@mantine/hooks"; + +export function useSidebarFullscreen() { + const [opened, { toggle: toggleMobile }] = useDisclosure(); + const [sidebarCollapsed, setSidebarCollapsed] = useDisclosure(false); + + const toggleSidebar = () => { + setSidebarCollapsed.toggle(); + }; + + const handleMainClick = () => { + if (!sidebarCollapsed) { + toggleSidebar(); + } + }; + + return { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + isCollapsed: sidebarCollapsed, + }; +} diff --git a/src/routes/bantuan.tsx b/src/routes/bantuan.tsx index 3c45d99..9f92ce6 100644 --- a/src/routes/bantuan.tsx +++ b/src/routes/bantuan.tsx @@ -1,16 +1,22 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import { Header } from "@/components/header"; import HelpPage from "@/components/help-page"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/bantuan")({ component: BantuanRoute, }); function BantuanRoute() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function BantuanRoute() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function BantuanRoute() { - + diff --git a/src/routes/bumdes.tsx b/src/routes/bumdes.tsx index d36a3f5..ba70a9f 100644 --- a/src/routes/bumdes.tsx +++ b/src/routes/bumdes.tsx @@ -1,16 +1,22 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import BumdesPage from "@/components/bumdes-page"; import { Header } from "@/components/header"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/bumdes")({ component: BumdesRoute, }); function BumdesRoute() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function BumdesRoute() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function BumdesRoute() { - + diff --git a/src/routes/demografi-pekerjaan.tsx b/src/routes/demografi-pekerjaan.tsx index 722817e..3d6641e 100644 --- a/src/routes/demografi-pekerjaan.tsx +++ b/src/routes/demografi-pekerjaan.tsx @@ -1,8 +1,8 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import { Header } from "@/components/header"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; import DemografiPekerjaan from "../components/demografi-pekerjaan"; export const Route = createFileRoute("/demografi-pekerjaan")({ @@ -10,7 +10,13 @@ export const Route = createFileRoute("/demografi-pekerjaan")({ }); function DemografiPekerjaanPage() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function DemografiPekerjaanPage() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function DemografiPekerjaanPage() { - + diff --git a/src/routes/index.tsx b/src/routes/index.tsx index ad6162a..84d9fd0 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -11,25 +11,32 @@ export const Route = createFileRoute("/")({ function DashboardPage() { const [opened, { toggle }] = useDisclosure(); + const [sidebarCollapsed, setSidebarCollapsed] = useDisclosure(false); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; const mainBgColor = colorScheme === "dark" ? "#11192D" : "#edf3f8ff"; + const handleMainClick = () => { + if (!sidebarCollapsed) { + setSidebarCollapsed.toggle(); + } + }; + return ( -
+
@@ -43,7 +50,11 @@ function DashboardPage() { - + diff --git a/src/routes/jenna-analytic.tsx b/src/routes/jenna-analytic.tsx index 2699fbe..ba5b92b 100644 --- a/src/routes/jenna-analytic.tsx +++ b/src/routes/jenna-analytic.tsx @@ -1,16 +1,22 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import { Header } from "@/components/header"; import JennaAnalytic from "@/components/jenna-analytic"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/jenna-analytic")({ component: JennaAnalyticPage, }); function JennaAnalyticPage() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function JennaAnalyticPage() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function JennaAnalyticPage() { - + diff --git a/src/routes/keamanan.tsx b/src/routes/keamanan.tsx index c315b97..2c6b284 100644 --- a/src/routes/keamanan.tsx +++ b/src/routes/keamanan.tsx @@ -1,16 +1,22 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import { Header } from "@/components/header"; import KeamananPage from "@/components/keamanan-page"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/keamanan")({ component: KeamananRoute, }); function KeamananRoute() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function KeamananRoute() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function KeamananRoute() { - + diff --git a/src/routes/keuangan-anggaran.tsx b/src/routes/keuangan-anggaran.tsx index 5dbcf8e..7fd3a89 100644 --- a/src/routes/keuangan-anggaran.tsx +++ b/src/routes/keuangan-anggaran.tsx @@ -1,16 +1,22 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import { Header } from "@/components/header"; import KeuanganAnggaran from "@/components/keuangan-anggaran"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/keuangan-anggaran")({ component: KeuanganAnggaranPage, }); function KeuanganAnggaranPage() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function KeuanganAnggaranPage() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function KeuanganAnggaranPage() { - + diff --git a/src/routes/kinerja-divisi.tsx b/src/routes/kinerja-divisi.tsx index 0f1d3ba..9108f71 100644 --- a/src/routes/kinerja-divisi.tsx +++ b/src/routes/kinerja-divisi.tsx @@ -1,16 +1,22 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import { Header } from "@/components/header"; import KinerjaDivisi from "@/components/kinerja-divisi"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/kinerja-divisi")({ component: KinerjaDivisiPage, }); function KinerjaDivisiPage() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function KinerjaDivisiPage() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function KinerjaDivisiPage() { - + diff --git a/src/routes/pengaduan-layanan-publik.tsx b/src/routes/pengaduan-layanan-publik.tsx index a653104..23f8f14 100644 --- a/src/routes/pengaduan-layanan-publik.tsx +++ b/src/routes/pengaduan-layanan-publik.tsx @@ -1,16 +1,22 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import { Header } from "@/components/header"; import PengaduanLayananPublik from "@/components/pengaduan-layanan-publik"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/pengaduan-layanan-publik")({ component: PengaduanLayananPublikPage, }); function PengaduanLayananPublikPage() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function PengaduanLayananPublikPage() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function PengaduanLayananPublikPage() { - + diff --git a/src/routes/pengaturan/route.tsx b/src/routes/pengaturan/route.tsx index a6e59c5..8cbba42 100644 --- a/src/routes/pengaturan/route.tsx +++ b/src/routes/pengaturan/route.tsx @@ -1,5 +1,5 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure, useMediaQuery } from "@mantine/hooks"; +import { useMediaQuery } from "@mantine/hooks"; import { createFileRoute, Outlet, @@ -8,13 +8,20 @@ import { import { useEffect } from "react"; import { Header } from "@/components/header"; import { Sidebar } from "@/components/sidebar"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/pengaturan")({ component: PengaturanLayout, }); function PengaturanLayout() { - const [opened, { toggle, close }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const isMobile = useMediaQuery("(max-width: 48em)"); @@ -27,9 +34,9 @@ function PengaturanLayout() { // Auto close navbar on route change (mobile only) useEffect(() => { if (isMobile && opened) { - close(); + toggleMobile(); } - }, [routerState.location.pathname, isMobile, opened, close]); + }, [routerState.location.pathname, isMobile, opened, toggleMobile]); return ( - -
+ +
@@ -58,7 +70,11 @@ function PengaturanLayout() { - +
diff --git a/src/routes/sosial.tsx b/src/routes/sosial.tsx index 4a3d79f..344cb7b 100644 --- a/src/routes/sosial.tsx +++ b/src/routes/sosial.tsx @@ -1,16 +1,22 @@ import { AppShell, Burger, Group, useMantineColorScheme } from "@mantine/core"; -import { useDisclosure } from "@mantine/hooks"; import { createFileRoute } from "@tanstack/react-router"; import { Header } from "@/components/header"; import { Sidebar } from "@/components/sidebar"; import SosialPage from "@/components/sosial-page"; +import { useSidebarFullscreen } from "@/hooks/use-sidebar-fullscreen"; export const Route = createFileRoute("/sosial")({ component: SosialRoute, }); function SosialRoute() { - const [opened, { toggle }] = useDisclosure(); + const { + opened, + toggleMobile, + sidebarCollapsed, + toggleSidebar, + handleMainClick, + } = useSidebarFullscreen(); const { colorScheme } = useMantineColorScheme(); const headerBgColor = colorScheme === "dark" ? "#11192D" : "#19355E"; const navbarBgColor = colorScheme === "dark" ? "#11192D" : "white"; @@ -22,14 +28,19 @@ function SosialRoute() { navbar={{ width: 300, breakpoint: "sm", - collapsed: { mobile: !opened }, + collapsed: { mobile: !opened, desktop: sidebarCollapsed }, }} padding="md" > - -
+ +
@@ -43,7 +54,11 @@ function SosialRoute() { - +