"use client"; import * as React from "react"; import { useEffect, useState } from "react"; import { AudioWaveform, Command, Frame, GalleryVerticalEnd, Loader2, SquareTerminal, } from "lucide-react"; import { NavMain } from "@/components/nav-main"; import { NavProjects } from "@/components/nav-projects"; import { NavUser } from "@/components/nav-user"; import { TeamSwitcher } from "@/components/team-switcher"; import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail, } from "@/components/ui/sidebar"; import { NavItemsGet, NavSubItems, } from "@/src/applications/entities/models/nav-items.model"; import { getNavItems } from "@/actions/dashboard/nav-items"; import DynamicIcon, { DynamicIconProps } from "./dynamic-icon"; // 🔧 Konstanta untuk localStorage key const NAV_ITEMS_STORAGE_KEY = "navItemsData"; // 🎨 Data fallback const fallbackData = { user: { name: "shadcn", email: "m@example.com", avatar: "/avatars/shadcn.jpg", }, teams: [ { name: "Acme Inc", logo: GalleryVerticalEnd, plan: "Enterprise", }, { name: "Acme Corp.", logo: AudioWaveform, plan: "Startup", }, { name: "Evil Corp.", logo: Command, plan: "Free", }, ], navMain: [ { title: "Playground", url: "#", icon: SquareTerminal, isActive: true, items: [ { title: "History", url: "#", }, { title: "Starred", url: "#", }, { title: "Settings", url: "#", }, ], }, // additional items... ], projects: [ { name: "Design Engineering", url: "#", icon: Frame, }, // additional projects... ], }; export function AppSidebar({ ...props }: React.ComponentProps) { const [navItems, setNavItems] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // 📦 Ambil data dari localStorage const loadNavItemsFromStorage = (): NavItemsGet | null => { const storedData = localStorage.getItem(NAV_ITEMS_STORAGE_KEY); return storedData ? (JSON.parse(storedData) as NavItemsGet) : null; }; // ⚡ Fungsi untuk membandingkan dua objek secara deep const isDataEqual = (data1: NavItemsGet, data2: NavItemsGet): boolean => JSON.stringify(data1) === JSON.stringify(data2); useEffect(() => { const fetchAndSyncNavItems = async () => { try { const localData = loadNavItemsFromStorage(); if (localData) { setNavItems(localData); setIsLoading(false); } const response = await getNavItems(); if (response.success && response.data) { const fetchedData = response.data as NavItemsGet; const currentStoredData = loadNavItemsFromStorage(); // 🔄 Jika data berbeda, update localStorage dan state if ( currentStoredData && !isDataEqual(currentStoredData, fetchedData) ) { localStorage.setItem( NAV_ITEMS_STORAGE_KEY, JSON.stringify(fetchedData) ); setNavItems(fetchedData); } } else { setError(response.error || "Failed to load navigation items"); } } catch (err) { setError("An unexpected error occurred while fetching navigation"); console.error(err); } finally { setIsLoading(false); } }; fetchAndSyncNavItems(); }, []); // 🎛️ Transformasi data DB ke format NavMain const formatNavItems = React.useMemo(() => { if (!navItems) return fallbackData.navMain; return navItems.map((item) => ({ title: item.title, url: item.url, icon: item.icon, isActive: item.isActive, items: item.subItems.map((subItem) => ({ title: subItem.title, url: subItem.url, icon: subItem.icon, isActive: subItem.isActive, })), })); }, [navItems]); // 🧩 Komponen NavMain dinamis dengan ikon const DynamicNavMain = ({ items }: { items: any[] }) => ( ({ ...item, icon: () => , items: item.items.map((subItem: NavSubItems) => ({ ...subItem, icon: () => ( ), })), }))} /> ); return ( {isLoading ? (
) : error ? (
{error}
) : ( )} {/* */}
); }