dstpabuaran.com/resources/js/pages/admin/roles/edit.tsx
Yoga Pangestu e9237f857e feat: add role management functionality with create, edit, and delete capabilities
- Implemented RoleEdit component for editing roles with permissions.
- Created RoleIndex component for listing roles with delete confirmation.
- Added routes for role management in web.php with appropriate permissions.
- Developed RoleTest to cover authentication, authorization, and data integrity for role management.
2026-07-31 23:15:55 +07:00

179 lines
7.2 KiB
TypeScript

import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { index as rolesIndex, update } from '@/routes/admin/settings/roles';
import { Form, Head } from '@inertiajs/react';
import { ArrowLeft } from 'lucide-react';
type PermissionsByModule = Record<string, string[]>;
type RoleData = {
id: number;
name: string;
permissions: {
id: number;
name: string;
}[];
};
type Props = {
role: RoleData;
permissions: PermissionsByModule;
};
const moduleLabels: Record<string, string> = {
'user': 'Pengguna',
'category': 'Kategori',
'supplier': 'Supplier',
'customer': 'Customer',
'cash-account': 'Kas Toko',
'expense': 'Pengeluaran',
'employee-advance': 'Kasbon',
'payroll-period': 'Periode Gaji',
'payroll': 'Gaji',
'payroll-adjustment': 'Adjustment Gaji',
'leave-request': 'Cuti',
'attendance': 'Absensi',
'settings': 'Pengaturan',
};
const actionLabels: Record<string, string> = {
'view': 'Lihat',
'create': 'Tambah',
'update': 'Edit',
'delete': 'Hapus',
'toggle-active': 'Aktif/Nonaktif',
'reset-password': 'Reset Kata Sandi',
'deposit': 'Setor',
'withdrawal': 'Tarik',
'approve': 'Setujui',
'pay': 'Bayar',
'reject': 'Tolak',
'current': 'Periode Saat Ini',
'close': 'Tutup',
'reopen': 'Buka Kembali',
'cancel': 'Batalkan',
'check-in': 'Check In',
'check-out': 'Check Out',
'by-date': 'Lihat Per Tanggal',
'show': 'Detail',
'update-system': 'Update Sistem',
'update-homepage': 'Update Homepage',
'update-social-media': 'Update Media Sosial',
'update-marketplace': 'Update Marketplace',
'update-hr': 'Update HR',
};
export default function RoleEdit({ role, permissions }: Props) {
const assignedPermissions = role.permissions.map((p) => p.name);
return (
<>
<Head title="Edit Role" />
<div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4 md:p-6">
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-semibold tracking-tight">
Edit Role
</h2>
</div>
<Button asChild variant="outline">
<a href={rolesIndex.url()}>
<ArrowLeft className="h-4 w-4" />
Kembali
</a>
</Button>
</div>
<Form action={update(role.id)}>
{({ errors, processing }) => (
<>
<div className="grid gap-6">
<Card>
<CardHeader>
<CardTitle>Informasi Role</CardTitle>
</CardHeader>
<CardContent>
<div className="grid gap-2">
<Label htmlFor="name">
Nama Role <span className="text-destructive">*</span>
</Label>
<Input
id="name"
name="name"
placeholder="Masukkan nama role"
defaultValue={role.name}
/>
<InputError message={errors.name} />
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Permission</CardTitle>
</CardHeader>
<CardContent className="grid gap-6">
{Object.entries(permissions).map(([module, actions]) => (
<div key={module} className="grid gap-3">
<Label className="text-sm font-semibold">
{moduleLabels[module] ?? module}
</Label>
<div className="grid grid-cols-2 gap-2 md:grid-cols-3 lg:grid-cols-4">
{actions.map((action) => (
<label
key={`${module}.${action}`}
className="flex items-center gap-2 rounded-md border p-2 text-sm hover:bg-muted cursor-pointer"
>
<Checkbox
name="permissions[]"
value={`${module}.${action}`}
defaultChecked={assignedPermissions.includes(`${module}.${action}`)}
/>
<span className="text-xs">
{actionLabels[action] ?? action}
</span>
</label>
))}
</div>
</div>
))}
<InputError message={errors.permissions} />
</CardContent>
</Card>
</div>
<div className="flex items-center gap-4 mt-6">
<Button type="submit" disabled={processing}>
{processing ? 'Menyimpan...' : 'Simpan'}
</Button>
</div>
</>
)}
</Form>
</div>
</>
);
}
RoleEdit.layout = {
breadcrumbs: [
{
title: 'Pengaturan',
href: '/admin/settings',
},
{
title: 'Role & Permission',
href: rolesIndex.url(),
},
{
title: 'Edit',
href: '#',
},
],
};