115 lines
4.1 KiB
TypeScript
115 lines
4.1 KiB
TypeScript
import { Role, FormStatus, PermissionList } from "@/types";
|
|
import { useForm } from "@inertiajs/react";
|
|
import { Button, Checkbox, SimpleGrid, Stack, Text, TextInput } from "@mantine/core";
|
|
import { IconDeviceFloppy } from "@tabler/icons-react";
|
|
import React from "react";
|
|
|
|
interface Props {
|
|
role?: Role;
|
|
status: FormStatus;
|
|
permissions: PermissionList;
|
|
}
|
|
|
|
export default function UserForm({ role, status, permissions }: Props) {
|
|
// 1. Initialize form with the permissions passed from PHP
|
|
const { data, setData, post, put, processing, errors } = useForm({
|
|
name: role?.name || '',
|
|
permissions: permissions,
|
|
});
|
|
|
|
// Handle individual permission toggle
|
|
const handlePermissionChange = (group: string, index: number, checked: boolean) => {
|
|
const updatedPermissions = { ...data.permissions };
|
|
|
|
if (updatedPermissions[group] && updatedPermissions[group][index]) {
|
|
// Create a new object for the specific permission to trigger state update
|
|
updatedPermissions[group][index] = {
|
|
...updatedPermissions[group][index],
|
|
checked
|
|
};
|
|
setData('permissions', updatedPermissions);
|
|
}
|
|
};
|
|
|
|
// Handle "Check All" for a specific group
|
|
const handleGroupCheckboxChange = (group: string, checked: boolean) => {
|
|
const updatedPermissions = { ...data.permissions };
|
|
|
|
if (updatedPermissions[group]) {
|
|
updatedPermissions[group] = updatedPermissions[group].map(p => ({
|
|
...p,
|
|
checked
|
|
}));
|
|
setData('permissions', updatedPermissions);
|
|
}
|
|
};
|
|
|
|
function submit(event: React.FormEvent) {
|
|
event.preventDefault();
|
|
if (status === 'create') {
|
|
post(route('management.roles.store'));
|
|
} else {
|
|
// Use put() for updates if your route is Route::put
|
|
post(route('management.roles.update', { id: role?.id }));
|
|
}
|
|
}
|
|
|
|
// IMPORTANT: Map over data.permissions (state), not permissions (prop)
|
|
const permissionCheckboxes = Object.entries(data.permissions).map(([group, list]) => {
|
|
const allChecked = list.every(p => p.checked);
|
|
const someChecked = list.some(p => p.checked);
|
|
|
|
return (
|
|
<Stack key={group} spacing="xs">
|
|
<Checkbox
|
|
label={<Text fw={600} sx={{ textTransform: 'capitalize' }}>{group}</Text>}
|
|
checked={allChecked}
|
|
indeterminate={someChecked && !allChecked}
|
|
onChange={(e) => handleGroupCheckboxChange(group, e.target.checked)}
|
|
/>
|
|
<SimpleGrid cols={1}>
|
|
{list.map((permission, index) => (
|
|
<Checkbox
|
|
key={permission.id}
|
|
ml={20}
|
|
label={<Text size="sm">{permission.description}</Text>}
|
|
checked={permission.checked}
|
|
onChange={(e) => handlePermissionChange(group, index, e.target.checked)}
|
|
/>
|
|
))}
|
|
</SimpleGrid>
|
|
</Stack>
|
|
);
|
|
});
|
|
|
|
return (
|
|
<form onSubmit={submit}>
|
|
<Stack spacing="xl">
|
|
<TextInput
|
|
label="Role Name"
|
|
value={data.name}
|
|
onChange={(e) => setData('name', e.target.value)}
|
|
error={errors.name}
|
|
required
|
|
/>
|
|
|
|
<Stack spacing={5}>
|
|
<Text fw={500}>Permissions</Text>
|
|
<SimpleGrid cols={4} spacing="lg" verticalSpacing="xl">
|
|
{permissionCheckboxes}
|
|
</SimpleGrid>
|
|
</Stack>
|
|
|
|
<Button
|
|
type="submit"
|
|
loading={processing}
|
|
leftIcon={<IconDeviceFloppy size={18} />}
|
|
style={{ width: 'fit-content' }}
|
|
>
|
|
Save Role
|
|
</Button>
|
|
</Stack>
|
|
</form>
|
|
);
|
|
}
|