- Integrated toast notifications to display error messages when form submissions fail across various components, enhancing user feedback and experience. - Updated components including DeleteUser, FormDialog, ManageTwoFactor, TwoFactorRecoveryCodes, TwoFactorSetupModal, PayrollPeriodShow, EmployeeCreate, EmployeeEdit, CuttingCreate, CuttingEdit, PurchaseCreate, PurchaseEdit, RestockCreate, RestockEdit, TransactionCreate, TransactionEdit, Category management, Product management, Raw Material management, Role management, Settings, and Authentication pages.
186 lines
8.2 KiB
TypeScript
186 lines
8.2 KiB
TypeScript
import { Form, Head, Link } from '@inertiajs/react';
|
|
import { ArrowLeft } from 'lucide-react';
|
|
import { toast } from 'sonner';
|
|
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';
|
|
|
|
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">
|
|
<Link href={rolesIndex.url()}>
|
|
<ArrowLeft className="h-4 w-4" />
|
|
Kembali
|
|
</Link>
|
|
</Button>
|
|
</div>
|
|
|
|
<Form
|
|
action={update(role.id)}
|
|
onError={() => {
|
|
toast.error('Terjadi kesalahan saat menyimpan data. Silakan periksa kembali input Anda.');
|
|
}}
|
|
>
|
|
{({ 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 cursor-pointer items-center gap-2 rounded-md border p-2 text-sm hover:bg-muted"
|
|
>
|
|
<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="mt-6 flex items-center gap-4">
|
|
<Button type="submit" disabled={processing}>
|
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
|
</Button>
|
|
</div>
|
|
</>
|
|
)}
|
|
</Form>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|