صفحة المستخدمين

محتويات الفولدر
Users Folder
| الفايلات |
|---|
| UsersRequest.ts |
| changeUserPasswordRequest.ts |
| columns.ts |
| useUsers.ts |
| UsersView.tsx |
UsersRequest.ts
export const baseSchema = (t: TFunction) =>
z.object({
name: z.string({ required_error: "يجب ادخال الاسم الظاهر" }),
password: z.string({
required_error: t("pages.management.users.inputs.password.required"),
}),
authId: z.string({
required_error: t("pages.management.users.inputs.username.required"),
}),
roleId: z.string({
required_error: t("pages.management.users.inputs.roleId.required"),
}),
isAdmin: z
.boolean({ required_error: "يجب تحديد هل المستخدم ادمن" })
.optional()
.nullable(),
});
- هاي السكيما مال اضافة مستخدم او يوزر جديد
- بيها ال Validation الي تخص كل حقل واذا مطلوب او لا
export const baseEditSchema = (t: TFunction) =>
z.object({
authId: z.string({
required_error: t("pages.management.users.inputs.username.required"),
}),
roleId: z.string({
required_error: t("pages.management.users.inputs.roleId.required"),
}),
isAdmin: z
.boolean({ required_error: "يجب اختيار هل المستخدم مسؤل" })
.optional(),
});
- هاي ايضا سكيما بس مال عملية التعديل او التحديث وبيها ايضا الحقول الاجبارية والاختيارية
changeUserPasswordRequest.ts
export const baseSchema = (t: TFunction) =>
z.object({
newPassword: z.string({
required_error: t("pages.management.users.inputs.newPassword.required"),
}),
});
- هذا السكيما الي يخص النافذة مال تحديث كلمة المرور مال المستخدم
- وبيه حقل واحد واجباري والي هو كلمة السر الجديدة
columns.ts
const getColumns = (t: TFunction): ColumnDef<users>[] => {
return [
{
accessorKey: "userName",
header: t("pages.management.users.columns.username"),
size: 450,
},
{
accessorKey: "userRole",
header: t("pages.management.users.columns.userRole"),
size: 150,
cell: ({ row }) => {
const userRole = row.getValue<{ id: string; name: string }>("userRole");
if (userRole) {
return userRole.name;
}
return "";
},
},
{
accessorKey: "isAdmin",
header: t("pages.management.users.columns.isAdmin"),
size: 50,
cell: ({ row }) => {
const isAdmin = row.getValue<boolean>("isAdmin");
if (isAdmin) {
return "نعم";
}
return "لا";
},
},
{
accessorKey: "createdAt",
header: t("pages.management.users.columns.createdAt"),
size: 450,
cell: ({ row }) => {
const date = row.getValue("createdAt") as string;
return new Date(date).toLocaleString("ar-EG", {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
hour12: true,
numberingSystem: "latn",
});
},
},
];
};
- هاي عبارة عن الاعمدة مال التيبل الي راح يعرض المستخدمين مالتك بالصفحة وراح يكون بيه
accessorKey: هذا الحقل هو ال Key او اسم المتغير مال المدخلheader: هذا الحقل حيكون عرض التايتل والي حيستخدم ال localiazationsize: هنا حيكون الحجم او العرض مال الحقل مالتكcell: هذا حيتخصص شلون راح تعرض الحقل مالتك تريدة او شنو تريدة يعرض او يرجعلك
useUsers.ts
const addNewUserMutation = useMutation({
mutationFn: registerRequest,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["users"],
});
setOpenDialog(false);
reset(defaultValues);
toast.success(t("pages.management.users.addUserSuccess"));
},
onError: (error: any) => {
toast.error(t("pages.management.users.addUserError"), {
description: error?.response?.data.message,
});
},
});
- هاي راح تكون مسؤولة عن تنفيذ عملية الاضافة
- راح يكون ال regeisterRequest هو عبارة عن request api الي راح يندز بيه ال Body مالتك
- لمن تصير عملية اضافة وتمت بنجاح راح يسوي Refetch للمستخدمين من جديد عن طريق ال queryClient.invalidateQueries
- راح تغلق النافذة مال الفورمة وراح تتصفر البيانات بال reset , وراح تظهر رسالة مال نجاح عملية الاضافة الي جتي من ملف ال ar.json/en.json
const changePasswordMutation = useMutation({
mutationFn: adminChangePassword,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["users"],
});
setEditPasswordDialog(false);
formPassword.reset({ newPassword: undefined });
toast.success(t("pages.management.users.changePasswordSuccess"));
},
onError: (error: any) => {
toast.error(t("pages.management.users.changePasswordError"), {
description: error?.response?.data.message,
});
},
});
- هاي راح تكون مسؤولة عن تنفيذ عملية تغيير الرمز السري للمستخدم
- راح يكون ال adminChangePassword هو عبارة عن request api الي راح يندز بيه ال Body مالتك
- لمن تصير عملية تغيير الرمز وتمت بنجاح راح يسوي Refetch للمستخدمين من جديد عن طريق ال queryClient.invalidateQueries
- راح تغلق النافذة مال الفورمة وراح تتصفر البيانات بال reset , وراح تظهر رسالة مال نجاح العملية الي جتي من ملف ال ar.json/en.json
const updateUserMutation = useMutation({
mutationFn: updateUser,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["users"],
});
setEditPasswordDialog(false);
formPassword.reset({ newPassword: undefined });
toast.success(t("pages.management.users.updateUserSuccess"));
},
onError: (error: any) => {
toast.error(t("pages.management.users.updateUserError"), {
description: error?.response?.data.message,
});
},
});
- هاي راح تكون مسؤولة عن تنفيذ عملية تحديث بيانات المستخدم الحالية
- راح يكون ال updateUser هو عبارة عن request api الي راح يندز بيه ال Body مالتك
- لمن تصير عملية تحديث وتمت بنجاح راح يسوي Refetch للمستخدمين من جديد عن طريق ال queryClient.invalidateQueries
- راح تغلق النافذة مال الفورمة وراح تتصفر البيانات بال reset , وراح تظهر رسالة مال نجاح العملية الي جتي من ملف ال ar.json/en.json
const deleteUserMutation = useMutation({
mutationFn: deleteUser,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["users"],
});
setDeleteDialog(false);
setSelectedUser(null);
reset(defaultValues);
toast.success(t("successMessage"));
},
onError: (error) => {
const errorMessage = (error as any)?.response?.data?.message;
toast.error(t("errorMessage"), { description: `${errorMessage}` });
},
});
- هاي راح تكون مسؤولة عن تنفيذ عملية حذف مستخدم حالي
- راح يكون ال deleteUser هو عبارة عن request api الي راح يندز بيه ال user Id علمود الحذف
- لمن تصير عملية حذف وتمت بنجاح راح يسوي Refetch للمستخدمين من جديد عن طريق ال queryClient.invalidateQueries
- راح تغلق النافذة مال الفورمة وراح تتصفر البيانات بال reset , وراح تظهر رسالة مال نجاح عملية الحذف الي جتي من ملف ال ar.json/en.json
const openAddDialog = () => {
setOpenDialog(true);
reset(defaultValues);
};
const openEditPasswordDialog = (id: string) => {
setEditPasswordDialog(true);
setSelectedUser(id);
formPassword.reset({ newPassword: undefined });
};
const openEditDialog = (id: string) => {
const user = users?.find((user) => user.id == id);
if (user) {
setEditDialog(true);
setSelectedUser(id);
editForm.reset({
authId: user.userName,
roleId: user.userRole?.id,
});
}
};
const openDeleteDialog = (id: string) => {
const user = users?.find((user) => user.id == id);
if (user) {
setDeleteDialog(true);
setSelectedUser(id);
}
};
- الدوال الفوك راح يكونن مسؤولات عن فتح النافذة مال عمليات الاضافة, التحديث , تغيير الرمز او الحذف
- بعضها راح يبحث عن المستخدم قبل لا يفتحلة النافذة يتأكد اذا المستخدم موجود لو لا يلة يفتح الة النافذة والي هو
const user = users?.find((user) => user.id == id); - وايضا بعض الاحيان راح يسوي تصفير للقيم او المتغيرات مثل ما موجود بدالة فتح نافذة التعديل
editForm.reset({ authId: user.userName,roleId: user.userRole?.id});
const handleDelete = () => {
if (selectedUser) {
deleteUserMutation.mutate(selectedUser);
}
};
const handleEditPassword = (data: changeUserPassRequest) => {
changePasswordMutation.mutate({
userId: selectedUser as string,
newPassword: data.newPassword,
});
};
const handleEdit = (data: UserEditRequest) => {
updateUserMutation.mutate({
id: selectedUser!,
authId: data.authId,
roleId: data.roleId,
isAdmin: data.isAdmin || false,
});
};
const onSubmit = (data: UsersRequest) => {
addNewUserMutation.mutate({
authId: data.authId,
isAdmin: data.isAdmin!,
password: data.password,
name: data.name,
roleId: data.roleId,
});
};
- هنا ذني الدوال خاصة انو تنفذ ال mutation وفي حال جانت محتاجة بيانات راح تتعبر منانة بهاي الدوال
- وبدالة الحذف راح يتم التأكد اول شي اذا اكو مستخدم لو لا علمود اذا ماكو ما ينفذ عملية الحذف من الاساس
- اما بالنسبة للانواع فشرحناها ببداية الصفحة الي هنة UsersRequest, UserEditRequest , changeUserPassRequest
usersView.tsx
const { t, i18n } = useTranslation();
const { updateBreadcrumbs } = useBreadcrumbs();
useEffect(() => {
updateBreadcrumbs([
{
link: "/users",
label: t("pages.management.users.title"),
},
]);
}, [i18n.language]);
const columns = useMemo(() => getColumns(t), [i18n.language]);
const { data: roles } = getRolesQuery();
- اول سطر حيكون جلب للدالة مال الترجمة من والى الانكليزي والعربي
- ثاني شي عدنة هو تحديث العنوان مال الصفحة لمن تتغير اللغة مال الصفحة مالتك وراح تستخدم هنا الدالة مال الترجمة وراح تجيب اما من ar.json or en.json حسب اللغة الحالية
- بالنسبة لل columns فهاي الاعمدة الي شرحناها فوك الي راح تعرض الاعمدة مال التيبل مالتك بالصفحة مال المستخدمين , وايضاً تم استخدام ال useMemo علمود يصير re-render بس لمن تتغير اللغة مال الصفحة
- اخر سطر بهذا الجزء حيكون عبارة عن دالة راح تجيب النة Roles الي راح يكون ال api endpoint مالتها هو
/rolesوالي راح ترجعid , name - باقي الصفحة هو عرض للمحتوى مال الصفحة وياه شوية لوجك متعلق بفتح النوافذ وغيرها
- ايضا اغلب المحتوى المعروض هو عبارة عن re-usable Components لهذا راح يتم الشرح عنها بالملفات المشتركة تجنبا للتكرار