diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php
index fb40980..02b9079 100644
--- a/app/Http/Middleware/HandleInertiaRequests.php
+++ b/app/Http/Middleware/HandleInertiaRequests.php
@@ -42,6 +42,7 @@ public function share(Request $request): array
'name' => config('app.name'),
'auth' => [
'user' => $request->user()?->load('roles:id,name'),
+ 'permissions' => $request->user()?->getAllPermissions()->pluck('name')->values() ?? [],
],
'sidebarOpen' => ! $request->hasCookie('sidebar_state') || $request->cookie('sidebar_state') === 'true',
'unreadNotificationsCount' => fn () => $request->user()
diff --git a/bootstrap/app.php b/bootstrap/app.php
index bc4b18f..95a5faf 100644
--- a/bootstrap/app.php
+++ b/bootstrap/app.php
@@ -7,6 +7,7 @@
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets;
use Illuminate\Http\Request;
+use Spatie\Permission\Middleware\PermissionMiddleware;
use Spatie\Permission\Middleware\RoleMiddleware;
return Application::configure(basePath: dirname(__DIR__))
@@ -26,6 +27,7 @@
$middleware->alias([
'role' => RoleMiddleware::class,
+ 'permission' => PermissionMiddleware::class,
]);
})
->withExceptions(function (Exceptions $exceptions): void {
diff --git a/database/seeders/RolePermissionSeeder.php b/database/seeders/RolePermissionSeeder.php
index d4571df..79f3ad9 100644
--- a/database/seeders/RolePermissionSeeder.php
+++ b/database/seeders/RolePermissionSeeder.php
@@ -13,17 +13,55 @@ public function run(): void
{
app()[PermissionRegistrar::class]->forgetCachedPermissions();
- $permissionNames = [
- 'view-dashboard',
- 'view-academic-terms',
- 'create-academic-terms',
- 'update-academic-terms',
- 'delete-academic-terms',
+ $master = [
+ 'view-academic-terms', 'create-academic-terms', 'update-academic-terms', 'delete-academic-terms', 'update-academic-terms-status',
+ 'view-departments', 'create-departments', 'update-departments', 'delete-departments',
+ 'view-courses', 'create-courses', 'update-courses', 'delete-courses',
+ ];
+
+ $academicClasses = [
+ 'view-materials', 'create-materials', 'update-materials', 'delete-materials',
+ 'view-assignments', 'create-assignments', 'update-assignments', 'delete-assignments',
+ 'view-assignment-submissions', 'create-assignment-submissions', 'update-assignment-submissions', 'delete-assignment-submissions',
+ 'view-schedules', 'create-schedules', 'update-schedules', 'delete-schedules',
+ 'view-attendances', 'create-attendances', 'delete-attendances',
+ ];
+
+ $manage = [
+ 'view-course-classes', 'create-course-classes', 'update-course-classes', 'delete-course-classes',
+ 'view-course-class-enrollments', 'create-course-class-enrollments', 'delete-course-class-enrollments',
+ 'view-course-registrations', 'create-course-registrations', 'approve-course-registrations', 'reject-course-registrations',
+ 'view-announcements', 'create-announcements', 'update-announcements', 'delete-announcements',
+ ];
+
+ $finances = [
+ 'view-tuition-invoices', 'create-tuition-invoices', 'update-tuition-invoices', 'delete-tuition-invoices',
+ 'view-tuition-payments', 'create-tuition-payments', 'update-tuition-payments', 'delete-tuition-payments',
+ ];
+
+ $services = [
+ 'view-letter-requests', 'create-letter-requests', 'update-letter-requests', 'delete-letter-requests',
+ 'view-academic-advising-logs', 'create-academic-advising-logs', 'update-academic-advising-logs', 'delete-academic-advising-logs',
+ ];
+
+ $users = [
+ 'view-lecturers', 'create-lecturers', 'update-lecturers', 'delete-lecturers', 'reset-lecturers-password', 'update-lecturers-status', 'export-lecturers',
+ 'view-students', 'create-students', 'update-students', 'delete-students', 'reset-students-password', 'update-students-academic-status', 'update-students-account-status', 'export-students',
+ 'view-administrators', 'create-administrators', 'update-administrators', 'delete-administrators', 'reset-administrators-password', 'update-administrators-status',
+ ];
+
+ $permissionNames = [
+ 'view-dashboard',
+ ...$master,
+ ...$academicClasses,
+ ...$manage,
+ ...$finances,
+ ...$services,
+ ...$users,
];
- $permissions = [];
foreach ($permissionNames as $name) {
- $permissions[] = Permission::firstOrCreate(['name' => $name, 'guard_name' => 'web']);
+ Permission::firstOrCreate(['name' => $name, 'guard_name' => 'web']);
}
app()[PermissionRegistrar::class]->forgetCachedPermissions();
@@ -33,19 +71,30 @@ public function run(): void
'dosen' => ['view-dashboard'],
'staff-admin' => [
'view-dashboard',
- 'view-academic-terms',
- 'create-academic-terms',
- 'update-academic-terms',
- 'delete-academic-terms',
+ ...$master,
+ ...$academicClasses,
+ ...$manage,
+ ...$services,
+ ...$users,
+ ],
+ 'staff-keuangan' => [
+ 'view-dashboard',
+ ...$finances,
+ ],
+ 'kaprodi' => [
+ 'view-dashboard',
+ 'view-academic-terms',
+ 'view-courses',
+ 'view-course-classes',
+ 'view-course-registrations',
+ 'view-students',
],
- 'staff-keuangan' => ['view-dashboard'],
- 'kaprodi' => ['view-dashboard', 'view-academic-terms'],
'developer' => $permissionNames,
];
foreach ($roles as $roleName => $rolePermissions) {
$role = Role::firstOrCreate(['name' => $roleName, 'guard_name' => 'web']);
- $role->givePermissionTo($rolePermissions);
+ $role->syncPermissions($rolePermissions);
}
}
}
diff --git a/resources/js/components/active-status-switch.tsx b/resources/js/components/active-status-switch.tsx
index ddaf9ed..c0c1b8a 100644
--- a/resources/js/components/active-status-switch.tsx
+++ b/resources/js/components/active-status-switch.tsx
@@ -3,15 +3,21 @@ import { Switch } from '@/components/ui/switch';
type ActiveStatusSwitchProps = {
isActive: boolean;
onChange: (isActive: boolean) => void;
+ disabled?: boolean;
};
export function ActiveStatusSwitch({
isActive,
onChange,
+ disabled,
}: ActiveStatusSwitchProps) {
return (
-
+
{isActive ? 'Aktif' : 'Nonaktif'}
diff --git a/resources/js/components/student-status-badge.tsx b/resources/js/components/student-status-badge.tsx
index 8694883..89b47b2 100644
--- a/resources/js/components/student-status-badge.tsx
+++ b/resources/js/components/student-status-badge.tsx
@@ -13,6 +13,7 @@ type StudentStatusBadgeProps = {
status: string | null | undefined;
statuses: StatusOption[];
onChange: (status: string) => void;
+ disabled?: boolean;
};
const StudentStatusVariants: Record<
@@ -29,6 +30,7 @@ export function StudentStatusBadge({
status,
statuses,
onChange,
+ disabled,
}: StudentStatusBadgeProps) {
const label =
statuses.find((option) => option.value === status)?.label ??
@@ -38,10 +40,11 @@ export function StudentStatusBadge({
return (
-
+
diff --git a/resources/js/hooks/use-permissions.ts b/resources/js/hooks/use-permissions.ts
new file mode 100644
index 0000000..0fab45d
--- /dev/null
+++ b/resources/js/hooks/use-permissions.ts
@@ -0,0 +1,17 @@
+import { usePage } from '@inertiajs/react';
+import type { Auth } from '@/types/auth';
+
+export function usePermissions() {
+ const { auth } = usePage<{ auth: Auth }>().props;
+ const permissions = auth?.permissions ?? [];
+
+ function hasPermission(name: string): boolean {
+ return permissions.includes(name);
+ }
+
+ function hasAnyPermission(names: string[]): boolean {
+ return names.some((name) => permissions.includes(name));
+ }
+
+ return { permissions, hasPermission, hasAnyPermission };
+}
diff --git a/resources/js/pages/admin/academic-classes/assignments/columns.tsx b/resources/js/pages/admin/academic-classes/assignments/columns.tsx
index fda93c4..91f638b 100644
--- a/resources/js/pages/admin/academic-classes/assignments/columns.tsx
+++ b/resources/js/pages/admin/academic-classes/assignments/columns.tsx
@@ -10,12 +10,21 @@ export type { Assignment } from '@/types/assignment';
type CreateColumnsParams = {
handleEdit: (assignment: Assignment) => void;
handleDeleteClick: (assignment: Assignment) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
+ canViewSubmissions: boolean;
};
export function createAssignmentColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick } = params;
+ const {
+ handleEdit,
+ handleDeleteClick,
+ canUpdate,
+ canDelete,
+ canViewSubmissions,
+ } = params;
return [
{
@@ -103,11 +112,13 @@ export function createAssignmentColumns(
{
label: 'Pengumpulan',
icon: ,
+ show: canViewSubmissions,
href: submissionsIndex.url(assignment.id),
},
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(assignment),
},
{
@@ -115,6 +126,7 @@ export function createAssignmentColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(assignment),
},
]}
diff --git a/resources/js/pages/admin/academic-classes/assignments/index.tsx b/resources/js/pages/admin/academic-classes/assignments/index.tsx
index ce145a5..5924b90 100644
--- a/resources/js/pages/admin/academic-classes/assignments/index.tsx
+++ b/resources/js/pages/admin/academic-classes/assignments/index.tsx
@@ -22,6 +22,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as assignmentIndex,
@@ -65,6 +66,11 @@ export default function AssignmentIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-assignments');
+ const canUpdate = hasPermission('update-assignments');
+ const canDelete = hasPermission('delete-assignments');
+ const canViewSubmissions = hasPermission('view-assignment-submissions');
const filterFields: FilterField[] = [
{
@@ -109,6 +115,9 @@ export default function AssignmentIndex({
const columns = createAssignmentColumns({
handleEdit: (assignment) => setEditing(assignment),
handleDeleteClick: (assignment) => setDeleting(assignment),
+ canUpdate,
+ canDelete,
+ canViewSubmissions,
});
return (
@@ -141,15 +150,17 @@ export default function AssignmentIndex({
)
}
actions={
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/academic-classes/assignments/submissions.tsx b/resources/js/pages/admin/academic-classes/assignments/submissions.tsx
index 5c3ea93..efd341a 100644
--- a/resources/js/pages/admin/academic-classes/assignments/submissions.tsx
+++ b/resources/js/pages/admin/academic-classes/assignments/submissions.tsx
@@ -24,6 +24,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
+import { usePermissions } from '@/hooks/use-permissions';
import { index as assignmentIndex } from '@/routes/admin/academic-classes/assignments';
import {
destroy,
@@ -48,6 +49,10 @@ export default function SubmissionIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-assignment-submissions');
+ const canUpdate = hasPermission('update-assignment-submissions');
+ const canDelete = hasPermission('delete-assignment-submissions');
function handleDelete() {
if (!deleting) {
@@ -137,6 +142,7 @@ export default function SubmissionIndex({
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => setEditing(row.original),
},
{
@@ -144,6 +150,7 @@ export default function SubmissionIndex({
icon: (
),
+ show: canDelete,
onClick: () => setDeleting(row.original),
},
]}
@@ -193,13 +200,15 @@ export default function SubmissionIndex({
Daftar Pengumpulan
- setCreateOpen(true)}
- disabled={availableStudents.length === 0}
- >
-
- Tambah Pengumpulan
-
+ {canCreate && (
+ setCreateOpen(true)}
+ disabled={availableStudents.length === 0}
+ >
+
+ Tambah Pengumpulan
+
+ )}
diff --git a/resources/js/pages/admin/academic-classes/attendances/index.tsx b/resources/js/pages/admin/academic-classes/attendances/index.tsx
index 525556d..fcbd6e6 100644
--- a/resources/js/pages/admin/academic-classes/attendances/index.tsx
+++ b/resources/js/pages/admin/academic-classes/attendances/index.tsx
@@ -23,6 +23,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
+import { usePermissions } from '@/hooks/use-permissions';
import { destroy, session } from '@/routes/admin/academic-classes/attendances';
import type {
AttendanceCourseClass,
@@ -41,6 +42,9 @@ function courseClassLabel(courseClass: AttendanceCourseClass): string {
export default function AttendanceIndex({ sessions, courseClasses }: Props) {
const [newSessionOpen, setNewSessionOpen] = useState(false);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-attendances');
+ const canDelete = hasPermission('delete-attendances');
function handleDelete() {
if (!deleting || deleting.meeting_number === null) {
@@ -61,10 +65,12 @@ export default function AttendanceIndex({ sessions, courseClasses }: Props) {
setNewSessionOpen(true)}>
-
- Ambil Kehadiran
-
+ canCreate && (
+ setNewSessionOpen(true)}>
+
+ Ambil Kehadiran
+
+ )
}
/>
@@ -129,16 +135,18 @@ export default function AttendanceIndex({ sessions, courseClasses }: Props) {
)}
-
- setDeleting(item)
- }
- >
-
-
+ {canDelete && (
+
+ setDeleting(item)
+ }
+ >
+
+
+ )}
diff --git a/resources/js/pages/admin/academic-classes/attendances/session.tsx b/resources/js/pages/admin/academic-classes/attendances/session.tsx
index 3bd62a1..2fa3dc6 100644
--- a/resources/js/pages/admin/academic-classes/attendances/session.tsx
+++ b/resources/js/pages/admin/academic-classes/attendances/session.tsx
@@ -7,6 +7,7 @@ import { PageHeader } from '@/components/page-header';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Label } from '@/components/ui/label';
+import { usePermissions } from '@/hooks/use-permissions';
import {
index as attendanceIndex,
store,
@@ -45,6 +46,8 @@ export default function AttendanceSession({
),
);
const [saving, setSaving] = useState(false);
+ const { hasPermission } = usePermissions();
+ const canSave = hasPermission('create-attendances');
function setAll(status: AttendanceStatus) {
setStatuses(
@@ -198,7 +201,7 @@ export default function AttendanceSession({
)}
- {roster.length > 0 && (
+ {roster.length > 0 && canSave && (
void;
handleDeleteClick: (material: Material) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
};
export function createMaterialColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick } = params;
+ const { handleEdit, handleDeleteClick, canUpdate, canDelete } = params;
return [
{
@@ -100,6 +102,7 @@ export function createMaterialColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(material),
},
{
@@ -107,6 +110,7 @@ export function createMaterialColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(material),
},
]}
diff --git a/resources/js/pages/admin/academic-classes/materials/index.tsx b/resources/js/pages/admin/academic-classes/materials/index.tsx
index a20424b..b33f1a0 100644
--- a/resources/js/pages/admin/academic-classes/materials/index.tsx
+++ b/resources/js/pages/admin/academic-classes/materials/index.tsx
@@ -21,6 +21,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as materialIndex,
@@ -64,6 +65,10 @@ export default function MaterialIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-materials');
+ const canUpdate = hasPermission('update-materials');
+ const canDelete = hasPermission('delete-materials');
const filterFields: FilterField[] = [
{
@@ -108,6 +113,8 @@ export default function MaterialIndex({
const columns = createMaterialColumns({
handleEdit: (material) => setEditing(material),
handleDeleteClick: (material) => setDeleting(material),
+ canUpdate,
+ canDelete,
});
return (
@@ -140,15 +147,17 @@ export default function MaterialIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/academic-classes/schedules/index.tsx b/resources/js/pages/admin/academic-classes/schedules/index.tsx
index e637333..e04c140 100644
--- a/resources/js/pages/admin/academic-classes/schedules/index.tsx
+++ b/resources/js/pages/admin/academic-classes/schedules/index.tsx
@@ -18,6 +18,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
+import { usePermissions } from '@/hooks/use-permissions';
import { cn } from '@/lib/utils';
import {
destroy,
@@ -58,6 +59,10 @@ export default function ScheduleIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-schedules');
+ const canUpdate = hasPermission('update-schedules');
+ const canDelete = hasPermission('delete-schedules');
function handleDelete() {
if (!deleting) {
@@ -89,15 +94,17 @@ export default function ScheduleIndex({
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
@@ -177,6 +184,7 @@ export default function ScheduleIndex({
icon: (
),
+ show: canUpdate,
onClick:
() =>
setEditing(
@@ -188,6 +196,7 @@ export default function ScheduleIndex({
icon: (
),
+ show: canDelete,
onClick:
() =>
setDeleting(
diff --git a/resources/js/pages/admin/finances/tuition-invoices/columns.tsx b/resources/js/pages/admin/finances/tuition-invoices/columns.tsx
index 29abff7..93d839f 100644
--- a/resources/js/pages/admin/finances/tuition-invoices/columns.tsx
+++ b/resources/js/pages/admin/finances/tuition-invoices/columns.tsx
@@ -14,12 +14,21 @@ export type { TuitionInvoice } from '@/types/tuition-invoice';
type CreateColumnsParams = {
handleEdit: (invoice: TuitionInvoice) => void;
handleDeleteClick: (invoice: TuitionInvoice) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
+ canViewPayments: boolean;
};
export function createTuitionInvoiceColumns(
params: CreateColumnsParams,
): ColumnDef
[] {
- const { handleEdit, handleDeleteClick } = params;
+ const {
+ handleEdit,
+ handleDeleteClick,
+ canUpdate,
+ canDelete,
+ canViewPayments,
+ } = params;
return [
{
@@ -133,11 +142,13 @@ export function createTuitionInvoiceColumns(
{
label: 'Pembayaran',
icon: ,
+ show: canViewPayments,
href: paymentsIndex.url(invoice.id),
},
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(invoice),
},
{
@@ -145,6 +156,7 @@ export function createTuitionInvoiceColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(invoice),
},
]}
diff --git a/resources/js/pages/admin/finances/tuition-invoices/index.tsx b/resources/js/pages/admin/finances/tuition-invoices/index.tsx
index 34a51e0..4ae99fd 100644
--- a/resources/js/pages/admin/finances/tuition-invoices/index.tsx
+++ b/resources/js/pages/admin/finances/tuition-invoices/index.tsx
@@ -47,6 +47,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import { formatRupiah } from '@/lib/currency';
import {
@@ -115,6 +116,11 @@ export default function TuitionInvoiceIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-tuition-invoices');
+ const canUpdate = hasPermission('update-tuition-invoices');
+ const canDelete = hasPermission('delete-tuition-invoices');
+ const canViewPayments = hasPermission('view-tuition-payments');
const filterFields: FilterField[] = [
{
@@ -175,6 +181,9 @@ export default function TuitionInvoiceIndex({
const columns = createTuitionInvoiceColumns({
handleEdit: (invoice) => setEditing(invoice),
handleDeleteClick: (invoice) => setDeleting(invoice),
+ canUpdate,
+ canDelete,
+ canViewPayments,
});
return (
@@ -192,15 +201,17 @@ export default function TuitionInvoiceIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/finances/tuition-invoices/payments.tsx b/resources/js/pages/admin/finances/tuition-invoices/payments.tsx
index f318091..476efbf 100644
--- a/resources/js/pages/admin/finances/tuition-invoices/payments.tsx
+++ b/resources/js/pages/admin/finances/tuition-invoices/payments.tsx
@@ -18,6 +18,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Label } from '@/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Textarea } from '@/components/ui/textarea';
+import { usePermissions } from '@/hooks/use-permissions';
import { formatRupiah } from '@/lib/currency';
import { index as tuitionInvoiceIndex } from '@/routes/admin/finances/tuition-invoices';
import {
@@ -43,6 +44,10 @@ export default function TuitionPaymentIndex({ invoice, payments }: Props) {
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-tuition-payments');
+ const canUpdate = hasPermission('update-tuition-payments');
+ const canDelete = hasPermission('delete-tuition-payments');
function handleDelete() {
if (!deleting) {
@@ -156,6 +161,7 @@ export default function TuitionPaymentIndex({ invoice, payments }: Props) {
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => setEditing(row.original),
},
{
@@ -163,6 +169,7 @@ export default function TuitionPaymentIndex({ invoice, payments }: Props) {
icon: (
),
+ show: canDelete,
onClick: () => setDeleting(row.original),
},
]}
@@ -231,7 +238,7 @@ export default function TuitionPaymentIndex({ invoice, payments }: Props) {
Riwayat Pembayaran
- {!isFullyPaid && (
+ {!isFullyPaid && canCreate && (
setCreateOpen(true)}>
Tambah Pembayaran
diff --git a/resources/js/pages/admin/manage/announcements/columns.tsx b/resources/js/pages/admin/manage/announcements/columns.tsx
index ed2e9ac..844d6dd 100644
--- a/resources/js/pages/admin/manage/announcements/columns.tsx
+++ b/resources/js/pages/admin/manage/announcements/columns.tsx
@@ -10,12 +10,14 @@ export type { Announcement } from '@/types/announcement';
type CreateColumnsParams = {
handleEdit: (announcement: Announcement) => void;
handleDeleteClick: (announcement: Announcement) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
};
export function createAnnouncementColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick } = params;
+ const { handleEdit, handleDeleteClick, canUpdate, canDelete } = params;
return [
{
@@ -82,6 +84,7 @@ export function createAnnouncementColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(row.original),
},
{
@@ -89,6 +92,7 @@ export function createAnnouncementColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(row.original),
},
]}
diff --git a/resources/js/pages/admin/manage/announcements/index.tsx b/resources/js/pages/admin/manage/announcements/index.tsx
index 0cb7279..6336c25 100644
--- a/resources/js/pages/admin/manage/announcements/index.tsx
+++ b/resources/js/pages/admin/manage/announcements/index.tsx
@@ -20,6 +20,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as announcementIndex,
@@ -58,6 +59,10 @@ export default function AnnouncementIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-announcements');
+ const canUpdate = hasPermission('update-announcements');
+ const canDelete = hasPermission('delete-announcements');
const filterFields: FilterField[] = [
{
@@ -102,6 +107,8 @@ export default function AnnouncementIndex({
const columns = createAnnouncementColumns({
handleEdit: (announcement) => setEditing(announcement),
handleDeleteClick: (announcement) => setDeleting(announcement),
+ canUpdate,
+ canDelete,
});
return (
@@ -119,15 +126,17 @@ export default function AnnouncementIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/manage/course-classes/columns.tsx b/resources/js/pages/admin/manage/course-classes/columns.tsx
index ea96d9c..fba81e6 100644
--- a/resources/js/pages/admin/manage/course-classes/columns.tsx
+++ b/resources/js/pages/admin/manage/course-classes/columns.tsx
@@ -12,12 +12,21 @@ export type { CourseClass } from '@/types/course-class';
type CreateColumnsParams = {
handleEdit: (courseClass: CourseClass) => void;
handleDeleteClick: (courseClass: CourseClass) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
+ canViewEnrollments: boolean;
};
export function createCourseClassColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick } = params;
+ const {
+ handleEdit,
+ handleDeleteClick,
+ canUpdate,
+ canDelete,
+ canViewEnrollments,
+ } = params;
return [
{
@@ -97,11 +106,13 @@ export function createCourseClassColumns(
{
label: 'Peserta',
icon: ,
+ show: canViewEnrollments,
href: enrollmentsIndex.url(courseClass.id),
},
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(courseClass),
},
{
@@ -109,6 +120,7 @@ export function createCourseClassColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(courseClass),
},
]}
diff --git a/resources/js/pages/admin/manage/course-classes/enrollments.tsx b/resources/js/pages/admin/manage/course-classes/enrollments.tsx
index 6a45aa8..12d4640 100644
--- a/resources/js/pages/admin/manage/course-classes/enrollments.tsx
+++ b/resources/js/pages/admin/manage/course-classes/enrollments.tsx
@@ -13,6 +13,7 @@ import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
+import { usePermissions } from '@/hooks/use-permissions';
import { index as courseClassIndex } from '@/routes/admin/manage/course-classes';
import {
destroy,
@@ -39,6 +40,9 @@ export default function ClassEnrollmentIndex({
}: Props) {
const [createOpen, setCreateOpen] = useState(false);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-course-class-enrollments');
+ const canDelete = hasPermission('delete-course-class-enrollments');
function handleDelete() {
if (!deleting) {
@@ -93,6 +97,7 @@ export default function ClassEnrollmentIndex({
icon: (
),
+ show: canDelete,
onClick: () => setDeleting(row.original),
},
]}
@@ -152,10 +157,12 @@ export default function ClassEnrollmentIndex({
Daftar Mahasiswa
- setCreateOpen(true)}>
-
- Tambah Mahasiswa
-
+ {canCreate && (
+ setCreateOpen(true)}>
+
+ Tambah Mahasiswa
+
+ )}
diff --git a/resources/js/pages/admin/manage/course-classes/index.tsx b/resources/js/pages/admin/manage/course-classes/index.tsx
index 564c896..76fae96 100644
--- a/resources/js/pages/admin/manage/course-classes/index.tsx
+++ b/resources/js/pages/admin/manage/course-classes/index.tsx
@@ -26,6 +26,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as courseClassIndex,
@@ -76,6 +77,11 @@ export default function CourseClassIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-course-classes');
+ const canUpdate = hasPermission('update-course-classes');
+ const canDelete = hasPermission('delete-course-classes');
+ const canViewEnrollments = hasPermission('view-course-class-enrollments');
const filterFields: FilterField[] = [
{
@@ -128,6 +134,9 @@ export default function CourseClassIndex({
const columns = createCourseClassColumns({
handleEdit: (courseClass) => setEditing(courseClass),
handleDeleteClick: (courseClass) => setDeleting(courseClass),
+ canUpdate,
+ canDelete,
+ canViewEnrollments,
});
return (
@@ -160,15 +169,17 @@ export default function CourseClassIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/manage/course-registrations/columns.tsx b/resources/js/pages/admin/manage/course-registrations/columns.tsx
index db7b39d..b4627d3 100644
--- a/resources/js/pages/admin/manage/course-registrations/columns.tsx
+++ b/resources/js/pages/admin/manage/course-registrations/columns.tsx
@@ -11,12 +11,14 @@ export type { CourseRegistrationSubmission } from '@/types/course-registration';
type CreateColumnsParams = {
handleApprove: (submission: CourseRegistrationSubmission) => void;
handleRejectClick: (submission: CourseRegistrationSubmission) => void;
+ canApprove: boolean;
+ canReject: boolean;
};
export function createCourseRegistrationColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleApprove, handleRejectClick } = params;
+ const { handleApprove, handleRejectClick, canApprove, canReject } = params;
return [
{
@@ -105,14 +107,18 @@ export function createCourseRegistrationColumns(
label: 'Setujui',
icon: ,
iconClassName: 'text-primary',
- show: submission.status === 'submitted',
+ show:
+ submission.status === 'submitted' &&
+ canApprove,
onClick: () => handleApprove(submission),
},
{
label: 'Tolak',
icon: ,
iconClassName: 'text-destructive',
- show: submission.status === 'submitted',
+ show:
+ submission.status === 'submitted' &&
+ canReject,
onClick: () => handleRejectClick(submission),
},
]}
diff --git a/resources/js/pages/admin/manage/course-registrations/index.tsx b/resources/js/pages/admin/manage/course-registrations/index.tsx
index 00e62fd..afa1405 100644
--- a/resources/js/pages/admin/manage/course-registrations/index.tsx
+++ b/resources/js/pages/admin/manage/course-registrations/index.tsx
@@ -27,6 +27,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as courseRegistrationIndex,
@@ -92,6 +93,10 @@ export default function CourseRegistrationIndex({
const [createOpen, setCreateOpen] = useState(false);
const [rejecting, setRejecting] =
useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-course-registrations');
+ const canApprove = hasPermission('approve-course-registrations');
+ const canReject = hasPermission('reject-course-registrations');
const filterFields: FilterField[] = [
{
@@ -138,6 +143,8 @@ export default function CourseRegistrationIndex({
const columns = createCourseRegistrationColumns({
handleApprove,
handleRejectClick: (submission) => setRejecting(submission),
+ canApprove,
+ canReject,
});
return (
@@ -155,15 +162,17 @@ export default function CourseRegistrationIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/master/academic-terms/columns.tsx b/resources/js/pages/admin/master/academic-terms/columns.tsx
index 8697413..7ef8cdf 100644
--- a/resources/js/pages/admin/master/academic-terms/columns.tsx
+++ b/resources/js/pages/admin/master/academic-terms/columns.tsx
@@ -12,12 +12,22 @@ type CreateColumnsParams = {
handleEdit: (academicTerm: AcademicTerm) => void;
handleDeleteClick: (academicTerm: AcademicTerm) => void;
handleStatusChange: (academicTerm: AcademicTerm, isActive: boolean) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
+ canUpdateStatus: boolean;
};
export function createAcademicTermColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick, handleStatusChange } = params;
+ const {
+ handleEdit,
+ handleDeleteClick,
+ handleStatusChange,
+ canUpdate,
+ canDelete,
+ canUpdateStatus,
+ } = params;
return [
{
@@ -73,6 +83,7 @@ export function createAcademicTermColumns(
onChange={(isActive) =>
handleStatusChange(academicTerm, isActive)
}
+ disabled={!canUpdateStatus}
/>
);
@@ -94,6 +105,7 @@ export function createAcademicTermColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(academicTerm),
},
{
@@ -101,6 +113,7 @@ export function createAcademicTermColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(academicTerm),
},
]}
diff --git a/resources/js/pages/admin/master/academic-terms/index.tsx b/resources/js/pages/admin/master/academic-terms/index.tsx
index 2e1ae8c..2697870 100644
--- a/resources/js/pages/admin/master/academic-terms/index.tsx
+++ b/resources/js/pages/admin/master/academic-terms/index.tsx
@@ -15,6 +15,7 @@ import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as academicTermIndex,
@@ -69,6 +70,11 @@ export default function AcademicTermIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-academic-terms');
+ const canUpdate = hasPermission('update-academic-terms');
+ const canDelete = hasPermission('delete-academic-terms');
+ const canUpdateStatus = hasPermission('update-academic-terms-status');
const pagination: PaginationState = {
current_page: academicTerms.current_page,
@@ -111,6 +117,9 @@ export default function AcademicTermIndex({
handleEdit: (academicTerm) => setEditing(academicTerm),
handleDeleteClick: (academicTerm) => setDeleting(academicTerm),
handleStatusChange,
+ canUpdate,
+ canDelete,
+ canUpdateStatus,
});
return (
@@ -143,15 +152,17 @@ export default function AcademicTermIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/master/courses/columns.tsx b/resources/js/pages/admin/master/courses/columns.tsx
index 4cedae4..77ffc44 100644
--- a/resources/js/pages/admin/master/courses/columns.tsx
+++ b/resources/js/pages/admin/master/courses/columns.tsx
@@ -9,12 +9,14 @@ export type { Course } from '@/types/course';
type CreateColumnsParams = {
handleEdit: (course: Course) => void;
handleDeleteClick: (course: Course) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
};
export function createCourseColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick } = params;
+ const { handleEdit, handleDeleteClick, canUpdate, canDelete } = params;
return [
{
@@ -87,6 +89,7 @@ export function createCourseColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(course),
},
{
@@ -94,6 +97,7 @@ export function createCourseColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(course),
},
]}
diff --git a/resources/js/pages/admin/master/courses/index.tsx b/resources/js/pages/admin/master/courses/index.tsx
index c5b07c0..df764a9 100644
--- a/resources/js/pages/admin/master/courses/index.tsx
+++ b/resources/js/pages/admin/master/courses/index.tsx
@@ -19,6 +19,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as courseIndex,
@@ -59,6 +60,10 @@ export default function CourseIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-courses');
+ const canUpdate = hasPermission('update-courses');
+ const canDelete = hasPermission('delete-courses');
const filterFields: FilterField[] = [
{
@@ -111,6 +116,8 @@ export default function CourseIndex({
const columns = createCourseColumns({
handleEdit: (course) => setEditing(course),
handleDeleteClick: (course) => setDeleting(course),
+ canUpdate,
+ canDelete,
});
return (
@@ -143,15 +150,17 @@ export default function CourseIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/master/departments/columns.tsx b/resources/js/pages/admin/master/departments/columns.tsx
index 2b72cae..ce1babf 100644
--- a/resources/js/pages/admin/master/departments/columns.tsx
+++ b/resources/js/pages/admin/master/departments/columns.tsx
@@ -9,12 +9,14 @@ export type { Department } from '@/types/department';
type CreateColumnsParams = {
handleEdit: (department: Department) => void;
handleDeleteClick: (department: Department) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
};
export function createDepartmentColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick } = params;
+ const { handleEdit, handleDeleteClick, canUpdate, canDelete } = params;
return [
{
@@ -69,6 +71,7 @@ export function createDepartmentColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(department),
},
{
@@ -76,6 +79,7 @@ export function createDepartmentColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(department),
},
]}
diff --git a/resources/js/pages/admin/master/departments/index.tsx b/resources/js/pages/admin/master/departments/index.tsx
index e43e44b..362532b 100644
--- a/resources/js/pages/admin/master/departments/index.tsx
+++ b/resources/js/pages/admin/master/departments/index.tsx
@@ -17,6 +17,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as departmentIndex,
@@ -43,6 +44,10 @@ export default function DepartmentIndex({ departments, highlight }: Props) {
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-departments');
+ const canUpdate = hasPermission('update-departments');
+ const canDelete = hasPermission('delete-departments');
const pagination: PaginationState = {
current_page: departments.current_page,
@@ -74,6 +79,8 @@ export default function DepartmentIndex({ departments, highlight }: Props) {
const columns = createDepartmentColumns({
handleEdit: (department) => setEditing(department),
handleDeleteClick: (department) => setDeleting(department),
+ canUpdate,
+ canDelete,
});
return (
@@ -106,15 +113,17 @@ export default function DepartmentIndex({ departments, highlight }: Props) {
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/services/academic-advising-logs/columns.tsx b/resources/js/pages/admin/services/academic-advising-logs/columns.tsx
index 36c0edf..db1de0e 100644
--- a/resources/js/pages/admin/services/academic-advising-logs/columns.tsx
+++ b/resources/js/pages/admin/services/academic-advising-logs/columns.tsx
@@ -9,12 +9,14 @@ export type { AcademicAdvisingLog } from '@/types/academic-advising-log';
type CreateColumnsParams = {
handleEdit: (log: AcademicAdvisingLog) => void;
handleDeleteClick: (log: AcademicAdvisingLog) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
};
export function createAcademicAdvisingLogColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick } = params;
+ const { handleEdit, handleDeleteClick, canUpdate, canDelete } = params;
return [
{
@@ -83,6 +85,7 @@ export function createAcademicAdvisingLogColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(row.original),
},
{
@@ -90,6 +93,7 @@ export function createAcademicAdvisingLogColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(row.original),
},
]}
diff --git a/resources/js/pages/admin/services/academic-advising-logs/index.tsx b/resources/js/pages/admin/services/academic-advising-logs/index.tsx
index 88d479d..427ef61 100644
--- a/resources/js/pages/admin/services/academic-advising-logs/index.tsx
+++ b/resources/js/pages/admin/services/academic-advising-logs/index.tsx
@@ -21,6 +21,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as academicAdvisingLogIndex,
@@ -69,6 +70,10 @@ export default function AcademicAdvisingLogIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-academic-advising-logs');
+ const canUpdate = hasPermission('update-academic-advising-logs');
+ const canDelete = hasPermission('delete-academic-advising-logs');
const filterFields: FilterField[] = [
{
@@ -113,6 +118,8 @@ export default function AcademicAdvisingLogIndex({
const columns = createAcademicAdvisingLogColumns({
handleEdit: (log) => setEditing(log),
handleDeleteClick: (log) => setDeleting(log),
+ canUpdate,
+ canDelete,
});
return (
@@ -130,15 +137,17 @@ export default function AcademicAdvisingLogIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/services/letter-requests/columns.tsx b/resources/js/pages/admin/services/letter-requests/columns.tsx
index 9b63224..d0745f0 100644
--- a/resources/js/pages/admin/services/letter-requests/columns.tsx
+++ b/resources/js/pages/admin/services/letter-requests/columns.tsx
@@ -11,12 +11,14 @@ export type { LetterRequest } from '@/types/letter-request';
type CreateColumnsParams = {
handleEdit: (letterRequest: LetterRequest) => void;
handleDeleteClick: (letterRequest: LetterRequest) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
};
export function createLetterRequestColumns(
params: CreateColumnsParams,
): ColumnDef[] {
- const { handleEdit, handleDeleteClick } = params;
+ const { handleEdit, handleDeleteClick, canUpdate, canDelete } = params;
return [
{
@@ -143,6 +145,7 @@ export function createLetterRequestColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(row.original),
},
{
@@ -150,6 +153,7 @@ export function createLetterRequestColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(row.original),
},
]}
diff --git a/resources/js/pages/admin/services/letter-requests/index.tsx b/resources/js/pages/admin/services/letter-requests/index.tsx
index 6c56f90..0e925a1 100644
--- a/resources/js/pages/admin/services/letter-requests/index.tsx
+++ b/resources/js/pages/admin/services/letter-requests/index.tsx
@@ -21,6 +21,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as letterRequestIndex,
@@ -63,6 +64,10 @@ export default function LetterRequestIndex({
const [createOpen, setCreateOpen] = useState(false);
const [editing, setEditing] = useState(null);
const [deleting, setDeleting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-letter-requests');
+ const canUpdate = hasPermission('update-letter-requests');
+ const canDelete = hasPermission('delete-letter-requests');
const filterFields: FilterField[] = [
{
@@ -107,6 +112,8 @@ export default function LetterRequestIndex({
const columns = createLetterRequestColumns({
handleEdit: (letterRequest) => setEditing(letterRequest),
handleDeleteClick: (letterRequest) => setDeleting(letterRequest),
+ canUpdate,
+ canDelete,
});
return (
@@ -124,15 +131,17 @@ export default function LetterRequestIndex({
)
}
actions={
-
- setCreateOpen(true)}
- >
-
- Tambah
-
-
+ canCreate && (
+
+ setCreateOpen(true)}
+ >
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/users/administrators/columns.tsx b/resources/js/pages/admin/users/administrators/columns.tsx
index 54da5e5..881f3ba 100644
--- a/resources/js/pages/admin/users/administrators/columns.tsx
+++ b/resources/js/pages/admin/users/administrators/columns.tsx
@@ -18,6 +18,10 @@ type CreateColumnsParams = {
handleDeleteClick: (admin: Administrator) => void;
handleResetPassword: (admin: Administrator) => void;
handleUserStatusChange: (admin: Administrator, isActive: boolean) => void;
+ canUpdate: boolean;
+ canResetPassword: boolean;
+ canDelete: boolean;
+ canUpdateStatus: boolean;
};
export function createAdministratorColumns(
@@ -28,6 +32,10 @@ export function createAdministratorColumns(
handleDeleteClick,
handleResetPassword,
handleUserStatusChange,
+ canUpdate,
+ canResetPassword,
+ canDelete,
+ canUpdateStatus,
} = params;
return [
@@ -74,6 +82,7 @@ export function createAdministratorColumns(
onChange={(isActive) =>
handleUserStatusChange(row.original, isActive)
}
+ disabled={!canUpdateStatus}
/>
),
},
@@ -93,11 +102,13 @@ export function createAdministratorColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(admin),
},
{
label: 'Reset Kata Sandi',
icon: ,
+ show: canResetPassword,
onClick: () => handleResetPassword(admin),
},
{
@@ -105,6 +116,7 @@ export function createAdministratorColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(admin),
},
]}
diff --git a/resources/js/pages/admin/users/administrators/index.tsx b/resources/js/pages/admin/users/administrators/index.tsx
index d8ec5f1..ad23fe7 100644
--- a/resources/js/pages/admin/users/administrators/index.tsx
+++ b/resources/js/pages/admin/users/administrators/index.tsx
@@ -9,6 +9,7 @@ import type { FilterField } from '@/components/filter-dialog';
import { FilterDialog } from '@/components/filter-dialog';
import { PageHeader } from '@/components/page-header';
import { Button } from '@/components/ui/button';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as administratorsIndex,
@@ -48,6 +49,8 @@ const filterFields: FilterField[] = [
export default function AdministratorIndex({ administrators, filters }: Props) {
const [deleting, setDeleting] = useState(null);
const [resetting, setResetting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-administrators');
const pagination: PaginationState = {
current_page: administrators.current_page,
@@ -107,6 +110,10 @@ export default function AdministratorIndex({ administrators, filters }: Props) {
handleDeleteClick: (admin) => setDeleting(admin),
handleResetPassword: (admin) => setResetting(admin),
handleUserStatusChange,
+ canUpdate: hasPermission('update-administrators'),
+ canResetPassword: hasPermission('reset-administrators-password'),
+ canDelete: hasPermission('delete-administrators'),
+ canUpdateStatus: hasPermission('update-administrators-status'),
});
return (
@@ -117,12 +124,14 @@ export default function AdministratorIndex({ administrators, filters }: Props) {
-
-
- Tambah
-
-
+ canCreate && (
+
+
+
+ Tambah
+
+
+ )
}
/>
diff --git a/resources/js/pages/admin/users/lecturers/columns.tsx b/resources/js/pages/admin/users/lecturers/columns.tsx
index b82f6b2..6446291 100644
--- a/resources/js/pages/admin/users/lecturers/columns.tsx
+++ b/resources/js/pages/admin/users/lecturers/columns.tsx
@@ -21,6 +21,10 @@ type CreateColumnsParams = {
handleDeleteClick: (lecturer: Lecturer) => void;
handleResetPassword: (lecturer: Lecturer) => void;
handleUserStatusChange: (lecturer: Lecturer, isActive: boolean) => void;
+ canUpdate: boolean;
+ canDelete: boolean;
+ canResetPassword: boolean;
+ canUpdateStatus: boolean;
};
export function createLecturerColumns(
@@ -31,6 +35,10 @@ export function createLecturerColumns(
handleDeleteClick,
handleResetPassword,
handleUserStatusChange,
+ canUpdate,
+ canDelete,
+ canResetPassword,
+ canUpdateStatus,
} = params;
return [
@@ -92,6 +100,7 @@ export function createLecturerColumns(
onChange={(isActive) =>
handleUserStatusChange(row.original, isActive)
}
+ disabled={!canUpdateStatus}
/>
),
},
@@ -111,11 +120,13 @@ export function createLecturerColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(lecturer),
},
{
label: 'Reset Kata Sandi',
icon: ,
+ show: canResetPassword,
onClick: () => handleResetPassword(lecturer),
},
{
@@ -123,6 +134,7 @@ export function createLecturerColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(lecturer),
},
]}
diff --git a/resources/js/pages/admin/users/lecturers/index.tsx b/resources/js/pages/admin/users/lecturers/index.tsx
index eebdda2..ad3008a 100644
--- a/resources/js/pages/admin/users/lecturers/index.tsx
+++ b/resources/js/pages/admin/users/lecturers/index.tsx
@@ -9,6 +9,7 @@ import type { FilterField } from '@/components/filter-dialog';
import { FilterDialog } from '@/components/filter-dialog';
import { PageHeader } from '@/components/page-header';
import { Button } from '@/components/ui/button';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
index as lecturersIndex,
@@ -47,6 +48,13 @@ export default function LecturerIndex({
}: Props) {
const [deleting, setDeleting] = useState(null);
const [resetting, setResetting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-lecturers');
+ const canUpdate = hasPermission('update-lecturers');
+ const canDelete = hasPermission('delete-lecturers');
+ const canResetPassword = hasPermission('reset-lecturers-password');
+ const canUpdateStatus = hasPermission('update-lecturers-status');
+ const canExport = hasPermission('export-lecturers');
const filterFields: FilterField[] = [
{
@@ -125,6 +133,10 @@ export default function LecturerIndex({
handleDeleteClick: (lecturer) => setDeleting(lecturer),
handleResetPassword: (lecturer) => setResetting(lecturer),
handleUserStatusChange,
+ canUpdate,
+ canDelete,
+ canResetPassword,
+ canUpdateStatus,
});
return (
@@ -136,22 +148,26 @@ export default function LecturerIndex({
title="Dosen"
actions={
-
-
-
- Export
-
-
-
-
-
- Tambah
-
-
+ {canExport && (
+
+
+
+ Export
+
+
+ )}
+ {canCreate && (
+
+
+
+ Tambah
+
+
+ )}
}
/>
diff --git a/resources/js/pages/admin/users/students/columns.tsx b/resources/js/pages/admin/users/students/columns.tsx
index 631c7e4..467581e 100644
--- a/resources/js/pages/admin/users/students/columns.tsx
+++ b/resources/js/pages/admin/users/students/columns.tsx
@@ -29,6 +29,11 @@ type CreateColumnsParams = {
handleStatusChange: (student: Student, status: string) => void;
handleUserStatusChange: (student: Student, isActive: boolean) => void;
statuses: StatusOption[];
+ canUpdate: boolean;
+ canDelete: boolean;
+ canResetPassword: boolean;
+ canUpdateAcademicStatus: boolean;
+ canUpdateAccountStatus: boolean;
};
export function createStudentColumns(
@@ -41,6 +46,11 @@ export function createStudentColumns(
handleStatusChange,
handleUserStatusChange,
statuses,
+ canUpdate,
+ canDelete,
+ canResetPassword,
+ canUpdateAcademicStatus,
+ canUpdateAccountStatus,
} = params;
return [
@@ -93,6 +103,7 @@ export function createStudentColumns(
onChange={(status) =>
handleStatusChange(row.original, status)
}
+ disabled={!canUpdateAcademicStatus}
/>
),
},
@@ -117,6 +128,7 @@ export function createStudentColumns(
onChange={(isActive) =>
handleUserStatusChange(row.original, isActive)
}
+ disabled={!canUpdateAccountStatus}
/>
),
},
@@ -136,11 +148,13 @@ export function createStudentColumns(
{
label: 'Edit',
icon: ,
+ show: canUpdate,
onClick: () => handleEdit(student),
},
{
label: 'Reset Kata Sandi',
icon: ,
+ show: canResetPassword,
onClick: () => handleResetPassword(student),
},
{
@@ -148,6 +162,7 @@ export function createStudentColumns(
icon: (
),
+ show: canDelete,
onClick: () => handleDeleteClick(student),
},
]}
diff --git a/resources/js/pages/admin/users/students/index.tsx b/resources/js/pages/admin/users/students/index.tsx
index 252471b..e77d6a1 100644
--- a/resources/js/pages/admin/users/students/index.tsx
+++ b/resources/js/pages/admin/users/students/index.tsx
@@ -10,6 +10,7 @@ import { FilterDialog } from '@/components/filter-dialog';
import { PageHeader } from '@/components/page-header';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
+import { usePermissions } from '@/hooks/use-permissions';
import { useServerTable } from '@/hooks/use-server-table';
import {
create,
@@ -56,6 +57,18 @@ export default function StudentIndex({
}: Props) {
const [deleting, setDeleting] = useState(null);
const [resetting, setResetting] = useState(null);
+ const { hasPermission } = usePermissions();
+ const canCreate = hasPermission('create-students');
+ const canUpdate = hasPermission('update-students');
+ const canDelete = hasPermission('delete-students');
+ const canResetPassword = hasPermission('reset-students-password');
+ const canUpdateAcademicStatus = hasPermission(
+ 'update-students-academic-status',
+ );
+ const canUpdateAccountStatus = hasPermission(
+ 'update-students-account-status',
+ );
+ const canExport = hasPermission('export-students');
const filterFields: FilterField[] = [
{
@@ -157,6 +170,11 @@ export default function StudentIndex({
handleStatusChange,
handleUserStatusChange,
statuses,
+ canUpdate,
+ canDelete,
+ canResetPassword,
+ canUpdateAcademicStatus,
+ canUpdateAccountStatus,
});
return (
@@ -168,22 +186,26 @@ export default function StudentIndex({
title="Mahasiswa"
actions={
-
-
-
- Export
-
-
-
-
-
- Tambah
-
-
+ {canExport && (
+
+
+
+ Export
+
+
+ )}
+ {canCreate && (
+
+
+
+ Tambah
+
+
+ )}
}
/>
diff --git a/resources/js/types/auth.ts b/resources/js/types/auth.ts
index 716f0cc..2f78729 100644
--- a/resources/js/types/auth.ts
+++ b/resources/js/types/auth.ts
@@ -14,4 +14,5 @@ export type User = {
export type Auth = {
user: User;
+ permissions?: string[];
};
diff --git a/routes/admin.php b/routes/admin.php
index fd292e5..76107e0 100644
--- a/routes/admin.php
+++ b/routes/admin.php
@@ -26,62 +26,105 @@
Route::middleware(['auth', 'verified'])->group(function () {
Route::prefix('admin/master')->name('admin.master.')->group(function () {
- Route::resource('academic-terms', AcademicTermController::class)->except(['create', 'edit', 'show']);
- Route::patch('academic-terms/{academic_term}/status', [AcademicTermController::class, 'updateStatus'])->name('academic-terms.update_status');
- Route::resource('departments', DepartmentController::class)->except(['create', 'edit', 'show']);
- Route::resource('courses', CourseController::class)->except(['create', 'edit', 'show']);
+ Route::resource('academic-terms', AcademicTermController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-academic-terms')
+ ->middlewareFor(['store'], 'permission:create-academic-terms')
+ ->middlewareFor(['update'], 'permission:update-academic-terms')
+ ->middlewareFor(['destroy'], 'permission:delete-academic-terms');
+ Route::patch('academic-terms/{academic_term}/status', [AcademicTermController::class, 'updateStatus'])->name('academic-terms.update_status')->middleware('permission:update-academic-terms-status');
+
+ Route::resource('departments', DepartmentController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-departments')
+ ->middlewareFor(['store'], 'permission:create-departments')
+ ->middlewareFor(['update'], 'permission:update-departments')
+ ->middlewareFor(['destroy'], 'permission:delete-departments');
+
+ Route::resource('courses', CourseController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-courses')
+ ->middlewareFor(['store'], 'permission:create-courses')
+ ->middlewareFor(['update'], 'permission:update-courses')
+ ->middlewareFor(['destroy'], 'permission:delete-courses');
});
Route::prefix('admin/academic-classes')->name('admin.academic-classes.')->group(function () {
- Route::resource('materials', MaterialController::class)->except(['create', 'edit', 'show']);
+ Route::resource('materials', MaterialController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-materials')
+ ->middlewareFor(['store'], 'permission:create-materials')
+ ->middlewareFor(['update'], 'permission:update-materials')
+ ->middlewareFor(['destroy'], 'permission:delete-materials');
- Route::resource('assignments', AssignmentController::class)->except(['create', 'edit', 'show']);
+ Route::resource('assignments', AssignmentController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-assignments')
+ ->middlewareFor(['store'], 'permission:create-assignments')
+ ->middlewareFor(['update'], 'permission:update-assignments')
+ ->middlewareFor(['destroy'], 'permission:delete-assignments');
Route::prefix('assignments/{assignment}/submissions')->name('assignments.submissions.')->group(function () {
- Route::get('/', [SubmissionController::class, 'index'])->name('index');
- Route::post('/', [SubmissionController::class, 'store'])->name('store');
- Route::put('{submission}', [SubmissionController::class, 'update'])->name('update');
- Route::delete('{submission}', [SubmissionController::class, 'destroy'])->name('destroy');
+ Route::get('/', [SubmissionController::class, 'index'])->name('index')->middleware('permission:view-assignment-submissions');
+ Route::post('/', [SubmissionController::class, 'store'])->name('store')->middleware('permission:create-assignment-submissions');
+ Route::put('{submission}', [SubmissionController::class, 'update'])->name('update')->middleware('permission:update-assignment-submissions');
+ Route::delete('{submission}', [SubmissionController::class, 'destroy'])->name('destroy')->middleware('permission:delete-assignment-submissions');
});
- Route::resource('schedules', ScheduleController::class)->except(['create', 'edit', 'show']);
+ Route::resource('schedules', ScheduleController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-schedules')
+ ->middlewareFor(['store'], 'permission:create-schedules')
+ ->middlewareFor(['update'], 'permission:update-schedules')
+ ->middlewareFor(['destroy'], 'permission:delete-schedules');
Route::prefix('attendances')->name('attendances.')->group(function () {
- Route::get('/', [AttendanceController::class, 'index'])->name('index');
+ Route::get('/', [AttendanceController::class, 'index'])->name('index')->middleware('permission:view-attendances');
Route::get('{course_class}/{meeting_number}', [AttendanceController::class, 'session'])
->whereNumber('meeting_number')
- ->name('session');
+ ->name('session')
+ ->middleware('permission:view-attendances');
Route::post('{course_class}/{meeting_number}', [AttendanceController::class, 'store'])
->whereNumber('meeting_number')
- ->name('store');
+ ->name('store')
+ ->middleware('permission:create-attendances');
Route::delete('{course_class}/{meeting_number}', [AttendanceController::class, 'destroy'])
->whereNumber('meeting_number')
- ->name('destroy');
+ ->name('destroy')
+ ->middleware('permission:delete-attendances');
});
});
Route::prefix('admin/manage')->name('admin.manage.')->group(function () {
- Route::resource('course-registrations', CourseRegistrationController::class)->only(['index', 'store']);
+ Route::resource('course-registrations', CourseRegistrationController::class)
+ ->only(['index', 'store'])
+ ->middlewareFor(['index'], 'permission:view-course-registrations')
+ ->middlewareFor(['store'], 'permission:create-course-registrations');
Route::prefix('course-registrations/{submission}')->name('course-registrations.')->group(function () {
- Route::get('/', [CourseRegistrationController::class, 'show'])->name('show');
- Route::patch('approve', [CourseRegistrationController::class, 'approve'])->name('approve');
- Route::patch('reject', [CourseRegistrationController::class, 'reject'])->name('reject');
+ Route::get('/', [CourseRegistrationController::class, 'show'])->name('show')->middleware('permission:view-course-registrations');
+ Route::patch('approve', [CourseRegistrationController::class, 'approve'])->name('approve')->middleware('permission:approve-course-registrations');
+ Route::patch('reject', [CourseRegistrationController::class, 'reject'])->name('reject')->middleware('permission:reject-course-registrations');
});
- Route::resource('course-classes', CourseClassController::class)->except(['create', 'edit', 'show']);
+ Route::resource('course-classes', CourseClassController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-course-classes')
+ ->middlewareFor(['store'], 'permission:create-course-classes')
+ ->middlewareFor(['update'], 'permission:update-course-classes')
+ ->middlewareFor(['destroy'], 'permission:delete-course-classes');
Route::prefix('course-classes/{course_class}/enrollments')->name('course-classes.enrollments.')->group(function () {
- Route::get('/', [ClassEnrollmentController::class, 'index'])->name('index');
- Route::post('/', [ClassEnrollmentController::class, 'store'])->name('store');
- Route::delete('{enrollment}', [ClassEnrollmentController::class, 'destroy'])->name('destroy');
+ Route::get('/', [ClassEnrollmentController::class, 'index'])->name('index')->middleware('permission:view-course-class-enrollments');
+ Route::post('/', [ClassEnrollmentController::class, 'store'])->name('store')->middleware('permission:create-course-class-enrollments');
+ Route::delete('{enrollment}', [ClassEnrollmentController::class, 'destroy'])->name('destroy')->middleware('permission:delete-course-class-enrollments');
});
Route::prefix('announcements')->name('announcements.')->group(function () {
- Route::get('/', [AnnouncementController::class, 'index'])->name('index');
- Route::post('/', [AnnouncementController::class, 'store'])->name('store');
- Route::put('{announcement}', [AnnouncementController::class, 'update'])->name('update');
- Route::delete('{announcement}', [AnnouncementController::class, 'destroy'])->name('destroy');
+ Route::get('/', [AnnouncementController::class, 'index'])->name('index')->middleware('permission:view-announcements');
+ Route::post('/', [AnnouncementController::class, 'store'])->name('store')->middleware('permission:create-announcements');
+ Route::put('{announcement}', [AnnouncementController::class, 'update'])->name('update')->middleware('permission:update-announcements');
+ Route::delete('{announcement}', [AnnouncementController::class, 'destroy'])->name('destroy')->middleware('permission:delete-announcements');
});
});
@@ -107,20 +150,35 @@
});
Route::prefix('admin/finances')->name('admin.finances.')->group(function () {
- Route::resource('tuition-invoices', TuitionInvoiceController::class)->except(['create', 'edit', 'show']);
+ Route::resource('tuition-invoices', TuitionInvoiceController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-tuition-invoices')
+ ->middlewareFor(['store'], 'permission:create-tuition-invoices')
+ ->middlewareFor(['update'], 'permission:update-tuition-invoices')
+ ->middlewareFor(['destroy'], 'permission:delete-tuition-invoices');
Route::prefix('tuition-invoices/{tuition_invoice}/payments')->name('tuition-invoices.payments.')->group(function () {
- Route::get('/', [TuitionPaymentController::class, 'index'])->name('index');
- Route::post('/', [TuitionPaymentController::class, 'store'])->name('store');
- Route::put('{payment}', [TuitionPaymentController::class, 'update'])->name('update');
- Route::delete('{payment}', [TuitionPaymentController::class, 'destroy'])->name('destroy');
+ Route::get('/', [TuitionPaymentController::class, 'index'])->name('index')->middleware('permission:view-tuition-payments');
+ Route::post('/', [TuitionPaymentController::class, 'store'])->name('store')->middleware('permission:create-tuition-payments');
+ Route::put('{payment}', [TuitionPaymentController::class, 'update'])->name('update')->middleware('permission:update-tuition-payments');
+ Route::delete('{payment}', [TuitionPaymentController::class, 'destroy'])->name('destroy')->middleware('permission:delete-tuition-payments');
});
});
Route::prefix('admin/services')->name('admin.services.')->group(function () {
- Route::resource('letter-requests', LetterRequestController::class)->except(['create', 'edit', 'show']);
+ Route::resource('letter-requests', LetterRequestController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-letter-requests')
+ ->middlewareFor(['store'], 'permission:create-letter-requests')
+ ->middlewareFor(['update'], 'permission:update-letter-requests')
+ ->middlewareFor(['destroy'], 'permission:delete-letter-requests');
- Route::resource('academic-advising-logs', AcademicAdvisingLogController::class)->except(['create', 'edit', 'show']);
+ Route::resource('academic-advising-logs', AcademicAdvisingLogController::class)
+ ->except(['create', 'edit', 'show'])
+ ->middlewareFor(['index'], 'permission:view-academic-advising-logs')
+ ->middlewareFor(['store'], 'permission:create-academic-advising-logs')
+ ->middlewareFor(['update'], 'permission:update-academic-advising-logs')
+ ->middlewareFor(['destroy'], 'permission:delete-academic-advising-logs');
});
Route::prefix('admin/settings')->name('admin.settings.')->group(function () {
@@ -145,19 +203,37 @@
->names('admin.feedback');
Route::prefix('admin/users')->name('admin.users.')->group(function () {
- Route::resource('lecturers', LecturerController::class)->except(['show'])->parameters(['lecturers' => 'user']);
- Route::patch('lecturers/{user}/reset-password', [LecturerController::class, 'resetPassword'])->name('lecturers.reset_password');
- Route::patch('lecturers/{user}/user-status', [LecturerController::class, 'updateUserStatus'])->name('lecturers.update_user_status');
- Route::get('lecturers/export', [LecturerController::class, 'export'])->name('lecturers.export');
+ Route::resource('lecturers', LecturerController::class)
+ ->except(['show'])
+ ->parameters(['lecturers' => 'user'])
+ ->middlewareFor(['index'], 'permission:view-lecturers')
+ ->middlewareFor(['create', 'store'], 'permission:create-lecturers')
+ ->middlewareFor(['edit', 'update'], 'permission:update-lecturers')
+ ->middlewareFor(['destroy'], 'permission:delete-lecturers');
+ Route::patch('lecturers/{user}/reset-password', [LecturerController::class, 'resetPassword'])->name('lecturers.reset_password')->middleware('permission:reset-lecturers-password');
+ Route::patch('lecturers/{user}/user-status', [LecturerController::class, 'updateUserStatus'])->name('lecturers.update_user_status')->middleware('permission:update-lecturers-status');
+ Route::get('lecturers/export', [LecturerController::class, 'export'])->name('lecturers.export')->middleware('permission:export-lecturers');
- Route::resource('students', StudentController::class)->except(['show'])->parameters(['students' => 'user']);
- Route::patch('students/{user}/reset-password', [StudentController::class, 'resetPassword'])->name('students.reset_password');
- Route::patch('students/{user}/status', [StudentController::class, 'updateStatus'])->name('students.update_status');
- Route::patch('students/{user}/user-status', [StudentController::class, 'updateUserStatus'])->name('students.update_user_status');
- Route::get('students/export', [StudentController::class, 'export'])->name('students.export');
+ Route::resource('students', StudentController::class)
+ ->except(['show'])
+ ->parameters(['students' => 'user'])
+ ->middlewareFor(['index'], 'permission:view-students')
+ ->middlewareFor(['create', 'store'], 'permission:create-students')
+ ->middlewareFor(['edit', 'update'], 'permission:update-students')
+ ->middlewareFor(['destroy'], 'permission:delete-students');
+ Route::patch('students/{user}/reset-password', [StudentController::class, 'resetPassword'])->name('students.reset_password')->middleware('permission:reset-students-password');
+ Route::patch('students/{user}/status', [StudentController::class, 'updateStatus'])->name('students.update_status')->middleware('permission:update-students-academic-status');
+ Route::patch('students/{user}/user-status', [StudentController::class, 'updateUserStatus'])->name('students.update_user_status')->middleware('permission:update-students-account-status');
+ Route::get('students/export', [StudentController::class, 'export'])->name('students.export')->middleware('permission:export-students');
- Route::resource('administrators', AdministratorController::class)->except(['show'])->parameters(['administrators' => 'user']);
- Route::patch('administrators/{user}/reset-password', [AdministratorController::class, 'resetPassword'])->name('administrators.reset_password');
- Route::patch('administrators/{user}/user-status', [AdministratorController::class, 'updateUserStatus'])->name('administrators.update_user_status');
+ Route::resource('administrators', AdministratorController::class)
+ ->except(['show'])
+ ->parameters(['administrators' => 'user'])
+ ->middlewareFor(['index'], 'permission:view-administrators')
+ ->middlewareFor(['create', 'store'], 'permission:create-administrators')
+ ->middlewareFor(['edit', 'update'], 'permission:update-administrators')
+ ->middlewareFor(['destroy'], 'permission:delete-administrators');
+ Route::patch('administrators/{user}/reset-password', [AdministratorController::class, 'resetPassword'])->name('administrators.reset_password')->middleware('permission:reset-administrators-password');
+ Route::patch('administrators/{user}/user-status', [AdministratorController::class, 'updateUserStatus'])->name('administrators.update_user_status')->middleware('permission:update-administrators-status');
});
});