ldc-groupe/resources/ts/back/Pages/Users/Form.tsx

229 lines
7.8 KiB
TypeScript

// * Packages
import { useForm, usePage } from "@inertiajs/react";
import { BookText, Eye } from "lucide-react";
import { route } from "ziggy-js";
import { FormEvent } from "react";
// * Components shadcn
import { Button } from "@/components/ui/button";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
// * Other
import SimpleInput from "@/back/Components/Inputs/SimpleInput";
import SimpleSelect from "@/back/Components/Inputs/SimpleSelect";
import SimpleSwitch from "@/back/Components/Inputs/SimpleSwitch";
import FieldsetWrapper from "@/back/Components/FieldsetWrapper";
import useTrans from "@/hooks/use-translations";
import str from "@/hooks/use-string";
import InputError from "@/back/Components/InputError";
import { useToast } from "@/hooks/use-toast";
import { Methods } from "@/lib/enums";
import { AuthProp, LaravelEnum, UserModel } from "@/back/types/global";
export default function Form({
model,
modelName,
modelRoute,
action,
method,
}: {
model?: UserModel;
modelName: string;
modelRoute: string;
action: string;
method: number;
}) {
/** Set messages success/errors */
const messages = {} as Record<string, string>;
messages.titleSuccess = useTrans(
method === Methods.POST
? "Création réussie !"
: "Mise à jour réussie !",
);
messages.descriptionSuccess = str(
useTrans(
method === Methods.POST
? "crud.messages.has_been_created"
: "crud.messages.has_been_updated",
{ model: useTrans(`models.classes.${modelName}`) },
),
)
.ucFirst()
.value();
messages.titleError = useTrans(
method === Methods.POST
? "Création annulée !"
: "Mise à jour annulée !",
);
messages.descriptionError = str(
useTrans(
method === Methods.POST
? "crud.messages.cannot_be_created"
: "crud.messages.cannot_be_updated",
{ model: useTrans(`models.classes.${modelName}`) },
),
)
.ucFirst()
.value();
const { toast } = useToast();
/** User roles */
const userModel = (usePage().props.auth as AuthProp).user;
const enumUserRole = usePage().props.enumUserRole as LaravelEnum;
const filterRoles = (value: number) => {
return (
Object.entries(enumUserRole)
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
.filter(([_, role]) => role.value >= value)
.reduce((acc, [key, val]) => ({ ...acc, [key]: val }), {})
);
};
/** Form section */
const { post, patch, setData, data } = useForm({
first_name: model?.first_name,
last_name: model?.last_name,
email: model?.email,
published: model?.published ?? false,
published_at: model?.published_at,
role: model?.role,
});
const routeOptions = () => {
return {
preserveScroll: true,
onSuccess: () => {
toast({
title: messages.titleSuccess,
description: messages.descriptionSuccess,
});
},
onError: () => {
toast({
variant: "destructive",
title: messages.titleError,
description: messages.descriptionError,
});
},
};
};
const submit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const routeUrl = route(`back.${modelRoute}.${action}`, model?.id);
switch (method) {
case Methods.POST:
post(routeUrl, routeOptions());
break;
case Methods.PATCH:
patch(routeUrl, routeOptions());
break;
default:
throw new Error("The method must be post or patch");
}
};
return (
<form onSubmit={submit}>
<InputError all />
<FieldsetWrapper
title={useTrans("back.form_title_global")}
icon={<BookText className="mr-1" />}
description={useTrans("back.form_subtitle_global")}
className="sm:grid-cols-2 gap-4"
>
<SimpleInput
name="first_name"
label={str(
useTrans("back.form_associate_to", {
attribute: useTrans(
"validation.attributes.first_name",
),
}),
)
.ucFirst()
.value()}
placeholder="ex: John Doe"
value={data.first_name}
setData={setData}
/>
<SimpleInput
name="last_name"
label={str(
useTrans("back.form_associate_to", {
attribute: useTrans(
"validation.attributes.last_name",
),
}),
)
.ucFirst()
.value()}
placeholder="ex: John Doe"
value={data.last_name}
setData={setData}
/>
<SimpleInput
name="email"
type="email"
label={str(
useTrans("back.form_associate_to", {
attribute: useTrans("validation.attributes.email"),
}),
)
.ucFirst()
.value()}
placeholder="ex: john.doe@gmail.com"
value={data.email}
setData={setData}
/>
<SimpleSelect
name="role"
options={
model?.role &&
userModel.role !== enumUserRole.conceptor.value
? filterRoles(model?.role)
: enumUserRole
}
label={str(
useTrans("back.form_associate_to", {
attribute: useTrans("validation.attributes.role"),
}),
)
.ucFirst()
.value()}
selected={data.role ? String(data.role) : undefined}
setData={setData}
/>
</FieldsetWrapper>
<FieldsetWrapper
className="gap-4"
title={useTrans("back.form_title_visibility")}
icon={<Eye className="mr-1" />}
description={useTrans("back.form_subtitle_visibility")}
inline
>
<SimpleSwitch
name="published"
checked={data.published}
setData={setData}
/>
</FieldsetWrapper>
<div className="text-center">
<Tooltip>
<TooltipTrigger asChild>
<Button type="submit">
{str(useTrans("crud.actions.save"))
.ucFirst()
.value()}
</Button>
</TooltipTrigger>
<TooltipContent>
{useTrans("crud.helpers.save_model", {
model: useTrans("models.classes.user"),
})}
</TooltipContent>
</Tooltip>
</div>
</form>
);
}