Spaces:
Running
Running
File size: 6,097 Bytes
308a91d 17178b7 308a91d 454ca1f e30505f 16bce84 5b92cf6 454ca1f 308a91d 454ca1f 308a91d 454ca1f 308a91d 9379fd7 e30505f 16bce84 5b92cf6 308a91d 54344fa 8194cb1 308a91d 17178b7 85ed9af 454ca1f 308a91d 85ed9af 308a91d 4502657 308a91d 7607c2e 308a91d 4502657 308a91d 7607c2e 308a91d 4502657 73d5fbe 7607c2e 308a91d 17178b7 308a91d 5c833e1 308a91d 17178b7 308a91d 17178b7 308a91d 65828cf 308a91d 7607c2e 308a91d 7607c2e 308a91d 4502657 308a91d cd3f69c 308a91d 7607c2e 4502657 308a91d 7607c2e 308a91d 7607c2e 308a91d 4502657 308a91d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | import { useNavigate, useLocation } from 'react-router-dom';
import useAuthStore from '../store/useAuthStore';
import { getCompanySlug } from '../utils/slug';
const superAdminMenus = [
{ path: '/admin/companies', label: 'Perusahaan', icon: 'store' },
{ path: '/admin/tenant-settings', label: 'Pengaturan Tenant', icon: 'settings' },
{ path: '/admin/topups', label: 'Verifikasi Saldo', icon: 'fact_check' },
{ path: '/admin/fees', label: 'Fee Report', icon: 'payments' },
];
const ownerMenus = [
{ path: '/dashboard', label: 'Dashboard', icon: 'dashboard' },
{ path: '/pos', label: 'Kasir (POS)', icon: 'point_of_sale' },
{ path: '/admin/branches', label: 'Cabang', icon: 'store' },
{ path: '/admin/products', label: 'Produk', icon: 'inventory_2' },
{ path: '/admin/categories', label: 'Kategori', icon: 'category' },
{ path: '/admin/kasir', label: 'Kasir', icon: 'group' },
{ path: '/admin/orders', label: 'Riwayat Order', icon: 'receipt_long' },
{ path: '/admin/members', label: 'Member', icon: 'group' },
{ path: '/admin/vouchers', label: 'Katalog Voucher', icon: 'confirmation_number' },
{ path: '/admin/wallet', label: 'Dompet Saldo', icon: 'account_balance_wallet' },
{ path: '/owner/report', label: 'Laporan Harian', icon: 'bar_chart' },
];
const kasirMenus = [
{ path: '/pos', label: 'Kasir (POS)', icon: 'point_of_sale' },
{ path: '/admin/members', label: 'Member', icon: 'group' },
{ path: '/kasir/report', label: 'Laporan Harian', icon: 'bar_chart' },
];
export default function Sidebar() {
const navigate = useNavigate();
const location = useLocation();
const { user, logout } = useAuthStore();
const slug = getCompanySlug(user?.company_name);
const getNavPath = (menuPath) => {
if (user?.role === 'super_admin') return menuPath;
return `/${slug}${menuPath}`;
};
let menus = user?.role === 'super_admin'
? superAdminMenus
: user?.role === 'owner'
? ownerMenus
: kasirMenus;
if (user?.role !== 'super_admin') {
const settings = user?.company_settings || {};
if (settings.enable_member === false) {
menus = menus.filter(m => m.path !== '/admin/members');
}
if (settings.enable_voucher === false) {
menus = menus.filter(m => m.path !== '/admin/vouchers');
}
}
return (
<aside className="sidebar-full" style={{
width: '256px', height: '100vh', position: 'fixed', left: 0, top: 0, zIndex: 40,
background: '#f0f5f8', borderRight: '1px solid rgba(8,45,67,0.06)',
display: 'flex', flexDirection: 'column', padding: '24px',
transition: 'width 0.2s ease, padding 0.2s ease',
}}>
{/* Brand */}
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '36px' }}>
<div className="bg-ember" style={{
width: '40px', height: '40px', borderRadius: '12px',
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: 'white', boxShadow: '0 4px 12px rgba(8,45,67,0.25)',
}}>
<span className="material-symbols-outlined" style={{ fontVariationSettings: "'FILL' 1", fontSize: '22px' }}>storefront</span>
</div>
<div className="sidebar-brand-text">
<h1 className="font-headline" style={{ fontSize: '18px', fontWeight: 700, color: '#0a1f2e', lineHeight: 1.2 }}>XOGM Go</h1>
<p style={{ fontSize: '10px', fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'rgba(8,45,67,0.45)' }}>Sistem Kasir Modern</p>
</div>
</div>
{/* Nav */}
<nav style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '4px', overflowY: 'auto', overflowX: 'hidden' }}>
{menus.map((menu) => {
const navPath = getNavPath(menu.path);
const active = location.pathname === navPath;
return (
<button key={menu.path} onClick={() => navigate(navPath)}
style={{
width: '100%', display: 'flex', alignItems: 'center', gap: '12px',
padding: '12px 16px', borderRadius: '12px', border: 'none', cursor: 'pointer',
fontSize: '13px', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase',
textAlign: 'left', lineHeight: '1.3',
transition: 'all 0.2s',
...(active
? { background: 'linear-gradient(135deg, #082D43, #0e4a6f)', color: 'white', boxShadow: '0 4px 16px rgba(8,45,67,0.25)' }
: { background: 'transparent', color: 'rgba(8,45,67,0.55)' }
),
}}
onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = 'rgba(8,45,67,0.06)'; }}
onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = 'transparent'; }}
>
<span className="material-symbols-outlined" style={{ fontSize: '20px', fontVariationSettings: active ? "'FILL' 1" : "'FILL' 0", flexShrink: 0 }}>
{menu.icon}
</span>
<span className="sidebar-label">{menu.label}</span>
</button>
);
})}
</nav>
{/* Bottom */}
<div style={{ paddingTop: '16px', borderTop: '1px solid rgba(8,45,67,0.06)' }}>
<button className="sidebar-logout" onClick={logout} style={{
width: '100%', display: 'flex', alignItems: 'center', gap: '12px',
padding: '12px 16px', borderRadius: '12px', border: 'none', cursor: 'pointer',
fontSize: '13px', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase',
background: 'transparent', color: 'rgba(8,45,67,0.55)', transition: 'all 0.2s',
}}
onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(8,45,67,0.06)'}
onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
>
<span className="material-symbols-outlined" style={{ fontSize: '20px', flexShrink: 0 }}>logout</span>
<span className="sidebar-label">Keluar</span>
</button>
</div>
</aside>
);
}
|