diff --git a/app/[locale]/(admin)/admin/layout.tsx b/app/[locale]/(admin)/admin/layout.tsx deleted file mode 100644 index 459794f..0000000 --- a/app/[locale]/(admin)/admin/layout.tsx +++ /dev/null @@ -1,11 +0,0 @@ -"use client"; - -import { AdminLayout } from "@/components/layout/admin-layout"; - -export default function AdminPageLayout({ - children, -}: { - children: React.ReactNode; -}) { - return {children}; -} diff --git a/app/[locale]/theme.css b/app/[locale]/theme.css new file mode 100644 index 0000000..3800566 --- /dev/null +++ b/app/[locale]/theme.css @@ -0,0 +1,63 @@ +.theme-dark { + --sidebar: 222.2 84% 4.9%; + --header: 222.2 84% 4.9%; +} +.theme-rose { + --sidebar: 341, 64%, 43%; + --header: 341, 64%, 43%; + --secondary: 339, 60%, 51%; + --menu-arrow: 339, 60%, 51%; + --menu-arrow-active: 336, 67%, 60%; + +} + +.theme-gray { + --sidebar: 210, 10%, 23%; + --header: 210, 10%, 23%; + + --secondary: 207, 14%, 31%; + --menu-arrow: 207, 14%, 31%; + --menu-arrow-active: 203, 16%, 43%; +} +.theme-steel-blue { + --sidebar: 226, 36%, 39%; + --header: 226, 36%, 39%; + --secondary: 224, 40%, 48%; + --menu-arrow: 224, 40%, 48%; + --menu-arrow-active: 216, 47%, 60%; +} +.theme-purple { + --sidebar: 299, 56%, 19%; + --header: 299, 56%, 19%; + --secondary: 299, 40%, 28%; + --menu-arrow: 299, 40%, 28%; + --menu-arrow-active: 298, 44%, 33%; +} + +.theme-redwood { + --sidebar: 345, 24%, 29%; + --header: 345, 24%, 29%; + --secondary: 346, 26%, 35%; + --menu-arrow: 346, 26%, 35%; + --menu-arrow-active: 344, 27%, 42%; +} +.theme-green { + --sidebar: 164, 64%, 21%; + --header: 164, 64%, 21%; + + --secondary: 164, 68%, 24%; + --menu-arrow: 164, 68%, 24%; + --menu-arrow-active: 163, 69%, 30%; +} +.theme-ocean-blue { + --sidebar: 206, 92%, 35%; + --header: 206, 92%, 35%; + + --secondary: 205, 94%, 39%; + --menu-arrow: 205, 94%, 39%; + --menu-arrow-active: 203, 85%, 48%; +} +.theme-transparent{ + --header: transparent; + box-shadow: none; +} \ No newline at end of file diff --git a/components/layout/admin-layout.tsx b/components/layout/admin-layout.tsx deleted file mode 100644 index fd45da0..0000000 --- a/components/layout/admin-layout.tsx +++ /dev/null @@ -1,80 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import React, { ReactNode } from "react"; -import { ThemeProvider } from "./theme-context"; -import { motion, AnimatePresence } from "framer-motion"; -import { SidebarProvider } from "./sidebar-context"; -import { ModernSidebar } from "./modern-sidebar"; -import { ModernHeader } from "./modern-header"; - -export const AdminLayout = ({ children }: { children: ReactNode }) => { - const [sidebarOpen, setSidebarOpen] = useState(true); - const [hasMounted, setHasMounted] = useState(false); - - const toggleSidebar = () => { - setSidebarOpen(!sidebarOpen); - }; - - // Hooks - useEffect(() => { - setHasMounted(true); - // Auto-collapse sidebar on mobile - const handleResize = () => { - if (window.innerWidth < 1024) { - setSidebarOpen(false); - } else { - setSidebarOpen(true); - } - }; - - handleResize(); - window.addEventListener('resize', handleResize); - return () => window.removeEventListener('resize', handleResize); - }, []); - - // Render loading state until mounted - if (!hasMounted) { - return ( -
-
-
- ); - } - - return ( - - -
-
- {/* Modern Sidebar */} - - - {/* Main Content Area */} -
- {/* Modern Header */} - - - {/* Main Content */} - -
- {children} -
-
-
-
-
-
-
- ); -}; diff --git a/components/layout/modern-header.tsx b/components/layout/modern-header.tsx deleted file mode 100644 index a1566db..0000000 --- a/components/layout/modern-header.tsx +++ /dev/null @@ -1,136 +0,0 @@ -"use client"; - -import React, { useState, useEffect, useRef } from "react"; -import { motion, AnimatePresence } from "framer-motion"; -import { - Search, - Bell, - User, - Settings, - LogOut, - ChevronDown, - Menu, -} from "lucide-react"; - -interface ModernHeaderProps { - onMenuToggle: () => void; - sidebarOpen: boolean; -} - -export const ModernHeader: React.FC = ({ - onMenuToggle, - sidebarOpen, -}) => { - const [showUserDropdown, setShowUserDropdown] = useState(false); - const [searchQuery, setSearchQuery] = useState(""); - const dropdownRef = useRef(null); - - // Close dropdown when clicking outside - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { - setShowUserDropdown(false); - } - }; - - document.addEventListener('mousedown', handleClickOutside); - return () => { - document.removeEventListener('mousedown', handleClickOutside); - }; - }, []); - - return ( -
-
- {/* Left Section */} -
- {/* Mobile Menu Button */} - - - {/* Search Bar */} -
-
- - setSearchQuery(e.target.value)} - className="w-full pl-10 pr-4 py-2 bg-white border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200" - /> -
-
-
- - {/* Right Section */} -
- {/* Notifications */} - - - {/* User Avatar & Dropdown */} -
- - - {/* Dropdown Menu */} - - {showUserDropdown && ( - -
-

Admin User

-

admin@netidhub.com

-
- - - - - -
- - -
- )} -
-
-
-
-
- ); -}; diff --git a/components/layout/modern-sidebar.tsx b/components/layout/modern-sidebar.tsx deleted file mode 100644 index 68ad996..0000000 --- a/components/layout/modern-sidebar.tsx +++ /dev/null @@ -1,266 +0,0 @@ -"use client"; - -import React, { useState } from "react"; -import Link from "next/link"; -import { usePathname } from "next/navigation"; -import { motion, AnimatePresence } from "framer-motion"; -import { - LayoutDashboard, - Image, - Video, - FileText, - Music, - ChevronRight, - ChevronDown, - Menu, - X, -} from "lucide-react"; - -interface SidebarItem { - title: string; - icon: React.ComponentType<{ className?: string }>; - link?: string; - children?: SidebarItem[]; -} - -const sidebarItems: SidebarItem[] = [ - { - title: "Dashboard", - icon: LayoutDashboard, - link: "/admin/dashboard", - }, - { - title: "Content Management", - icon: FileText, - children: [ - { - title: "Foto", - icon: Image, - link: "/admin/content/image", - }, - { - title: "Audio Visual", - icon: Video, - link: "/admin/content/audio-visual", - }, - { - title: "Teks", - icon: FileText, - link: "/admin/content/document", - }, - { - title: "Audio", - icon: Music, - link: "/admin/content/audio", - }, - ], - }, -]; - -interface ModernSidebarProps { - isOpen: boolean; - onToggle: () => void; -} - -export const ModernSidebar: React.FC = ({ - isOpen, - onToggle, -}) => { - const pathname = usePathname(); - const [expandedItems, setExpandedItems] = useState([]); - - const toggleExpanded = (title: string) => { - setExpandedItems((prev) => - prev.includes(title) - ? prev.filter((item) => item !== title) - : [...prev, title] - ); - }; - - const SidebarItemComponent: React.FC<{ - item: SidebarItem; - level?: number; - }> = ({ item, level = 0 }) => { - const isExpanded = expandedItems.includes(item.title); - const hasChildren = item.children && item.children.length > 0; - const isActive = pathname === item.link; - - if (hasChildren) { - return ( -
- {/* Parent Menu */} - - - {/* Expanded Submenu (when sidebar is open) */} - - {isOpen && isExpanded && ( - -
- {item.children?.map((child) => ( - - ))} -
-
- )} -
- - {/* Collapsed Submenu Icons (when sidebar is collapsed) */} - {!isOpen && ( -
- {item.children?.map((child) => ( - -
- -
- - ))} -
- )} -
- ); - } - - return ( - -
0 ? "ml-4" : ""}`} - > - - {isOpen && ( - {item.title} - )} -
- - ); - }; - - return ( - <> - {/* Mobile Overlay */} - - {isOpen && ( - - )} - - - {/* Sidebar */} - - {/* Header */} -
- -
- N -
- {isOpen && ( - -

- Netidhub -

-

Admin Panel

-
- )} -
-
- - {/* Navigation */} - - -
- - {/* Floating Toggle Button - Expand */} - - {!isOpen && ( - - - - )} - - - {/* Floating Toggle Button - Collapse */} - - {isOpen && ( - - - - )} - - - ); -}; diff --git a/components/layout/sidebar-context.tsx b/components/layout/sidebar-context.tsx deleted file mode 100644 index a566005..0000000 --- a/components/layout/sidebar-context.tsx +++ /dev/null @@ -1,58 +0,0 @@ -'use client' -import React, { createContext, useContext, useEffect, useState } from 'react'; - -interface SidebarContextType { - isOpen: boolean; - toggleSidebar: () => void; -} - -const SidebarContext = createContext(undefined); - -export const SidebarProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [isOpen, setIsOpen] = useState(() => { - if (typeof window !== 'undefined') { - const storedValue = localStorage.getItem('sidebarOpen'); - return storedValue ? JSON.parse(storedValue) : false; - } - }); - - const toggleSidebar = () => { - setIsOpen(!isOpen); - }; - - useEffect(() => { - localStorage.setItem('sidebarOpen', JSON.stringify(isOpen)); - }, [isOpen]); - - useEffect(() => { - const handleResize = () => { - setIsOpen(window.innerWidth > 768); // Ganti 768 dengan lebar yang sesuai dengan breakpoint Anda - }; - - handleResize(); // Pastikan untuk memanggil fungsi handleResize saat komponen dimuat - - window.addEventListener('resize', handleResize); - - return () => { - window.removeEventListener('resize', handleResize); - }; - }, []); - - return ( - - {children} - - ); -}; - -export const useSidebar = () => { - const context = useContext(SidebarContext); - if (!context) { - throw new Error('useSidebar must be used within a SidebarProvider'); - } - return context; -}; - -export const useSidebarContext = () => { - return useContext(SidebarContext); -}; \ No newline at end of file diff --git a/components/layout/theme-context.tsx b/components/layout/theme-context.tsx deleted file mode 100644 index b498a01..0000000 --- a/components/layout/theme-context.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client"; - -import React, { createContext, useContext, useEffect, useState } from 'react'; - -type Theme = 'light' | 'dark'; - -interface ThemeContextType { - theme: Theme; - toggleTheme: () => void; - setTheme: (theme: Theme) => void; -} - -const ThemeContext = createContext(undefined); - -export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [theme, setThemeState] = useState('light'); - const [mounted, setMounted] = useState(false); - - useEffect(() => { - setMounted(true); - // Get theme from localStorage or default to 'light' - const savedTheme = localStorage.getItem('theme') as Theme; - if (savedTheme) { - setThemeState(savedTheme); - } else { - // Check system preference - const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; - setThemeState(systemTheme); - } - }, []); - - useEffect(() => { - if (!mounted) return; - - // Update document class and localStorage - document.documentElement.classList.remove('light', 'dark'); - document.documentElement.classList.add(theme); - localStorage.setItem('theme', theme); - }, [theme, mounted]); - - const toggleTheme = () => { - setThemeState(prev => prev === 'light' ? 'dark' : 'light'); - }; - - const setTheme = (newTheme: Theme) => { - setThemeState(newTheme); - }; - - // Prevent hydration mismatch - if (!mounted) { - return <>{children}; - } - - return ( - - {children} - - ); -}; - -export const useTheme = () => { - const context = useContext(ThemeContext); - if (context === undefined) { - throw new Error('useTheme must be used within a ThemeProvider'); - } - return context; -}; \ No newline at end of file diff --git a/components/logo.tsx b/components/logo.tsx index 2b940df..941e434 100644 --- a/components/logo.tsx +++ b/components/logo.tsx @@ -31,10 +31,9 @@ const Logo = () => {

D

)} */} logo ); diff --git a/components/partials/sidebar/common/collapse-menu-button.tsx b/components/partials/sidebar/common/collapse-menu-button.tsx index 006cf42..6f7db4f 100644 --- a/components/partials/sidebar/common/collapse-menu-button.tsx +++ b/components/partials/sidebar/common/collapse-menu-button.tsx @@ -146,7 +146,7 @@ export function CollapseMenuButton({ variant="ghost" fullWidth size='sm' - className={cn('w-full justify-center text-center p-0 h-auto hover:bg-transparent hover:text-default capitalize text-xs font-normal mb-2 first:mt-4 last:mb-0', { + className={cn('w-full justify-center text-center p-0 h-auto hover:bg-transparent hover:text-default capitalize text-xs font-normal mb-1.5 first:mt-2 last:mb-0', { 'font-semibold': active })} asChild @@ -180,7 +180,7 @@ export function CollapseMenuButton({ ref={setNodeRef} variant={active ? "default" : "ghost"} color='secondary' - className={cn('justify-start capitalize group h-auto py-3 md:px-3 px-3 ring-offset-sidebar group-data-[state=open]:bg-secondary ', { + className={cn('justify-start capitalize group h-auto py-2.5 md:px-3 px-3 ring-offset-sidebar group-data-[state=open]:bg-secondary ', { 'hover:md:ps-8': config.sidebar === 'draggable' && isDesktop })} fullWidth @@ -237,7 +237,7 @@ export function CollapseMenuButton({ key={index} color='secondary' variant="ghost" - className={cn('w-full justify-start h-auto hover:bg-transparent hover:ring-offset-0 capitalize text-sm font-normal mb-2 last:mb-0 first:mt-3 md:px-5 px-5', { + className={cn('w-full justify-start h-auto hover:bg-transparent hover:ring-offset-0 capitalize text-sm font-normal mb-1.5 last:mb-0 first:mt-2 md:px-5 px-5', { 'font-medium': active, 'dark:opacity-80': !active, })} diff --git a/components/partials/sidebar/common/menu-item.tsx b/components/partials/sidebar/common/menu-item.tsx index 1e04826..d4bb2f9 100644 --- a/components/partials/sidebar/common/menu-item.tsx +++ b/components/partials/sidebar/common/menu-item.tsx @@ -4,7 +4,7 @@ import React, { CSSProperties } from 'react' import { Button } from "@/components/ui/button"; import { Icon } from '@/components/ui/icon' import { type Menu } from '@/lib/menus'; -import { Link } from '@/i18n/routing'; +import { Link } from '@/components/navigation'; import { cn } from "@/lib/utils"; import { GripVertical } from 'lucide-react'; @@ -58,7 +58,7 @@ const MenuItem = ({ href, label, icon, active, id, collapsed }: MenuItemProps) = color={active ? "default" : "secondary"} fullWidth className={cn('', { - 'justify-start text-sm font-medium capitalize group hover:md:px-8 h-auto py-3 md:px-3 px-3': !collapsed, + 'justify-start text-sm font-medium capitalize group hover:md:px-8 h-auto py-2.5 md:px-3 px-3': !collapsed, 'hover:ring-transparent hover:ring-offset-0': !active })} asChild @@ -129,7 +129,7 @@ const MenuItem = ({ href, label, icon, active, id, collapsed }: MenuItemProps) = fullWidth color={active ? "default" : "secondary"} className={cn('', { - 'justify-start text-sm font-medium capitalize h-auto py-3 md:px-3 px-3': !collapsed || hovered, + 'justify-start text-sm font-medium capitalize h-auto py-2.5 md:px-3 px-3': !collapsed || hovered, 'hover:ring-transparent hover:ring-offset-0': !active })} asChild diff --git a/components/partials/sidebar/common/menu-label.tsx b/components/partials/sidebar/common/menu-label.tsx index 0ec5918..f128766 100644 --- a/components/partials/sidebar/common/menu-label.tsx +++ b/components/partials/sidebar/common/menu-label.tsx @@ -7,7 +7,7 @@ const MenuLabel = ({ label, className }: { label: string, className?: string }) const [config] = useConfig() if (config.sidebar === 'compact') return null return ( -

+

{label}

) diff --git a/components/partials/sidebar/menu/menu-classic.tsx b/components/partials/sidebar/menu/menu-classic.tsx index b371b9e..12df7bc 100644 --- a/components/partials/sidebar/menu/menu-classic.tsx +++ b/components/partials/sidebar/menu/menu-classic.tsx @@ -84,10 +84,10 @@ export function MenuClassic({ }) { ) : ""}