281 lines
9.5 KiB
TypeScript
281 lines
9.5 KiB
TypeScript
import { usePage } from '@inertiajs/react';
|
|
import type { Icon } from '@tabler/icons-react';
|
|
import { IconGridDots, IconHelp, IconMessageDots } from '@tabler/icons-react';
|
|
import {
|
|
BookOpen,
|
|
Building2,
|
|
Calendar,
|
|
CalendarClock,
|
|
ClipboardCheck,
|
|
ClipboardList,
|
|
FileCheck2,
|
|
FileText,
|
|
GraduationCap,
|
|
Mail,
|
|
Megaphone,
|
|
MessageCircle,
|
|
Receipt,
|
|
School,
|
|
ScrollText,
|
|
ShieldCheck,
|
|
User,
|
|
Users,
|
|
} from 'lucide-react';
|
|
import * as React from 'react';
|
|
|
|
import AppLogoIcon from '@/components/app-logo-icon';
|
|
import type { NavGroup, NavItem } from '@/components/nav-main';
|
|
import { NavMain } from '@/components/nav-main';
|
|
import { NavSecondary } from '@/components/nav-secondary';
|
|
import {
|
|
Sidebar,
|
|
SidebarContent,
|
|
SidebarHeader,
|
|
SidebarMenu,
|
|
SidebarMenuButton,
|
|
SidebarMenuItem,
|
|
} from '@/components/ui/sidebar';
|
|
import { index as assignmentsRoute } from '@/routes/admin/academic-classes/assignments';
|
|
import { index as attendancesRoute } from '@/routes/admin/academic-classes/attendances';
|
|
import { index as materialsRoute } from '@/routes/admin/academic-classes/materials';
|
|
import { index as schedulesRoute } from '@/routes/admin/academic-classes/schedules';
|
|
import { index as logsRoute } from '@/routes/admin/developer/logs';
|
|
import { index as rolePermissionsRoute } from '@/routes/admin/developer/roles';
|
|
import { index as feedbackRoute } from '@/routes/admin/feedback';
|
|
import { index as tuitionInvoicesRoute } from '@/routes/admin/finances/tuition-invoices';
|
|
import { index as announcementsRoute } from '@/routes/admin/manage/announcements';
|
|
import { index as courseClassesRoute } from '@/routes/admin/manage/course-classes';
|
|
import { index as courseRegistrationsRoute } from '@/routes/admin/manage/course-registrations';
|
|
import { index as academicTerm } from '@/routes/admin/master/academic-terms';
|
|
import { index as coursesRoute } from '@/routes/admin/master/courses';
|
|
import { index as departmentsRoute } from '@/routes/admin/master/departments';
|
|
import { index as academicAdvisingLogsRoute } from '@/routes/admin/services/academic-advising-logs';
|
|
import { index as letterRequestsRoute } from '@/routes/admin/services/letter-requests';
|
|
import { index as administratorsRoute } from '@/routes/admin/users/administrators';
|
|
import { index as lecturersRoute } from '@/routes/admin/users/lecturers';
|
|
import { index as studentsRoute } from '@/routes/admin/users/students';
|
|
import { index as lecturerAcademicAdvisingLogsRoute } from '@/routes/lecturer/academic-advising-logs';
|
|
import { index as studentCourseRegistrationsRoute } from '@/routes/student/course-registrations';
|
|
import { index as studentLetterRequestsRoute } from '@/routes/student/letter-requests';
|
|
import type { Auth } from '@/types/auth';
|
|
|
|
const STAFF_ROLES = ['developer', 'staff-admin', 'staff-keuangan', 'kaprodi'];
|
|
|
|
function buildNavMain({
|
|
isMahasiswa,
|
|
isDosen,
|
|
canViewLogs,
|
|
canViewRoles,
|
|
}: {
|
|
isMahasiswa: boolean;
|
|
isDosen: boolean;
|
|
canViewLogs: boolean;
|
|
canViewRoles: boolean;
|
|
}): (NavGroup | NavItem)[] {
|
|
return [
|
|
{
|
|
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,
|
|
},
|
|
]
|
|
: []),
|
|
],
|
|
},
|
|
]
|
|
: []),
|
|
];
|
|
}
|
|
|
|
const navSecondary: { title: string; url: string; icon: Icon }[] = [
|
|
{
|
|
title: 'Kritik dan Saran',
|
|
url: feedbackRoute.url(),
|
|
icon: IconMessageDots,
|
|
},
|
|
{
|
|
title: 'Bantuan',
|
|
url: '#',
|
|
icon: IconHelp,
|
|
},
|
|
];
|
|
|
|
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|
const { name, auth } = usePage<{ auth: Auth }>().props;
|
|
const roleNames = auth?.user?.roles?.map((role) => role.name) ?? [];
|
|
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 navMain = buildNavMain({
|
|
isMahasiswa,
|
|
isDosen,
|
|
canViewLogs,
|
|
canViewRoles,
|
|
});
|
|
|
|
return (
|
|
<Sidebar collapsible="icon" {...props}>
|
|
<SidebarHeader>
|
|
<SidebarMenu>
|
|
<SidebarMenuItem>
|
|
<SidebarMenuButton
|
|
asChild
|
|
className="data-[slot=sidebar-menu-button]:p-1.5!"
|
|
>
|
|
<a href="#">
|
|
<AppLogoIcon className="size-5! rounded-sm object-cover" />
|
|
<span className="text-base font-semibold">
|
|
{name}
|
|
</span>
|
|
</a>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
</SidebarMenu>
|
|
</SidebarHeader>
|
|
<SidebarContent>
|
|
<NavMain items={navMain} />
|
|
<NavSecondary items={navSecondary} className="mt-auto" />
|
|
</SidebarContent>
|
|
</Sidebar>
|
|
);
|
|
}
|