inspiren-sem-tool/resources/js/forms/management/UserForm.tsx
brian-inspiren 221d3f8173
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
feat: sem codebase
2026-05-21 11:28:03 +08:00

108 lines
3.5 KiB
TypeScript

import { FormStatus, Role, User } from "@/types";
import { useForm } from "@inertiajs/react";
import { Button, MultiSelect, PasswordInput, Select, Stack, TextInput } from "@mantine/core";
import { IconDeviceFloppy } from "@tabler/icons-react";
import React from "react";
interface Props {
roles: Role[];
managers: { value: string; label: string }[];
user?: User;
status: FormStatus;
}
export default function UserForm({ roles, managers, user, status }: Props) {
const { data, setData, post, processing, errors } = useForm({
name: user?.name ?? "",
email: user?.email ?? "",
password: "",
manager_id: user?.manager_id ? String(user.manager_id) : null,
roles: user?.roles?.map((role) => role.name) ?? [],
});
const roleOptions = roles.map((role) => ({
value: role.name,
label: role.name,
}));
const submit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (status === "create") {
post(route("management.users.store"));
return;
}
post(route("management.users.update", { id: user?.id ?? "" }));
};
return (
<form onSubmit={submit}>
<Stack spacing="md">
<TextInput
label="Full name"
value={data.name}
onChange={(event) => setData("name", event.target.value)}
error={errors.name}
required
/>
<TextInput
label="Email address"
value={data.email}
onChange={(event) => setData("email", event.target.value)}
error={errors.email}
type="email"
required
/>
<PasswordInput
label="Password"
value={data.password}
onChange={(event) => setData("password", event.target.value)}
error={errors.password}
description={
status === "update"
? "Leave blank to keep the existing password."
: undefined
}
required={status === "create"}
minLength={status === "create" ? 8 : undefined}
/>
<Select
data={managers}
label="Reports to"
placeholder="No manager"
value={data.manager_id}
onChange={(value) => setData("manager_id", value)}
error={errors.manager_id}
searchable
clearable
nothingFound="No users found"
/>
<MultiSelect
data={roleOptions}
label="Roles"
value={data.roles}
onChange={(value) => setData("roles", value)}
error={errors.roles}
searchable
nothingFound="No roles found"
required
/>
<Button
type="submit"
leftIcon={<IconDeviceFloppy size={16} />}
loading={processing}
style={{ width: "max-content" }}
>
Save User
</Button>
</Stack>
</form>
);
}