From 4350f7d9ea8b8ccebe23fce5ec64e7a5780b0145 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Mon, 31 Aug 2026 16:34:31 +0700 Subject: [PATCH] feat: refactor navigation structure in AppSidebar to use permissions for dynamic item rendering --- resources/js/components/app-sidebar.tsx | 354 ++++++++++++++---------- 1 file changed, 202 insertions(+), 152 deletions(-) diff --git a/resources/js/components/app-sidebar.tsx b/resources/js/components/app-sidebar.tsx index ae2d1e8..7d77d39 100644 --- a/resources/js/components/app-sidebar.tsx +++ b/resources/js/components/app-sidebar.tsx @@ -64,164 +64,216 @@ const STAFF_ROLES = ['developer', 'staff-admin', 'staff-keuangan', 'kaprodi']; function buildNavMain({ isMahasiswa, isDosen, - canViewLogs, - canViewRoles, + permissions, }: { isMahasiswa: boolean; isDosen: boolean; - canViewLogs: boolean; - canViewRoles: boolean; + permissions: string[]; }): (NavGroup | NavItem)[] { - return [ + const can = (permission: string) => permissions.includes(permission); + + const penggunaItems: NavItem[] = [ + ...(can('view-administrators') + ? [ + { + name: 'Administrator', + url: administratorsRoute.url(), + icon: User, + }, + ] + : []), + ...(can('view-lecturers') + ? [{ name: 'Dosen', url: lecturersRoute.url(), icon: Users }] + : []), + ...(can('view-students') + ? [ + { + name: 'Mahasiswa', + url: studentsRoute.url(), + icon: GraduationCap, + }, + ] + : []), + ]; + + const masterItems: NavItem[] = [ + ...(can('view-academic-terms') + ? [ + { + name: 'Periode Akademik', + url: academicTerm.url(), + icon: Calendar, + }, + ] + : []), + ...(can('view-departments') + ? [ + { + name: 'Jurusan', + url: departmentsRoute.url(), + icon: Building2, + }, + ] + : []), + ...(can('view-courses') + ? [{ name: 'Mata Kuliah', url: coursesRoute.url(), icon: BookOpen }] + : []), + ]; + + const kelolaItems: NavItem[] = [ + ...(isMahasiswa || can('view-course-registrations') + ? [ + { + name: 'Registrasi KRS', + url: isMahasiswa + ? studentCourseRegistrationsRoute.url() + : courseRegistrationsRoute.url(), + icon: FileCheck2, + }, + ] + : []), + ...(can('view-course-classes') + ? [ + { + name: 'Kelas Mata Kuliah', + url: courseClassesRoute.url(), + icon: School, + }, + ] + : []), + ...(can('view-announcements') + ? [ + { + name: 'Pengumuman', + url: announcementsRoute.url(), + icon: Megaphone, + }, + ] + : []), + ]; + + const kelasItems: NavItem[] = [ + ...(can('view-materials') + ? [{ name: 'Materi', url: materialsRoute.url(), icon: FileText }] + : []), + ...(can('view-assignments') + ? [ + { + name: 'Tugas', + url: assignmentsRoute.url(), + icon: ClipboardList, + }, + ] + : []), + ...(can('view-schedules') + ? [ + { + name: 'Jadwal', + url: schedulesRoute.url(), + icon: CalendarClock, + }, + ] + : []), + ...(can('view-attendances') + ? [ + { + name: 'Kehadiran', + url: attendancesRoute.url(), + icon: ClipboardCheck, + }, + ] + : []), + ]; + + const keuanganItems: NavItem[] = [ + ...(can('view-tuition-invoices') + ? [ + { + name: 'Tagihan', + url: tuitionInvoicesRoute.url(), + icon: Receipt, + }, + ] + : []), + ]; + + const layananItems: NavItem[] = [ + ...(isMahasiswa || can('view-letter-requests') + ? [ + { + name: 'Surat Permohonan', + url: isMahasiswa + ? studentLetterRequestsRoute.url() + : letterRequestsRoute.url(), + icon: Mail, + }, + ] + : []), + ...(isDosen || can('view-academic-advising-logs') + ? [ + { + name: 'Bimbingan Akademik', + url: isDosen + ? lecturerAcademicAdvisingLogsRoute.url() + : academicAdvisingLogsRoute.url(), + icon: MessageCircle, + }, + ] + : []), + ]; + + const pengembangItems: NavItem[] = [ + ...(can('view-logs') + ? [{ name: 'Logs', url: logsRoute.url(), icon: ScrollText }] + : []), + ...(can('view-roles') + ? [ + { + name: 'Role & Permission', + url: rolePermissionsRoute.url(), + icon: ShieldCheck, + }, + ] + : []), + ]; + + const groups: (NavGroup | NavItem)[] = [ { name: 'Dasbor', url: '#', icon: IconGridDots, }, - { - label: 'Pengguna', - items: [ - { - name: 'Administrator', - url: administratorsRoute.url(), - icon: User, - }, - { - name: 'Dosen', - url: lecturersRoute.url(), - icon: Users, - }, - { - name: 'Mahasiswa', - url: studentsRoute.url(), - icon: GraduationCap, - }, - ], - }, - { - label: 'Master', - items: [ - { - name: 'Periode Akademik', - url: academicTerm.url(), - icon: Calendar, - }, - { - name: 'Jurusan', - url: departmentsRoute.url(), - icon: Building2, - }, - { - name: 'Mata Kuliah', - url: coursesRoute.url(), - icon: BookOpen, - }, - ], - }, - { - label: 'Kelola', - items: [ - { - name: 'Registrasi KRS', - url: isMahasiswa - ? studentCourseRegistrationsRoute.url() - : courseRegistrationsRoute.url(), - icon: FileCheck2, - }, - { - name: 'Kelas Mata Kuliah', - url: courseClassesRoute.url(), - icon: School, - }, - { - name: 'Pengumuman', - url: announcementsRoute.url(), - icon: Megaphone, - }, - ], - }, - { - label: 'Kelas', - items: [ - { - name: 'Materi', - url: materialsRoute.url(), - icon: FileText, - }, - { - name: 'Tugas', - url: assignmentsRoute.url(), - icon: ClipboardList, - }, - { - name: 'Jadwal', - url: schedulesRoute.url(), - icon: CalendarClock, - }, - { - name: 'Kehadiran', - url: attendancesRoute.url(), - icon: ClipboardCheck, - }, - ], - }, - { - label: 'Keuangan', - items: [ - { - name: 'Tagihan', - url: tuitionInvoicesRoute.url(), - icon: Receipt, - }, - ], - }, - { - label: 'Layanan', - items: [ - { - name: 'Surat Permohonan', - url: isMahasiswa - ? studentLetterRequestsRoute.url() - : letterRequestsRoute.url(), - icon: Mail, - }, - { - name: 'Bimbingan Akademik', - url: isDosen - ? lecturerAcademicAdvisingLogsRoute.url() - : academicAdvisingLogsRoute.url(), - icon: MessageCircle, - }, - ], - }, - ...(canViewLogs || canViewRoles - ? [ - { - label: 'Pengembang', - items: [ - ...(canViewLogs - ? [ - { - name: 'Logs', - url: logsRoute.url(), - icon: ScrollText, - }, - ] - : []), - ...(canViewRoles - ? [ - { - name: 'Role & Permission', - url: rolePermissionsRoute.url(), - icon: ShieldCheck, - }, - ] - : []), - ], - }, - ] - : []), ]; + + if (penggunaItems.length > 0) { + groups.push({ label: 'Pengguna', items: penggunaItems }); + } + + if (masterItems.length > 0) { + groups.push({ label: 'Master', items: masterItems }); + } + + if (kelolaItems.length > 0) { + groups.push({ label: 'Kelola', items: kelolaItems }); + } + + if (kelasItems.length > 0) { + groups.push({ label: 'Kelas', items: kelasItems }); + } + + if (keuanganItems.length > 0) { + groups.push({ label: 'Keuangan', items: keuanganItems }); + } + + if (layananItems.length > 0) { + groups.push({ label: 'Layanan', items: layananItems }); + } + + if (pengembangItems.length > 0) { + groups.push({ label: 'Pengembang', items: pengembangItems }); + } + + return groups; } function buildNavSecondary( @@ -249,13 +301,11 @@ export function AppSidebar({ ...props }: React.ComponentProps) { const isStaff = roleNames.some((role) => STAFF_ROLES.includes(role)); const isMahasiswa = !isStaff && roleNames.includes('mahasiswa'); const isDosen = !isStaff && roleNames.includes('dosen'); - const canViewLogs = (auth?.permissions ?? []).includes('view-logs'); - const canViewRoles = (auth?.permissions ?? []).includes('view-roles'); + const permissions = auth?.permissions ?? []; const navMain = buildNavMain({ isMahasiswa, isDosen, - canViewLogs, - canViewRoles, + permissions, }); return (