Files
Rasadyar_Inspection_System/src/partials/users/SubmitNewUser.tsx

267 lines
7.7 KiB
TypeScript
Raw Normal View History

2026-01-26 10:14:10 +03:30
import React, { useMemo } from "react";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm, Controller } from "react-hook-form";
import { z } from "zod";
import { Grid } from "../../components/Grid/Grid";
import Button from "../../components/Button/Button";
import Textfield from "../../components/Textfeild/Textfeild";
import { useUserProfileStore } from "../../context/zustand-store/userStore";
import { useApiMutation } from "../../utils/useApiRequest";
import { useToast } from "../../hooks/useToast";
import { useDrawerStore } from "../../context/zustand-store/appStore";
import { getCitiesOfProvinceInfo } from "../../utils/getCitiesOfProvinceInfo";
import AutoComplete from "../../components/AutoComplete/AutoComplete";
import {
zValidateString,
zValidateMobile,
zValidateAutoComplete,
} from "../../data/getFormTypeErrors";
interface UserItem {
_id?: string;
Id?: string;
mobile?: string;
fullname?: string;
permissions?: string[];
province?: string;
city?: string;
}
2026-01-26 10:14:10 +03:30
interface SubmitNewUserProps {
province: string;
onSuccess?: () => void;
item?: UserItem | null;
2026-01-26 10:14:10 +03:30
}
const getSchema = (isEdit: boolean) =>
z.object({
mobile: zValidateMobile("موبایل"),
password: isEdit ? z.string().optional() : zValidateString("کلمه عبور"),
fullname: zValidateString("نام کامل"),
permissions: zValidateAutoComplete("دسترسی‌ها"),
city: zValidateAutoComplete("شهر"),
});
2026-01-26 10:14:10 +03:30
type FormValues = z.infer<ReturnType<typeof getSchema>>;
2026-01-26 10:14:10 +03:30
export const SubmitNewUser: React.FC<SubmitNewUserProps> = ({
onSuccess,
item,
}) => {
2026-01-26 10:14:10 +03:30
const { profile } = useUserProfileStore();
const showToast = useToast();
const { closeDrawer } = useDrawerStore();
const isEdit = !!item;
const schema = useMemo(() => getSchema(isEdit), [isEdit]);
2026-01-26 10:14:10 +03:30
const {
control,
handleSubmit,
setValue,
formState: { errors, isSubmitting },
} = useForm<FormValues>({
resolver: zodResolver(schema),
defaultValues: item
? {
mobile: item.mobile ?? "",
password: "",
fullname: item.fullname ?? "",
permissions: Array.isArray(item.permissions) ? item.permissions : [],
city: item.city ? [item.city] : [],
}
: {
mobile: "",
password: "",
fullname: "",
permissions: [],
city: [],
},
2026-01-26 10:14:10 +03:30
});
const createUserMutation = useApiMutation({
2026-01-26 10:14:10 +03:30
api: "user",
method: "post",
});
const updateUserMutation = useApiMutation({
api: `user/${item?._id ?? item?.Id ?? ""}`,
method: "put",
});
2026-01-26 10:14:10 +03:30
const cityOptions = useMemo(() => {
return getCitiesOfProvinceInfo(profile?.province || "").map((item) => ({
key: item.en,
value: item.fa,
}));
}, [profile?.province]);
const hasAdminPermission = profile?.permissions?.includes("admin");
2026-01-26 10:14:10 +03:30
const permissionOptions = useMemo(() => {
const options = [
2026-01-26 10:14:10 +03:30
{ key: "add", value: "ثبت کاربر" },
{ key: "submit", value: "ثبت بازرسی" },
];
if (hasAdminPermission) {
options.push({ key: "admin", value: "ادمین" });
}
return options;
}, [hasAdminPermission]);
2026-01-26 10:14:10 +03:30
const onSubmit = async (data: FormValues) => {
try {
const basePayload = {
2026-01-26 10:14:10 +03:30
mobile: data.mobile,
fullname: data.fullname,
pic: "",
permissions: data.permissions as string[],
province: profile?.province,
city:
Array.isArray(data.city) && data.city.length > 0
? String(data.city[0])
: "",
};
if (isEdit) {
const payload =
data.password && String(data.password).trim() !== ""
? { ...basePayload, password: data.password }
: basePayload;
await updateUserMutation.mutateAsync(payload);
showToast("کاربر با موفقیت ویرایش شد", "success");
} else {
if (!data.password || String(data.password).trim() === "") {
showToast("کلمه عبور را وارد کنید", "error");
return;
}
const payload = { ...basePayload, password: data.password };
await createUserMutation.mutateAsync(payload);
showToast("کاربر با موفقیت ثبت شد", "success");
}
2026-01-26 10:14:10 +03:30
closeDrawer();
if (onSuccess) {
onSuccess();
}
} catch (error) {
console.error(error);
showToast(
isEdit
? "مشکلی پیش آمده است!"
: "مشکلی پیش آمده است، ممکن است کاربر تکراری باشد!",
"error",
);
2026-01-26 10:14:10 +03:30
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container column className="gap-4">
<Controller
name="mobile"
control={control}
render={({ field }) => (
<Textfield
placeholder="موبایل"
value={field.value}
onChange={field.onChange}
error={!!errors.mobile}
helperText={errors.mobile?.message}
fullWidth
/>
)}
/>
<Controller
name="password"
control={control}
render={({ field }) => (
<Textfield
placeholder="کلمه عبور"
value={field.value}
onChange={field.onChange}
password
error={!!errors.password}
helperText={errors.password?.message}
fullWidth
/>
)}
/>
<Controller
name="fullname"
control={control}
render={({ field }) => (
<Textfield
placeholder="نام کامل"
value={field.value}
onChange={field.onChange}
error={!!errors.fullname}
helperText={errors.fullname?.message}
fullWidth
/>
)}
/>
<div className="w-full">
<Controller
name="city"
control={control}
render={({ field }) => (
<AutoComplete
data={cityOptions}
selectedKeys={
(Array.isArray(field.value) ? field.value : []) as (
| string
| number
)[]
}
onChange={(keys) => setValue("city", keys as any)}
title="شهر را انتخاب کنید"
error={!!errors.city}
helperText={errors.city?.message}
multiselect={false}
/>
)}
/>
</div>
<div className="w-full">
<Controller
name="permissions"
control={control}
render={({ field }) => (
<AutoComplete
data={permissionOptions}
selectedKeys={
(Array.isArray(field.value) ? field.value : []) as (
| string
| number
)[]
}
onChange={(keys) => setValue("permissions", keys as any)}
title="دسترسی‌ها را انتخاب کنید"
error={!!errors.permissions}
helperText={errors.permissions?.message}
multiselect={true}
/>
)}
/>
</div>
<Button
type="submit"
variant="submit"
fullWidth
disabled={
isSubmitting ||
createUserMutation.isPending ||
updateUserMutation.isPending
}
2026-01-26 10:14:10 +03:30
>
{isEdit ? "ذخیره تغییرات" : "ثبت کاربر"}
2026-01-26 10:14:10 +03:30
</Button>
</Grid>
</form>
);
};