From d94aeed2d230ef28f45eb92ab06ec89a9210a943 Mon Sep 17 00:00:00 2001 From: mhmjalali Date: Mon, 28 Jul 2025 11:55:12 +0330 Subject: [PATCH 1/8] pear dependencies --- .gitignore | 2 +- .idea/.gitignore | 8 ++++++++ .idea/crm-app.iml | 12 ++++++++++++ .idea/inspectionProfiles/Project_Default.xml | 6 ++++++ .idea/modules.xml | 8 ++++++++ .idea/vcs.xml | 6 ++++++ docker-compose.yml | 2 +- 7 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/crm-app.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index 5ef6a52..e72b4d6 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,7 @@ yarn-error.log* .pnpm-debug.log* # env files (can opt-in for committing if needed) -.env* +.env # vercel .vercel diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/crm-app.iml b/.idea/crm-app.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/crm-app.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..f13d54d --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 7f34faf..1ba06c5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,5 +13,5 @@ services: ports: - "3000:3000" env_file: - - .env.local + - .env restart: unless-stopped \ No newline at end of file From 1a6cb32528e4e32eac846ec819ecb11ac362b729 Mon Sep 17 00:00:00 2001 From: mhmjalali Date: Mon, 28 Jul 2025 12:00:50 +0330 Subject: [PATCH 2/8] remove telephone_id from login form --- src/components/Login/Form/index.jsx | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/components/Login/Form/index.jsx b/src/components/Login/Form/index.jsx index 4cb925a..b836889 100644 --- a/src/components/Login/Form/index.jsx +++ b/src/components/Login/Form/index.jsx @@ -31,13 +31,11 @@ const LoginForm = () => { const defaultValues = { username: "", password: "", - telephone_id: "", }; const validationSchema = object({ username: string().required("لطفا نام کاربری را وارد کنید!"), password: string().required("لطفا رمز عبور را وارد کنید!"), - telephone_id: string().required("لطفا شماره تماس داخلی را وارد کنید!"), }); const { @@ -57,7 +55,6 @@ const LoginForm = () => { const formData = new FormData(); formData.append("username", data.username); formData.append("password", data.password); - formData.append("telephone_id", data.telephone_id); await requestServer(GET_USER_LOGIN_ROUTE, "post", { data: formData, }); @@ -155,32 +152,6 @@ const LoginForm = () => { }} name={"password"} /> - { - return ( - - - - ), - }, - }} - fullWidth - error={!!error} - helperText={!!error && error.message} - /> - ); - }} - name={"telephone_id"} - /> - - - - - - ); + return ( + + + + + + ورود به سامانه CRM + + + + + { + return ( + + + + ), + }, + }} + fullWidth + error={!!error} + helperText={!!error && error.message} + /> + ); + }} + name={"username"} + /> + { + return ( + + + {showPassword ? : } + + + ), + endAdornment: ( + + + + ), + }, + }} + fullWidth + error={!!error} + helperText={!!error && error.message} + /> + ); + }} + name={"password"} + /> + + + + + + + + + ); }; export default LoginForm; diff --git a/src/components/Login/LoginLinkRouting.jsx b/src/components/Login/LoginLinkRouting.jsx index 83c5165..6bc9ff7 100644 --- a/src/components/Login/LoginLinkRouting.jsx +++ b/src/components/Login/LoginLinkRouting.jsx @@ -4,22 +4,22 @@ import Link from "next/link"; import { useSearchParams } from "next/navigation"; const LoginLinkRouting = () => { - const searchParams = useSearchParams(); + const searchParams = useSearchParams(); - const redirect = searchParams.get("redirect"); + const redirect = searchParams.get("redirect"); - return ( - - - - ); + return ( + + + + ); }; export default LoginLinkRouting; diff --git a/src/components/Login/index.jsx b/src/components/Login/index.jsx index d0f485d..ad22bd7 100644 --- a/src/components/Login/index.jsx +++ b/src/components/Login/index.jsx @@ -5,15 +5,15 @@ import LoginLinkRouting from "./LoginLinkRouting"; import { Suspense } from "react"; const LoginPage = () => { - return ( - - - - - - - - - ); + return ( + + + + + + + + + ); }; export default LoginPage; diff --git a/src/components/dashboard/Users/DataTable.jsx b/src/components/dashboard/Users/DataTable.jsx index 71da3fe..5157149 100644 --- a/src/components/dashboard/Users/DataTable.jsx +++ b/src/components/dashboard/Users/DataTable.jsx @@ -13,205 +13,200 @@ import OnlineCell from "./RowActions/Online"; import TelephoneId from "./RowActions/TelephoneId"; const DataTable = () => { - const columns = useMemo( - () => [ - { - accessorKey: "id", - header: "کد یکتا", - id: "id", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - sortDescFirst: false, - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - }, - { - accessorKey: "full_name", - header: "نام و نام خانوادگی", - id: "full_name", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - sortDescFirst: false, - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - }, - { - header: "شماره تماس داخلی", - id: "telephone_id", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - sortDescFirst: false, - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - Cell: ({ row }) => , - }, - { - accessorKey: "is_online", - header: "وضعیت برخط", - id: "is_online", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - sortDescFirst: false, - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - Cell: ({ row }) => , - }, - { - header: "استان", - id: "province_id", - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - grow: false, - size: 130, - ColumnSelectComponent: (props) => { - const { provinces, errorProvinces, loadingProvinces } = - useProvinces(); - const getColumnSelectOptions = useMemo(() => { - if (loadingProvinces) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorProvinces) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "کل کشور" }, - ...provinces.map((province) => ({ - value: province.id, - label: province.name, - })), - ]; - }, [provinces, errorProvinces, loadingProvinces]); - return ( - - ); - }, - Cell: ({ renderedCellValue, row }) => <>{row.original.province_fa}, - }, - { - accessorKey: "username", - header: "نام کاربری", - id: "username", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - sortDescFirst: false, - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - }, - { - accessorKey: "position", - header: "سمت", - id: "position", - enableColumnFilter: false, - grow: false, - size: 100, - }, - { - accessorKey: "phone_number", - header: "شماره همراه", - id: "phone_number", - enableColumnFilter: false, - grow: false, - size: 100, - }, - { - header: "نقش", - id: "role__id", - enableColumnFilter: false, - grow: false, - size: 100, - enableColumnFilter: true, - datatype: "numeric", - filterMode: "equals", - grow: false, - size: 130, - ColumnSelectComponent: (props) => { - const { roles, errorRoles, loadingRoles } = useRoles(); - const getColumnSelectOptions = useMemo(() => { - if (loadingRoles) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorRoles) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "همه نقش ها" }, - ...roles.map((role) => ({ - value: role.id, - label: role.name_fa, - })), - ]; - }, [roles, errorRoles, loadingRoles]); - return ( - - ); - }, - Cell: ({ row }) => <>{row.original.roles[0].name_fa}, - }, - { - accessorKey: "national_id", - header: "کد ملی", - id: "national_id", - enableColumnFilter: true, - datatype: "text", - filterMode: "equals", - sortDescFirst: false, - columnFilterModeOptions: ["equals", "contains"], - grow: false, - size: 100, - }, - { - accessorKey: "gender", - header: "جنسیت", - id: "gender", - enableColumnFilter: false, - grow: false, - size: 100, - Cell: ({ renderedCellValue }) => ( - <>{renderedCellValue == "male" ? "آقا" : "خانم"} - ), - }, - ], - [], - ); + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "full_name", + header: "نام و نام خانوادگی", + id: "full_name", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + header: "شماره تماس داخلی", + id: "telephone_id", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + Cell: ({ row }) => , + }, + { + accessorKey: "is_online", + header: "وضعیت برخط", + id: "is_online", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + Cell: ({ row }) => , + }, + { + header: "استان", + id: "province_id", + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + grow: false, + size: 130, + ColumnSelectComponent: (props) => { + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const getColumnSelectOptions = useMemo(() => { + if (loadingProvinces) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorProvinces) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "کل کشور" }, + ...provinces.map((province) => ({ + value: province.id, + label: province.name, + })), + ]; + }, [provinces, errorProvinces, loadingProvinces]); + return ( + + ); + }, + Cell: ({ renderedCellValue, row }) => <>{row.original.province_fa}, + }, + { + accessorKey: "username", + header: "نام کاربری", + id: "username", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "position", + header: "سمت", + id: "position", + enableColumnFilter: false, + grow: false, + size: 100, + }, + { + accessorKey: "phone_number", + header: "شماره همراه", + id: "phone_number", + enableColumnFilter: false, + grow: false, + size: 100, + }, + { + header: "نقش", + id: "role__id", + enableColumnFilter: false, + grow: false, + size: 100, + enableColumnFilter: true, + datatype: "numeric", + filterMode: "equals", + grow: false, + size: 130, + ColumnSelectComponent: (props) => { + const { roles, errorRoles, loadingRoles } = useRoles(); + const getColumnSelectOptions = useMemo(() => { + if (loadingRoles) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorRoles) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "همه نقش ها" }, + ...roles.map((role) => ({ + value: role.id, + label: role.name_fa, + })), + ]; + }, [roles, errorRoles, loadingRoles]); + return ( + + ); + }, + Cell: ({ row }) => <>{row.original.roles[0].name_fa}, + }, + { + accessorKey: "national_id", + header: "کد ملی", + id: "national_id", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "gender", + header: "جنسیت", + id: "gender", + enableColumnFilter: false, + grow: false, + size: 100, + Cell: ({ renderedCellValue }) => <>{renderedCellValue == "male" ? "آقا" : "خانم"}, + }, + ], + [] + ); - return ( - <> - - - - - ); + return ( + <> + + + + + ); }; export default DataTable; diff --git a/src/components/dashboard/Users/RowActions/Delete/DeleteContent.jsx b/src/components/dashboard/Users/RowActions/Delete/DeleteContent.jsx index 36a8710..693e441 100644 --- a/src/components/dashboard/Users/RowActions/Delete/DeleteContent.jsx +++ b/src/components/dashboard/Users/RowActions/Delete/DeleteContent.jsx @@ -1,56 +1,39 @@ import { DELETE_USER } from "@/core/utils/routes"; import useRequest from "@/lib/hooks/useRequest"; -import { - Button, - DialogActions, - DialogContent, - Stack, - Typography, -} from "@mui/material"; +import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material"; import { useState } from "react"; const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => { - const [submitting, setSubmitting] = useState(false); - const requestServer = useRequest({ notificationSuccess: true }); - const handleClick = async () => { - setSubmitting(true); - try { - await requestServer(`${DELETE_USER}/${rowId}`, "delete"); - mutate(); - setOpenDeleteDialog(false); - } catch (error) { - } finally { - setSubmitting(false); - } - }; - return ( - <> - - - آیا از حذف کاربر اطمینان دارید؟ - - - - - - - - ); + const [submitting, setSubmitting] = useState(false); + const requestServer = useRequest({ notificationSuccess: true }); + const handleClick = async () => { + setSubmitting(true); + try { + await requestServer(`${DELETE_USER}/${rowId}`, "delete"); + mutate(); + setOpenDeleteDialog(false); + } catch (error) { + } finally { + setSubmitting(false); + } + }; + return ( + <> + + + آیا از حذف کاربر اطمینان دارید؟ + + + + + + + + ); }; export default DeleteContent; diff --git a/src/components/dashboard/Users/RowActions/Delete/index.jsx b/src/components/dashboard/Users/RowActions/Delete/index.jsx index 5f55897..7d045bf 100644 --- a/src/components/dashboard/Users/RowActions/Delete/index.jsx +++ b/src/components/dashboard/Users/RowActions/Delete/index.jsx @@ -3,35 +3,30 @@ import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; import { useState } from "react"; import DeleteContent from "./DeleteContent"; const Delete = ({ rowId, mutate }) => { - const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); - return ( - <> - - setOpenDeleteDialog(true)}> - - - - setOpenDeleteDialog(false)} - PaperProps={{ - sx: { - boxShadow: - "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", - }, - }} - dir="rtl" - maxWidth={"md"} - > - حذف - - - - ); + return ( + <> + + setOpenDeleteDialog(true)}> + + + + setOpenDeleteDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + dir="rtl" + maxWidth={"md"} + > + حذف + + + + ); }; export default Delete; diff --git a/src/components/dashboard/Users/RowActions/Edit/Form/index.jsx b/src/components/dashboard/Users/RowActions/Edit/Form/index.jsx index 3094eb3..2686f27 100644 --- a/src/components/dashboard/Users/RowActions/Edit/Form/index.jsx +++ b/src/components/dashboard/Users/RowActions/Edit/Form/index.jsx @@ -7,363 +7,357 @@ import useRequest from "@/lib/hooks/useRequest"; import useRoles from "@/lib/hooks/useRoles"; import { yupResolver } from "@hookform/resolvers/yup"; import { - Button, - Chip, - DialogActions, - DialogContent, - Divider, - FormControl, - FormHelperText, - Grid, - InputLabel, - MenuItem, - OutlinedInput, - Select, - Stack, - TextField, + Button, + Chip, + DialogActions, + DialogContent, + Divider, + FormControl, + FormHelperText, + Grid, + InputLabel, + MenuItem, + OutlinedInput, + Select, + Stack, + TextField, } from "@mui/material"; import { useMemo } from "react"; import { Controller, useForm } from "react-hook-form"; import { object, string } from "yup"; const validationSchema = object().shape({ - full_name: string().required("نام و نام خانوادگی خود را وارد کنید"), - username: string().required("نام کاربری خود را وارد کنید"), - phone_number: string() - .matches(/^09\d{9}$/, "شماره همراه باید با 09 شروع شود و 11 رقم باشد.") - .required("شماره همراه خود را وارد کنید"), - gender: string().required("جنسیت خود را وارد کنید"), - national_id: string() - .test( - "max", - "کد ملی باید شامل 10 رقم باشد", - (value) => value.toString().length === 10, - ) - .test("validation", "کد ملی صحیح نمی باشد", (value) => - validateNationalCode(value), - ) - .required("کد ملی خود را وارد کنید"), - position: string().required("سمت خود را وارد کنید"), - province_id: string().required("استان خود را وارد کنید"), - role_id: string().required("نقش خود را وارد کنید"), + full_name: string().required("نام و نام خانوادگی خود را وارد کنید"), + username: string().required("نام کاربری خود را وارد کنید"), + phone_number: string() + .matches(/^09\d{9}$/, "شماره همراه باید با 09 شروع شود و 11 رقم باشد.") + .required("شماره همراه خود را وارد کنید"), + gender: string().required("جنسیت خود را وارد کنید"), + national_id: string() + .test("max", "کد ملی باید شامل 10 رقم باشد", (value) => value.toString().length === 10) + .test("validation", "کد ملی صحیح نمی باشد", (value) => validateNationalCode(value)) + .required("کد ملی خود را وارد کنید"), + position: string().required("سمت خود را وارد کنید"), + province_id: string().required("استان خود را وارد کنید"), + role_id: string().required("نقش خود را وارد کنید"), }); const UpdateUserForm = ({ values, setOpen, mutate }) => { - const requestServer = useRequest({ notificationSuccess: true }); - const { provinces, errorProvinces, loadingProvinces } = useProvinces(); - const { roles, errorRoles, loadingRoles } = useRoles(); + const requestServer = useRequest({ notificationSuccess: true }); + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const { roles, errorRoles, loadingRoles } = useRoles(); - const defaultValues = { - full_name: values.full_name, - username: values.username, - position: values.position, - gender: values.gender, - national_id: values.national_id, - phone_number: values.phone_number, - province_id: values.province_id, - role_id: values.roles[0].id, - }; + const defaultValues = { + full_name: values.full_name, + username: values.username, + position: values.position, + gender: values.gender, + national_id: values.national_id, + phone_number: values.phone_number, + province_id: values.province_id, + role_id: values.roles[0].id, + }; - const provinceSelectOptions = useMemo(() => { - if (loadingProvinces) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorProvinces) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "انتخاب استان" }, - ...provinces.map((province) => ({ - value: province.id, - label: province.name, - })), - ]; - }, [provinces, errorProvinces, loadingProvinces]); + const provinceSelectOptions = useMemo(() => { + if (loadingProvinces) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorProvinces) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "انتخاب استان" }, + ...provinces.map((province) => ({ + value: province.id, + label: province.name, + })), + ]; + }, [provinces, errorProvinces, loadingProvinces]); - const roleSelectOptions = useMemo(() => { - if (loadingRoles) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorRoles) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "انتخاب نقش" }, - ...roles.map((role) => ({ - value: role.id, - label: role.name_fa, - })), - ]; - }, [roles, errorRoles, loadingRoles]); + const roleSelectOptions = useMemo(() => { + if (loadingRoles) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorRoles) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "انتخاب نقش" }, + ...roles.map((role) => ({ + value: role.id, + label: role.name_fa, + })), + ]; + }, [roles, errorRoles, loadingRoles]); - const { - control, - handleSubmit, - formState: { isSubmitting, errors }, - } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); + const { + control, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); - const onSubmit = async (data) => { - const formData = new FormData(); - Object.keys(data).forEach((key) => { - formData.append(key, data[key]); - }); - try { - await requestServer(`${UPDATE_USER}/${values.id}`, "post", { - data: formData, - }); - setOpen(false); - mutate(); - } catch (error) {} - }; + const onSubmit = async (data) => { + const formData = new FormData(); + Object.keys(data).forEach((key) => { + formData.append(key, data[key]); + }); + try { + await requestServer(`${UPDATE_USER}/${values.id}`, "post", { + data: formData, + }); + setOpen(false); + mutate(); + } catch (error) {} + }; - return ( - <> - - - - - - - - - { - return ( - - ); - }} - name={"username"} - /> - - - { - return ( - - ); - }} - name={"full_name"} - /> - - - { - return ( - - ); - }} - name={"position"} - /> - - - { - return ( - { - const inputValue = event.target.value; - if (isNaN(Number(inputValue))) { - return; - } - if (inputValue.length > 11) { - return; - } - field.onChange(inputValue); - }} - error={!!error} - helperText={!!error && error.message} - /> - ); - }} - name={"phone_number"} - /> - - - { - return ( - - - جنسیت - - - - {!!error && error.message} - - - ); - }} - name={"gender"} - /> - - - { - return ( - { - const inputValue = event.target.value; - if (isNaN(Number(inputValue))) { - return; - } - if (inputValue.length > 10) { - return; - } - field.onChange(inputValue); - }} - error={!!error} - helperText={!!error && error.message} - /> - ); - }} - name={"national_id"} - /> - - - { - return ( - - - استان - - - - {!!error && error.message} - - - ); - }} - name={"province_id"} - /> - - - { - return ( - - - نقش - - - - {!!error && error.message} - - - ); - }} - name={"role_id"} - /> - - - - - - - - - - - ); + return ( + <> + + + + + + + + + { + return ( + + ); + }} + name={"username"} + /> + + + { + return ( + + ); + }} + name={"full_name"} + /> + + + { + return ( + + ); + }} + name={"position"} + /> + + + { + return ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + if (inputValue.length > 11) { + return; + } + field.onChange(inputValue); + }} + error={!!error} + helperText={!!error && error.message} + /> + ); + }} + name={"phone_number"} + /> + + + { + return ( + + + جنسیت + + + + {!!error && error.message} + + + ); + }} + name={"gender"} + /> + + + { + return ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + if (inputValue.length > 10) { + return; + } + field.onChange(inputValue); + }} + error={!!error} + helperText={!!error && error.message} + /> + ); + }} + name={"national_id"} + /> + + + { + return ( + + + استان + + + + {!!error && error.message} + + + ); + }} + name={"province_id"} + /> + + + { + return ( + + + نقش + + + + {!!error && error.message} + + + ); + }} + name={"role_id"} + /> + + + + + + + + + + + ); }; export default UpdateUserForm; diff --git a/src/components/dashboard/Users/RowActions/Edit/index.jsx b/src/components/dashboard/Users/RowActions/Edit/index.jsx index 22c7638..1aa42c4 100644 --- a/src/components/dashboard/Users/RowActions/Edit/index.jsx +++ b/src/components/dashboard/Users/RowActions/Edit/index.jsx @@ -5,28 +5,23 @@ import { useState } from "react"; import UpdateUserForm from "./Form"; const UpdateUser = ({ values, mutate }) => { - const [open, setOpen] = useState(false); + const [open, setOpen] = useState(false); - const handleOpen = () => { - setOpen(true); - }; + const handleOpen = () => { + setOpen(true); + }; - return ( - <> - - - - - - - - - - ); + return ( + <> + + + + + + + + + + ); }; export default UpdateUser; diff --git a/src/components/dashboard/Users/RowActions/Online/index.jsx b/src/components/dashboard/Users/RowActions/Online/index.jsx index 14a730e..bf7645a 100644 --- a/src/components/dashboard/Users/RowActions/Online/index.jsx +++ b/src/components/dashboard/Users/RowActions/Online/index.jsx @@ -3,15 +3,11 @@ import { Power, PowerOff } from "@mui/icons-material"; import { Stack } from "@mui/material"; const OnlineCell = ({ user_id }) => { - const { clientsOnline } = useSocket(); - return ( - - {clientsOnline.some((co) => co.user_id == user_id) ? ( - - ) : ( - - )} - - ); + const { clientsOnline } = useSocket(); + return ( + + {clientsOnline.some((co) => co.user_id == user_id) ? : } + + ); }; export default OnlineCell; diff --git a/src/components/dashboard/Users/RowActions/TelephoneId/index.jsx b/src/components/dashboard/Users/RowActions/TelephoneId/index.jsx index 63aea1b..44e5e63 100644 --- a/src/components/dashboard/Users/RowActions/TelephoneId/index.jsx +++ b/src/components/dashboard/Users/RowActions/TelephoneId/index.jsx @@ -2,10 +2,8 @@ import { useSocket } from "@/lib/contexts/socket"; import { Stack } from "@mui/material"; const TelephoneId = ({ user_id }) => { - const { clientsOnline } = useSocket(); - const telephone_id = clientsOnline.find( - (co) => co.user_id == user_id, - )?.telephone_id; - return {telephone_id}; + const { clientsOnline } = useSocket(); + const telephone_id = clientsOnline.find((co) => co.user_id == user_id)?.telephone_id; + return {telephone_id}; }; export default TelephoneId; diff --git a/src/components/dashboard/Users/RowActions/index.jsx b/src/components/dashboard/Users/RowActions/index.jsx index 2b15ee4..b551a15 100644 --- a/src/components/dashboard/Users/RowActions/index.jsx +++ b/src/components/dashboard/Users/RowActions/index.jsx @@ -2,11 +2,11 @@ import { Box } from "@mui/material"; import Delete from "./Delete"; import UpdateUser from "./Edit"; const RowActions = ({ row, mutate }) => { - return ( - - - - - ); + return ( + + + + + ); }; export default RowActions; diff --git a/src/components/dashboard/Users/Toolbar/Create/Form/index.jsx b/src/components/dashboard/Users/Toolbar/Create/Form/index.jsx index c84864a..6c51e4c 100644 --- a/src/components/dashboard/Users/Toolbar/Create/Form/index.jsx +++ b/src/components/dashboard/Users/Toolbar/Create/Form/index.jsx @@ -4,22 +4,22 @@ import validateNationalCode from "@/core/utils/nationalCodeValidation"; import useProvinces from "@/lib/hooks/useProvince"; import { yupResolver } from "@hookform/resolvers/yup"; import { - Button, - Chip, - DialogActions, - DialogContent, - Divider, - FormControl, - FormHelperText, - Grid, - IconButton, - InputAdornment, - InputLabel, - MenuItem, - OutlinedInput, - Select, - Stack, - TextField, + Button, + Chip, + DialogActions, + DialogContent, + Divider, + FormControl, + FormHelperText, + Grid, + IconButton, + InputAdornment, + InputLabel, + MenuItem, + OutlinedInput, + Select, + Stack, + TextField, } from "@mui/material"; import { Controller, useForm } from "react-hook-form"; import { object, string } from "yup"; @@ -30,387 +30,375 @@ import { CREATE_USER } from "@/core/utils/routes"; import { Visibility, VisibilityOff } from "@mui/icons-material"; const defaultValues = { - full_name: "", - username: "", - position: "", - gender: "male", - national_id: "", - phone_number: "", - province_id: "", - password: "", - role_id: "", + full_name: "", + username: "", + position: "", + gender: "male", + national_id: "", + phone_number: "", + province_id: "", + password: "", + role_id: "", + telephone_id: "", }; const validationSchema = object().shape({ - full_name: string().required("نام و نام خانوادگی خود را وارد کنید"), - username: string().required("نام کاربری خود را وارد کنید"), - phone_number: string() - .matches(/^09\d{9}$/, "شماره همراه باید با 09 شروع شود و 11 رقم باشد.") - .required("شماره همراه خود را وارد کنید"), - gender: string().required("جنسیت خود را وارد کنید"), - national_id: string() - .test( - "max", - "کد ملی باید شامل 10 رقم باشد", - (value) => value.toString().length === 10, - ) - .test("validation", "کد ملی صحیح نمی باشد", (value) => - validateNationalCode(value), - ) - .required("کد ملی خود را وارد کنید"), - password: string() - .required("رمز عبور خود را وارد کنید") - .matches( - /^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, - "رمز عبور باید حداقل 8 کاراکتر و متشکل از عدد، حرف یا سمبل باشد", - ), - position: string().required("سمت خود را وارد کنید"), - province_id: string().required("استان خود را وارد کنید"), - role_id: string().required("نقش خود را وارد کنید"), + full_name: string().required("نام و نام خانوادگی خود را وارد کنید"), + username: string().required("نام کاربری خود را وارد کنید"), + phone_number: string() + .matches(/^09\d{9}$/, "شماره همراه باید با 09 شروع شود و 11 رقم باشد.") + .required("شماره همراه خود را وارد کنید"), + gender: string().required("جنسیت خود را وارد کنید"), + national_id: string() + .test("max", "کد ملی باید شامل 10 رقم باشد", (value) => value.toString().length === 10) + .test("validation", "کد ملی صحیح نمی باشد", (value) => validateNationalCode(value)) + .required("کد ملی خود را وارد کنید"), + password: string() + .required("رمز عبور خود را وارد کنید") + .matches(/^(?=.*[a-zA-Z])(?=.*\d).{8,}$/, "رمز عبور باید حداقل 8 کاراکتر و متشکل از عدد، حرف یا سمبل باشد"), + position: string().required("سمت خود را وارد کنید"), + province_id: string().required("استان خود را وارد کنید"), + role_id: string().required("نقش خود را وارد کنید"), }); const CreateUserForm = ({ setOpen, mutate }) => { - const requestServer = useRequest({ notificationSuccess: true }); - const [showPassword, setShowPassword] = useState(false); - const { provinces, errorProvinces, loadingProvinces } = useProvinces(); - const { roles, errorRoles, loadingRoles } = useRoles(); + const requestServer = useRequest({ notificationSuccess: true }); + const [showPassword, setShowPassword] = useState(false); + const { provinces, errorProvinces, loadingProvinces } = useProvinces(); + const { roles, errorRoles, loadingRoles } = useRoles(); - const handleClickShowPassword = () => setShowPassword((show) => !show); + const handleClickShowPassword = () => setShowPassword((show) => !show); - const provinceSelectOptions = useMemo(() => { - if (loadingProvinces) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorProvinces) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "انتخاب استان" }, - ...provinces.map((province) => ({ - value: province.id, - label: province.name, - })), - ]; - }, [provinces, errorProvinces, loadingProvinces]); + const provinceSelectOptions = useMemo(() => { + if (loadingProvinces) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorProvinces) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "انتخاب استان" }, + ...provinces.map((province) => ({ + value: province.id, + label: province.name, + })), + ]; + }, [provinces, errorProvinces, loadingProvinces]); - const roleSelectOptions = useMemo(() => { - if (loadingRoles) { - return [{ value: "loading", label: "در حال بارگذاری..." }]; - } - if (errorRoles) { - return [{ value: "error", label: "خطا در بارگذاری" }]; - } - return [ - { value: "", label: "انتخاب نقش" }, - ...roles.map((role) => ({ - value: role.id, - label: role.name_fa, - })), - ]; - }, [roles, errorRoles, loadingRoles]); + const roleSelectOptions = useMemo(() => { + if (loadingRoles) { + return [{ value: "loading", label: "در حال بارگذاری..." }]; + } + if (errorRoles) { + return [{ value: "error", label: "خطا در بارگذاری" }]; + } + return [ + { value: "", label: "انتخاب نقش" }, + ...roles.map((role) => ({ + value: role.id, + label: role.name_fa, + })), + ]; + }, [roles, errorRoles, loadingRoles]); - const { - control, - handleSubmit, - formState: { isSubmitting, errors }, - } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); + const { + control, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); - const onSubmit = async (data) => { - const formData = new FormData(); - Object.keys(data).forEach((key) => { - formData.append(key, data[key]); - }); - try { - await requestServer(CREATE_USER, "post", { - data: formData, - }); - setOpen(false); - mutate(); - } catch (error) {} - }; + const onSubmit = async (data) => { + const formData = new FormData(); + Object.keys(data).forEach((key) => { + formData.append(key, data[key]); + }); + try { + await requestServer(CREATE_USER, "post", { + data: formData, + }); + setOpen(false); + mutate(); + } catch (error) {} + }; - return ( - <> - - - - - - - - - { - return ( - - ); - }} - name={"username"} - /> - - - { - return ( - - - {showPassword ? ( - - ) : ( - - )} - - - ), - }, - }} - fullWidth - error={!!error} - helperText={!!error && error.message} - /> - ); - }} - name={"password"} - /> - - - { - return ( - - ); - }} - name={"full_name"} - /> - - - { - return ( - - ); - }} - name={"position"} - /> - - - { - return ( - { - const inputValue = event.target.value; - if (isNaN(Number(inputValue))) { - return; - } - if (inputValue.length > 11) { - return; - } - field.onChange(inputValue); - }} - error={!!error} - helperText={!!error && error.message} - /> - ); - }} - name={"phone_number"} - /> - - - { - return ( - - - جنسیت - - - - {!!error && error.message} - - - ); - }} - name={"gender"} - /> - - - { - return ( - { - const inputValue = event.target.value; - if (isNaN(Number(inputValue))) { - return; - } - if (inputValue.length > 10) { - return; - } - field.onChange(inputValue); - }} - error={!!error} - helperText={!!error && error.message} - /> - ); - }} - name={"national_id"} - /> - - - { - return ( - - - استان - - - - {!!error && error.message} - - - ); - }} - name={"province_id"} - /> - - - { - return ( - - - نقش - - - - {!!error && error.message} - - - ); - }} - name={"role_id"} - /> - - - - - - - - - - - ); + return ( + <> + + + + + + + + + { + return ( + + ); + }} + name={"username"} + /> + + + { + return ( + + + {showPassword ? : } + + + ), + }, + }} + fullWidth + error={!!error} + helperText={!!error && error.message} + /> + ); + }} + name={"password"} + /> + + + { + return ( + + ); + }} + name={"full_name"} + /> + + + { + return ( + + ); + }} + name={"position"} + /> + + + { + return ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + if (inputValue.length > 11) { + return; + } + field.onChange(inputValue); + }} + error={!!error} + helperText={!!error && error.message} + /> + ); + }} + name={"phone_number"} + /> + + + { + return ( + + + جنسیت + + + + {!!error && error.message} + + + ); + }} + name={"gender"} + /> + + + { + return ( + { + const inputValue = event.target.value; + if (isNaN(Number(inputValue))) { + return; + } + if (inputValue.length > 10) { + return; + } + field.onChange(inputValue); + }} + error={!!error} + helperText={!!error && error.message} + /> + ); + }} + name={"national_id"} + /> + + + { + return ( + + + استان + + + + {!!error && error.message} + + + ); + }} + name={"province_id"} + /> + + + { + return ( + + + نقش + + + + {!!error && error.message} + + + ); + }} + name={"role_id"} + /> + + + + + + + + + + + ); }; export default CreateUserForm; diff --git a/src/components/dashboard/Users/Toolbar/Create/index.jsx b/src/components/dashboard/Users/Toolbar/Create/index.jsx index 2af6c35..99d3e26 100644 --- a/src/components/dashboard/Users/Toolbar/Create/index.jsx +++ b/src/components/dashboard/Users/Toolbar/Create/index.jsx @@ -1,49 +1,39 @@ "use client"; import { AddCircle } from "@mui/icons-material"; -import { - Button, - Dialog, - IconButton, - useMediaQuery, - useTheme, -} from "@mui/material"; +import { Button, Dialog, IconButton, useMediaQuery, useTheme } from "@mui/material"; import CreateUserForm from "./Form"; import { useState } from "react"; const CreateUser = ({ mutate }) => { - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down("sm")); - const [open, setOpen] = useState(false); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [open, setOpen] = useState(false); - const handleOpen = () => { - setOpen(true); - }; + const handleOpen = () => { + setOpen(true); + }; - return ( - <> - {isMobile ? ( - - - - ) : ( - - )} - - - - - ); + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + + + + + ); }; export default CreateUser; diff --git a/src/components/dashboard/Users/Toolbar/index.jsx b/src/components/dashboard/Users/Toolbar/index.jsx index 58b990f..cc33101 100644 --- a/src/components/dashboard/Users/Toolbar/index.jsx +++ b/src/components/dashboard/Users/Toolbar/index.jsx @@ -1,10 +1,10 @@ import CreateUser from "./Create"; const Toolbar = ({ mutate }) => { - return ( - <> - - - ); + return ( + <> + + + ); }; export default Toolbar; diff --git a/src/components/dashboard/Users/index.jsx b/src/components/dashboard/Users/index.jsx index 5c4e237..55ca962 100644 --- a/src/components/dashboard/Users/index.jsx +++ b/src/components/dashboard/Users/index.jsx @@ -3,12 +3,12 @@ import { Stack } from "@mui/material"; import DataTable from "./DataTable"; const UsersPage = () => { - return ( - - - - - ); + return ( + + + + + ); }; export default UsersPage; diff --git a/src/components/dashboard/dashboard/OnlineUsersReport/index.jsx b/src/components/dashboard/dashboard/OnlineUsersReport/index.jsx index ee62cbc..f202cd6 100644 --- a/src/components/dashboard/dashboard/OnlineUsersReport/index.jsx +++ b/src/components/dashboard/dashboard/OnlineUsersReport/index.jsx @@ -3,10 +3,6 @@ import { Stack } from "@mui/material"; const OnlineUsersReport = () => { const { clientsOnline } = useSocket(); - return ( - - clientsOnline: {clientsOnline.length} - - ) -} -export default OnlineUsersReport; \ No newline at end of file + return clientsOnline: {clientsOnline.length}; +}; +export default OnlineUsersReport; diff --git a/src/components/dashboard/dashboard/index.jsx b/src/components/dashboard/dashboard/index.jsx index ca6dc5b..29faec3 100644 --- a/src/components/dashboard/dashboard/index.jsx +++ b/src/components/dashboard/dashboard/index.jsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import { Stack } from "@mui/material"; import OnlineUsersReport from "./OnlineUsersReport"; @@ -7,6 +7,6 @@ const DashboardPage = () => { - ) -} -export default DashboardPage; \ No newline at end of file + ); +}; +export default DashboardPage; diff --git a/src/components/layouts/dashboard/headerWithSidebar/HeaderMenu/index.jsx b/src/components/layouts/dashboard/headerWithSidebar/HeaderMenu/index.jsx index 74c471a..92c9553 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/HeaderMenu/index.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/HeaderMenu/index.jsx @@ -1,60 +1,45 @@ import { ExpandLess, ExpandMore, Link } from "@mui/icons-material"; -import { - Button, - Divider, - ListItemIcon, - ListItemText, - Menu, - MenuItem, - Stack, -} from "@mui/material"; +import { Button, Divider, ListItemIcon, ListItemText, Menu, MenuItem, Stack } from "@mui/material"; import NextLink from "next/link"; import { useState } from "react"; const HeaderMenu = ({ menu }) => { - const [anchorEl, setAnchorEl] = useState(null); - const open = Boolean(anchorEl); + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); - const handleClick = (event) => { - setAnchorEl(event.currentTarget); - }; - const handleClose = () => { - setAnchorEl(null); - }; + const handleClick = (event) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; - return ( - - - - {menu.subMenu.flatMap((subMenu, index) => [ - ...subMenu.map((sub) => ( - + - - ); + {menu.title} + + + {menu.subMenu.flatMap((subMenu, index) => [ + ...subMenu.map((sub) => ( + + + + + {sub.title} + + )), + index < menu.subMenu.length - 1 && , + ])} + + + ); }; export default HeaderMenu; diff --git a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx index 239a5e6..5f0fa7a 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarBadge.jsx @@ -4,16 +4,16 @@ import { Chip } from "@mui/material"; import { useEffect, useState } from "react"; const SidebarBadge = ({ badge, chipProps = {} }) => { - const { data } = useSidebarBadge(); - const [value, setValue] = useState(); + const { data } = useSidebarBadge(); + const [value, setValue] = useState(); - useEffect(() => { - setValue(getValueByPath(data, badge)); - }, [data, badge]); + useEffect(() => { + setValue(getValueByPath(data, badge)); + }, [data, badge]); - if (!data) return null; - if (!value) return null; + if (!data) return null; + if (!value) return null; - return ; + return ; }; export default SidebarBadge; diff --git a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarListItems.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarListItems.jsx index 4b4e640..c61dbe3 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarListItems.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarListItems.jsx @@ -1,92 +1,67 @@ import { ExpandLess, ExpandMore } from "@mui/icons-material"; -import { - Collapse, - List, - ListItem, - ListItemButton, - ListItemIcon, - ListItemText, - Stack, -} from "@mui/material"; +import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Stack } from "@mui/material"; import Link from "next/link"; import SidebarBadge from "./SidebarBadge"; import SidebarSubitems from "./SidebarSubitems"; const SidebarListItems = ({ menuItem, dispatch }) => { - return ( - <> - - { - if (menuItem.type !== "page") { - dispatch({ type: "COLLAPSE_MENU", id: menuItem.id }); - } - }} - > - - {menuItem.icon} - - - {menuItem.badges && ( - - {menuItem.badges.map((badge, i) => ( - - ))} - - )} - {menuItem.hasSubitems ? ( - menuItem.showSubitems ? ( - - ) : ( - - ) - ) : null} - - - - {menuItem.hasSubitems ? ( - - {menuItem.Subitems.map((subitem, index) => { - return ( - - ); - })} - - ) : null} - - - ); + return ( + <> + + { + if (menuItem.type !== "page") { + dispatch({ type: "COLLAPSE_MENU", id: menuItem.id }); + } + }} + > + + {menuItem.icon} + + + {menuItem.badges && ( + + {menuItem.badges.map((badge, i) => ( + + ))} + + )} + {menuItem.hasSubitems ? menuItem.showSubitems ? : : null} + + + + {menuItem.hasSubitems ? ( + + {menuItem.Subitems.map((subitem, index) => { + return ; + })} + + ) : null} + + + ); }; export default SidebarListItems; diff --git a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarMenu.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarMenu.jsx index 29c2b09..1bfb012 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarMenu.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarMenu.jsx @@ -9,120 +9,106 @@ import SidebarListItems from "./SidebarListItems"; import Profile from "@/core/components/Profile"; function selectPage(item, route) { - if (item.type === "page") { - return { - ...item, - selected: item.route === route, - showSubitems: item.route === route, - }; - } else if (item.Subitems && Array.isArray(item.Subitems)) { - const updatedSubitems = item.Subitems.map((subitem) => - selectPage(subitem, route), - ); - return { - ...item, - Subitems: updatedSubitems, - showSubitems: updatedSubitems.some( - (subitem) => subitem.showSubitems || subitem.route === route, - ), - }; - } - return item; + if (item.type === "page") { + return { + ...item, + selected: item.route === route, + showSubitems: item.route === route, + }; + } else if (item.Subitems && Array.isArray(item.Subitems)) { + const updatedSubitems = item.Subitems.map((subitem) => selectPage(subitem, route)); + return { + ...item, + Subitems: updatedSubitems, + showSubitems: updatedSubitems.some((subitem) => subitem.showSubitems || subitem.route === route), + }; + } + return item; } function toggleSubitems(items, actionId) { - return items.map((item) => - actionId === item.id - ? { ...item, showSubitems: !item.showSubitems } - : { ...item, showSubitems: false }, - ); + return items.map((item) => + actionId === item.id ? { ...item, showSubitems: !item.showSubitems } : { ...item, showSubitems: false } + ); } function reducer(state, action) { - switch (action.type) { - case "UPDATE_MENU": - const _permissions = action.permissions || []; - return filterMenuItems(state, ["all", ..._permissions]); + switch (action.type) { + case "UPDATE_MENU": + const _permissions = action.permissions || []; + return filterMenuItems(state, ["all", ..._permissions]); - case "COLLAPSE_MENU": - return state.map((item) => ({ - ...item, - showSubitems: item.id === action.id ? !item.showSubitems : false, - })); + case "COLLAPSE_MENU": + return state.map((item) => ({ + ...item, + showSubitems: item.id === action.id ? !item.showSubitems : false, + })); - case "COLLAPSE_SUB_ITEMS": - return state.map((item) => - item.hasSubitems - ? { ...item, Subitems: toggleSubitems(item.Subitems, action.id) } - : item, - ); + case "COLLAPSE_SUB_ITEMS": + return state.map((item) => + item.hasSubitems ? { ...item, Subitems: toggleSubitems(item.Subitems, action.id) } : item + ); - case "COLLAPSE_SUB_SECOND_ITEMS": - return state.map((item) => - item.hasSubitems - ? { - ...item, - Subitems: item.Subitems.map((subitem) => - subitem.hasSubitems - ? { - ...subitem, - Subitems: toggleSubitems(subitem.Subitems, action.id), - } - : subitem, - ), - } - : item, - ); + case "COLLAPSE_SUB_SECOND_ITEMS": + return state.map((item) => + item.hasSubitems + ? { + ...item, + Subitems: item.Subitems.map((subitem) => + subitem.hasSubitems + ? { + ...subitem, + Subitems: toggleSubitems(subitem.Subitems, action.id), + } + : subitem + ), + } + : item + ); - case "SELECTED": - return state.map((item) => selectPage(item, action.route)); + case "SELECTED": + return state.map((item) => selectPage(item, action.route)); - default: - throw new Error(); - } + default: + throw new Error(); + } } const SidebarMenu = () => { - const { data: userPermissions } = usePermissions(); - const [menuItems, dispatch] = useReducer(reducer, pageMenu); - const pathname = usePathname(); - const [selectedKey, setSelectedKey] = useState(null); + const { data: userPermissions } = usePermissions(); + const [menuItems, dispatch] = useReducer(reducer, pageMenu); + const pathname = usePathname(); + const [selectedKey, setSelectedKey] = useState(null); - useEffect(() => { - dispatch({ type: "SELECTED", route: pathname }); - setSelectedKey(pathname); - }, [userPermissions, pathname]); + useEffect(() => { + dispatch({ type: "SELECTED", route: pathname }); + setSelectedKey(pathname); + }, [userPermissions, pathname]); - useEffect(() => { - if (!userPermissions) return; - dispatch({ type: "UPDATE_MENU", permissions: userPermissions }); - }, [userPermissions]); + useEffect(() => { + if (!userPermissions) return; + dispatch({ type: "UPDATE_MENU", permissions: userPermissions }); + }, [userPermissions]); - useEffect(() => { - selectedKey && - document.querySelector(`[data-route="${selectedKey}"]`)?.scrollIntoView({ - behavior: "smooth", - block: "center", - }); - }, [selectedKey]); + useEffect(() => { + selectedKey && + document.querySelector(`[data-route="${selectedKey}"]`)?.scrollIntoView({ + behavior: "smooth", + block: "center", + }); + }, [selectedKey]); - return ( - <> - - {userPermissions && ( - - {menuItems.map((menuItem) => { - return ( - - ); - })} - - )} - - ); + return ( + <> + + {userPermissions && ( + + {menuItems.map((menuItem) => { + return ; + })} + + )} + + ); }; export default SidebarMenu; diff --git a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx index e74204b..ba0cd5f 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/Sidebar/SidebarSubitems.jsx @@ -1,96 +1,76 @@ import { ExpandLess, ExpandMore } from "@mui/icons-material"; -import { - Box, - Collapse, - List, - ListItem, - ListItemButton, - ListItemIcon, - ListItemText, - Stack, -} from "@mui/material"; +import { Box, Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Stack } from "@mui/material"; import Link from "next/link"; import SidebarBadge from "./SidebarBadge"; const SidebarSubitems = ({ subitem, dispatch }) => { - return ( - <> - - { - if (subitem.type !== "page") { - dispatch({ type: "COLLAPSE_SUB_ITEMS", id: subitem.id }); - } - }} - > - - {subitem.icon} - - - {subitem.badges && ( - - {subitem.badges.map((badge, i) => ( - - ))} - - )} - {subitem.hasSubitems ? ( - subitem.showSubitems ? ( - - ) : ( - - ) - ) : ( - - )} - - - - {subitem.hasSubitems ? ( - - {subitem.Subitems.map((subSubitem, index) => { - return ( - - ); - })} - - ) : null} - - - ); + return ( + <> + + { + if (subitem.type !== "page") { + dispatch({ type: "COLLAPSE_SUB_ITEMS", id: subitem.id }); + } + }} + > + + {subitem.icon} + + + {subitem.badges && ( + + {subitem.badges.map((badge, i) => ( + + ))} + + )} + {subitem.hasSubitems ? ( + subitem.showSubitems ? ( + + ) : ( + + ) + ) : ( + + )} + + + + {subitem.hasSubitems ? ( + + {subitem.Subitems.map((subSubitem, index) => { + return ; + })} + + ) : null} + + + ); }; export default SidebarSubitems; diff --git a/src/components/layouts/dashboard/headerWithSidebar/index.jsx b/src/components/layouts/dashboard/headerWithSidebar/index.jsx index 6fb683a..4b58b78 100644 --- a/src/components/layouts/dashboard/headerWithSidebar/index.jsx +++ b/src/components/layouts/dashboard/headerWithSidebar/index.jsx @@ -1,17 +1,7 @@ "use client"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import MenuIcon from "@mui/icons-material/Menu"; -import { - Box, - Drawer, - IconButton, - Stack, - styled, - Toolbar, - Typography, - useMediaQuery, - useTheme, -} from "@mui/material"; +import { Box, Drawer, IconButton, Stack, styled, Toolbar, Typography, useMediaQuery, useTheme } from "@mui/material"; import MuiAppBar from "@mui/material/AppBar"; import { useState, useEffect } from "react"; import HeaderMenu from "./HeaderMenu"; @@ -21,170 +11,157 @@ import SidebarMenu from "./Sidebar/SidebarMenu"; const drawerWidth = 300; -const Main = styled(Stack, { shouldForwardProp: (prop) => prop !== "open" })( - ({ theme, open }) => ({ +const Main = styled(Stack, { shouldForwardProp: (prop) => prop !== "open" })(({ theme, open }) => ({ flexGrow: 1, height: "100%", transition: theme.transitions.create("margin", { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.leavingScreen, + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, }), marginLeft: `-${drawerWidth}px`, ...(open && { - transition: theme.transitions.create("margin", { - easing: theme.transitions.easing.easeOut, - duration: theme.transitions.duration.enteringScreen, - }), - marginLeft: 0, + transition: theme.transitions.create("margin", { + easing: theme.transitions.easing.easeOut, + duration: theme.transitions.duration.enteringScreen, + }), + marginLeft: 0, }), - }), -); +})); const AppBar = styled(MuiAppBar, { - shouldForwardProp: (prop) => prop !== "open", + shouldForwardProp: (prop) => prop !== "open", })(({ theme, open }) => ({ - transition: theme.transitions.create(["margin", "width"], { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.leavingScreen, - }), - ...(open && { - width: `calc(100% - ${drawerWidth}px)`, - marginLeft: `${drawerWidth}px`, transition: theme.transitions.create(["margin", "width"], { - easing: theme.transitions.easing.easeOut, - duration: theme.transitions.duration.enteringScreen, + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + ...(open && { + width: `calc(100% - ${drawerWidth}px)`, + marginLeft: `${drawerWidth}px`, + transition: theme.transitions.create(["margin", "width"], { + easing: theme.transitions.easing.easeOut, + duration: theme.transitions.duration.enteringScreen, + }), }), - }), })); const DrawerHeader = styled("div")(({ theme }) => ({ - display: "flex", - alignItems: "center", - padding: theme.spacing(0, 1), - ...theme.mixins.toolbar, - minHeight: "40px !important", - justifyContent: "flex-end", + display: "flex", + alignItems: "center", + padding: theme.spacing(0, 1), + ...theme.mixins.toolbar, + minHeight: "40px !important", + justifyContent: "flex-end", })); const HeaderWithSidebar = ({ children }) => { - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down("md")); // Detect mobile/tablet screen - const [open, setOpen] = useState(!isMobile); // Initial state based on screen size + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("md")); // Detect mobile/tablet screen + const [open, setOpen] = useState(!isMobile); // Initial state based on screen size - useEffect(() => { - setOpen(!isMobile); // Toggle state when screen size changes - }, [isMobile]); + useEffect(() => { + setOpen(!isMobile); // Toggle state when screen size changes + }, [isMobile]); - const now = moment().locale("fa").format("YYYY/MM/DD"); + const now = moment().locale("fa").format("YYYY/MM/DD"); - const handleDrawerOpen = () => { - setOpen(true); - }; - const handleDrawerClose = () => { - setOpen(false); - }; + const handleDrawerOpen = () => { + setOpen(true); + }; + const handleDrawerClose = () => { + setOpen(false); + }; - return ( - - - - - - - - {headerMenu.map((menu) => ( - - ))} - - - - - - - تاریخ امروز: {now} - - - - - - - - v{process.env.NEXT_PUBLIC_VERSION} - - -
- + return ( - {children} + + + + + + + {headerMenu.map((menu) => ( + + ))} + + + + + + + تاریخ امروز: {now} + + + + + + + + v{process.env.NEXT_PUBLIC_VERSION} + + +
+ + + {children} + +
-
-
- ); + ); }; export default HeaderWithSidebar; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/ActionHeader.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/ActionHeader.jsx index 368c7b1..560801d 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/ActionHeader.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/ActionHeader.jsx @@ -1,29 +1,25 @@ import { Stack, Typography } from "@mui/material"; const ActionHeader = ({ tab }) => { - return ( - - - .... عملیات های مربوط به تماس: - - - {tab.phone_number} .... - - - ); + return ( + + + .... عملیات های مربوط به تماس: + + + {tab.phone_number} .... + + + ); }; export default ActionHeader; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionCategoriesButton.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionCategoriesButton.jsx index c21d2dc..734bed4 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionCategoriesButton.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionCategoriesButton.jsx @@ -2,26 +2,24 @@ import { Button, Grid } from "@mui/material"; import { Controller } from "react-hook-form"; const CallActionCategoriesButton = ({ category, control }) => { - return ( - ( - - )} - name={"category_id"} - /> - ); + return ( + ( + + )} + name={"category_id"} + /> + ); }; export default CallActionCategoriesButton; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionDescription.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionDescription.jsx index 6eacebd..c2bc665 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionDescription.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionDescription.jsx @@ -3,42 +3,42 @@ import { useEffect, useRef } from "react"; import { Controller } from "react-hook-form"; const CallActionDescription = ({ control }) => { - const inputRef = useRef(null); + const inputRef = useRef(null); - useEffect(() => { - const timer = setTimeout(() => { - if (inputRef.current) { - inputRef.current.focus(); - } - }, 100); + useEffect(() => { + const timer = setTimeout(() => { + if (inputRef.current) { + inputRef.current.focus(); + } + }, 100); - return () => clearTimeout(timer); - }, []); + return () => clearTimeout(timer); + }, []); - return ( - <> - - - - - ( - - )} - name={"description"} - /> - - - ); + return ( + <> + + + + + ( + + )} + name={"description"} + /> + + + ); }; export default CallActionDescription; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionSubcategoriesButton.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionSubcategoriesButton.jsx index 1783b32..1e68b6d 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionSubcategoriesButton.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionSubcategoriesButton.jsx @@ -3,36 +3,36 @@ import { useCallback } from "react"; import { Controller, useWatch } from "react-hook-form"; const CallActionSubcategoriesButton = ({ sub_category, control, onSubmit }) => { - const category_id = useWatch({ control, name: "category_id" }); + const category_id = useWatch({ control, name: "category_id" }); - const handleClick = useCallback( - (onChange) => { - onChange(sub_category.subcategory_id); - setTimeout(() => { - onSubmit(); - }, 0); - }, - [sub_category.subcategory_id], - ); + const handleClick = useCallback( + (onChange) => { + onChange(sub_category.subcategory_id); + setTimeout(() => { + onSubmit(); + }, 0); + }, + [sub_category.subcategory_id] + ); - return ( - { - return sub_category.category_id === category_id ? ( - - ) : null; - }} - name={"subcategory_id"} - /> - ); + return ( + { + return sub_category.category_id === category_id ? ( + + ) : null; + }} + name={"subcategory_id"} + /> + ); }; export default CallActionSubcategoriesButton; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionsCategories.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionsCategories.jsx index 32cd698..d3278e3 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionsCategories.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionsCategories.jsx @@ -3,22 +3,18 @@ import CallActionCategoriesButton from "./CallActionCategoriesButton"; import { Chip, Divider, Grid, Stack } from "@mui/material"; const CallActionsCategories = ({ control }) => { - const { categoryLists } = useCategory(); - return ( - <> - - - - - {categoryLists.map((category) => ( - - ))} - - - ); + const { categoryLists } = useCategory(); + return ( + <> + + + + + {categoryLists.map((category) => ( + + ))} + + + ); }; export default CallActionsCategories; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionsSubcategories.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionsSubcategories.jsx index f67b385..388b414 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionsSubcategories.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/CallActionsSubcategories.jsx @@ -3,25 +3,25 @@ import CallActionSubcategoriesButton from "./CallActionSubcategoriesButton"; import { Chip, Divider, Grid, Stack } from "@mui/material"; const CallActionsSubcategories = ({ control, onSubmit }) => { - const { subCategoryLists } = useCategory(); - return ( - <> - - - - - {subCategoryLists.map((sub_category, index) => { - return ( - - ); - })} - - - ); + const { subCategoryLists } = useCategory(); + return ( + <> + + + + + {subCategoryLists.map((sub_category, index) => { + return ( + + ); + })} + + + ); }; export default CallActionsSubcategories; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/index.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/index.jsx index 242afdf..ae928d7 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallActions/index.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallActions/index.jsx @@ -12,76 +12,70 @@ import CallActionsCategories from "./CallActionsCategories"; import CallActionsSubcategories from "./CallActionsSubcategories"; const defaultValues = { - description: "", - category_id: "", - subcategory_id: "", + description: "", + category_id: "", + subcategory_id: "", }; const validationSchema = object({ - category_id: string().required("لطفا نام کاربری را وارد کنید!"), - subcategory_id: string().required("لطفا رمز عبور را وارد کنید!"), + category_id: string().required("لطفا نام کاربری را وارد کنید!"), + subcategory_id: string().required("لطفا رمز عبور را وارد کنید!"), }); function CallActions({ tab }) { - const requestServer = useRequest(); - const { closeCall } = useCall(); + const requestServer = useRequest(); + const { closeCall } = useCall(); - const { - control, - handleSubmit, - formState: { isSubmitting }, - } = useForm({ - defaultValues, - resolver: yupResolver(validationSchema), - mode: "all", - }); + const { + control, + handleSubmit, + formState: { isSubmitting }, + } = useForm({ + defaultValues, + resolver: yupResolver(validationSchema), + mode: "all", + }); - const onSubmit = handleSubmit(async (data) => { - try { - const formData = new FormData(); - data.description != "" && - formData.append("description", data.description); - formData.append("category_id", data.category_id); - formData.append("subcategory_id", data.subcategory_id); - await requestServer(`${CALL_ACTION}/${tab.id}`, "post", { - data: formData, - }); - closeCall(tab.id); - } catch (error) {} - }); + const onSubmit = handleSubmit(async (data) => { + try { + const formData = new FormData(); + data.description != "" && formData.append("description", data.description); + formData.append("category_id", data.category_id); + formData.append("subcategory_id", data.subcategory_id); + await requestServer(`${CALL_ACTION}/${tab.id}`, "post", { + data: formData, + }); + closeCall(tab.id); + } catch (error) {} + }); - return ( - - - - - - - {isSubmitting && ( - - - - )} - - - ); + > + + + + + + {isSubmitting && ( + + + + )} + + + ); } export default CallActions; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty.jsx index e76a269..9cabc94 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ErrorOrEmpty.jsx @@ -1,39 +1,39 @@ import { Typography } from "@mui/material"; const ErrorOrEmpty = ({ isErrorOrEmpty }) => { - return ( - <> - {isErrorOrEmpty === "error" ? ( - - خطا در دریافت تاریخچه تماس دریافتی - - ) : isErrorOrEmpty === "empty" ? ( - - تاریخچه ای برای تماس دریافتی یافت نشد - - ) : ( - <> - )} - - ); + return ( + <> + {isErrorOrEmpty === "error" ? ( + + خطا در دریافت تاریخچه تماس دریافتی + + ) : isErrorOrEmpty === "empty" ? ( + + تاریخچه ای برای تماس دریافتی یافت نشد + + ) : ( + <> + )} + + ); }; export default ErrorOrEmpty; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/HistoryHeader.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/HistoryHeader.jsx index e3498d1..39a4a7d 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/HistoryHeader.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/HistoryHeader.jsx @@ -1,25 +1,25 @@ import { Stack, Typography } from "@mui/material"; const HistoryHeader = ({ tab }) => { - return ( - - - .... تاریخچه تماس های: - - - {tab.phone_number} .... - - - ); + return ( + + + .... تاریخچه تماس های: + + + {tab.phone_number} .... + + + ); }; export default HistoryHeader; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData.jsx index 5197ca8..4c93548 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/PreviousOperatorData.jsx @@ -3,28 +3,26 @@ import { Avatar, Box, Stack, Typography } from "@mui/material"; import moment from "jalali-moment"; const PreviousOperatorData = ({ historyItem }) => { - return ( - - - - - - - - - - {historyItem.operator_full_name} - - - (کارشناس) - + return ( + + + + + + + + + {historyItem.operator_full_name} + + (کارشناس) + + + + {moment(historyItem.created_at).locale("fa").fromNow()} + + - - {moment(historyItem.created_at).locale("fa").fromNow()} - - - - ); + ); }; export default PreviousOperatorData; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics..jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics..jsx index 13e7063..f4298a9 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics..jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/Topics..jsx @@ -1,60 +1,46 @@ import { Chip, Divider, Stack } from "@mui/material"; const Topics = ({ historyItem }) => { - return ( - - - - - {historyItem.category_name && ( - - )} - - - - - {historyItem.subcategory_name && ( - - )} - - - - - {historyItem.description && } - - - ); + return ( + + + + + {historyItem.category_name && } + + + + + {historyItem.subcategory_name && } + + + + + {historyItem.description && } + + + ); }; export default Topics; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/index.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/index.jsx index f06ba45..5b61e51 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/index.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/ListItemOfCalls/index.jsx @@ -3,12 +3,12 @@ import PreviousOperatorData from "./PreviousOperatorData"; import Topics from "./Topics."; const ListItemOfCalls = ({ historyItem }) => { - return ( - - - - - ); + return ( + + + + + ); }; export default ListItemOfCalls; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/LoadingHistory.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/LoadingHistory.jsx index 674b7eb..0d49a6b 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/LoadingHistory.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/LoadingHistory.jsx @@ -1,115 +1,108 @@ -import { - Box, - List, - ListItem, - ListItemAvatar, - ListItemText, - Skeleton, -} from "@mui/material"; +import { Box, List, ListItem, ListItemAvatar, ListItemText, Skeleton } from "@mui/material"; const LoadingHistory = () => { - return ( - <> - - - - - - - - - } - secondary={ - - } - /> - - - - - + - - - - - - - - - - - - - - - - - ); + > + + + + + + + + } + secondary={ + + } + /> + + + + + + + + + + + + + + + + + + + + + + ); }; export default LoadingHistory; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/index.jsx b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/index.jsx index 4d47ce3..acfa3df 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/index.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/CallHistory/index.jsx @@ -9,53 +9,52 @@ import { Headphones } from "@mui/icons-material"; const max_size = 10; const CallHistory = ({ tab }) => { - const { - firstItemOfHistory, - historyList, - isLoadingHistoryList, - errorHistoryList, - } = useCallerHistory(tab.id, tab.phone_number, max_size); - const [showRestOfHistory, setShowRestOfHistory] = useState(false); + const { firstItemOfHistory, historyList, isLoadingHistoryList, errorHistoryList } = useCallerHistory( + tab.id, + tab.phone_number, + max_size + ); + const [showRestOfHistory, setShowRestOfHistory] = useState(false); - return ( - - - - {isLoadingHistoryList ? ( - - ) : errorHistoryList ? ( - - ) : !firstItemOfHistory ? ( - - ) : ( - - - {historyList && ( - - } - onClick={() => setShowRestOfHistory(true)} - label={"نمایش موارد بیشتر"} - disabled={showRestOfHistory} - /> - - )} - {showRestOfHistory && - historyList.map((historyItem, index) => ( - <> - - - - ))} - - )} - - - ); + return ( + + + + {isLoadingHistoryList ? ( + + ) : errorHistoryList ? ( + + ) : !firstItemOfHistory ? ( + + ) : ( + + + {historyList && ( + + } + onClick={() => setShowRestOfHistory(true)} + label={"نمایش موارد بیشتر"} + disabled={showRestOfHistory} + /> + + )} + {showRestOfHistory && + historyList.map((historyItem, index) => ( + <> + + + + ))} + + )} + + + ); }; export default CallHistory; diff --git a/src/components/widget/call/CallTabs/CallTabPanel/index.jsx b/src/components/widget/call/CallTabs/CallTabPanel/index.jsx index a22af79..50443bf 100644 --- a/src/components/widget/call/CallTabs/CallTabPanel/index.jsx +++ b/src/components/widget/call/CallTabs/CallTabPanel/index.jsx @@ -3,27 +3,27 @@ import CallActions from "./CallActions"; import CallHistory from "./CallHistory"; const CallTabPanel = ({ tab }) => { - return ( - - - - - - - - - - ); + return ( + + + + + + + + + + ); }; export default CallTabPanel; diff --git a/src/components/widget/call/CallTabs/CallTabsList/CallTabDetails.jsx b/src/components/widget/call/CallTabs/CallTabsList/CallTabDetails.jsx index a7c0290..f095d4c 100644 --- a/src/components/widget/call/CallTabs/CallTabsList/CallTabDetails.jsx +++ b/src/components/widget/call/CallTabs/CallTabsList/CallTabDetails.jsx @@ -3,19 +3,14 @@ import { Stack, Typography } from "@mui/material"; import CallTabTime from "./CallTabTime"; const CallTabDetails = ({ tab }) => { - return ( - - - - {tab.phone_number} - - - - ); + return ( + + + + {tab.phone_number} + + + + ); }; export default CallTabDetails; diff --git a/src/components/widget/call/CallTabs/CallTabsList/CallTabLabel.jsx b/src/components/widget/call/CallTabs/CallTabsList/CallTabLabel.jsx index 3b45b80..97ae268 100644 --- a/src/components/widget/call/CallTabs/CallTabsList/CallTabLabel.jsx +++ b/src/components/widget/call/CallTabs/CallTabsList/CallTabLabel.jsx @@ -4,32 +4,31 @@ import { IconButton, Stack, Zoom } from "@mui/material"; import CallTabDetails from "./CallTabDetails"; const CallTabLabel = ({ tab, index }) => { - const { closeCall, activeCall } = useCall(); - const handleCloseClick = (id) => { - closeCall(id); - }; + const { closeCall, activeCall } = useCall(); + const handleCloseClick = (id) => { + closeCall(id); + }; - return ( - - - - handleCloseClick(tab.id)}> - - - - - ); + return ( + + + + handleCloseClick(tab.id)}> + + + + + ); }; export default CallTabLabel; diff --git a/src/components/widget/call/CallTabs/CallTabsList/CallTabTime.jsx b/src/components/widget/call/CallTabs/CallTabsList/CallTabTime.jsx index a2ce2b3..4cefa31 100644 --- a/src/components/widget/call/CallTabs/CallTabsList/CallTabTime.jsx +++ b/src/components/widget/call/CallTabs/CallTabsList/CallTabTime.jsx @@ -3,26 +3,26 @@ import moment from "jalali-moment"; import { useEffect, useState } from "react"; const CallTabTime = ({ realTimeDate }) => { - const [date, setDate] = useState("..."); - const changeTabTime = (tabTime) => { - moment.relativeTimeThreshold("ss", 1); - return moment(tabTime).locale("fa").fromNow(); - }; - - useEffect(() => { - const timer = setInterval(() => { - setDate(changeTabTime(realTimeDate)); - }, 1000); - - return () => { - clearInterval(timer); + const [date, setDate] = useState("..."); + const changeTabTime = (tabTime) => { + moment.relativeTimeThreshold("ss", 1); + return moment(tabTime).locale("fa").fromNow(); }; - }, [realTimeDate]); - return ( - - {date} - - ); + useEffect(() => { + const timer = setInterval(() => { + setDate(changeTabTime(realTimeDate)); + }, 1000); + + return () => { + clearInterval(timer); + }; + }, [realTimeDate]); + + return ( + + {date} + + ); }; export default CallTabTime; diff --git a/src/components/widget/call/CallTabs/CallTabsList/index.jsx b/src/components/widget/call/CallTabs/CallTabsList/index.jsx index 67e02d9..64bf038 100644 --- a/src/components/widget/call/CallTabs/CallTabsList/index.jsx +++ b/src/components/widget/call/CallTabs/CallTabsList/index.jsx @@ -3,38 +3,38 @@ import { Box, Tab, Tabs } from "@mui/material"; import CallTabLabel from "./CallTabLabel"; const CallTabsList = () => { - const { calls, changeActiveTabCall, activeCall } = useCall(); - const handleChange = (event, newValue) => { - changeActiveTabCall(newValue); - }; + const { calls, changeActiveTabCall, activeCall } = useCall(); + const handleChange = (event, newValue) => { + changeActiveTabCall(newValue); + }; - return ( - - - {calls.map((call, index) => ( - } - key={call.id} - /> - ))} - - - ); + return ( + + + {calls.map((call, index) => ( + } + key={call.id} + /> + ))} + + + ); }; export default CallTabsList; diff --git a/src/components/widget/call/CallTabs/index.jsx b/src/components/widget/call/CallTabs/index.jsx index 58bb4e7..eb92d0a 100644 --- a/src/components/widget/call/CallTabs/index.jsx +++ b/src/components/widget/call/CallTabs/index.jsx @@ -3,15 +3,15 @@ import CallTabPanel from "./CallTabPanel"; import CallTabsList from "./CallTabsList"; const CallTabs = () => { - const { calls } = useCall(); + const { calls } = useCall(); - return ( - <> - - {calls.map((call) => ( - - ))} - - ); + return ( + <> + + {calls.map((call) => ( + + ))} + + ); }; export default CallTabs; diff --git a/src/components/widget/call/CallWidgetDialog.jsx b/src/components/widget/call/CallWidgetDialog.jsx index ea29f13..b08970e 100644 --- a/src/components/widget/call/CallWidgetDialog.jsx +++ b/src/components/widget/call/CallWidgetDialog.jsx @@ -7,42 +7,38 @@ import { useEffect } from "react"; import CallTabs from "./CallTabs"; const CallWidgetDialog = () => { - const { openCallDialog, setOpenCallDialog, calls, newCall } = useCall(); - const { socket } = useSocket(); + const { openCallDialog, setOpenCallDialog, calls, newCall } = useCall(); + const { socket } = useSocket(); - useEffect(() => { - const call = (_data, act) => { - const data = JSON.parse(_data); - newCall({ - id: data.call_id, - phone_number: data.phone_number, - }); - act(); - }; - socket.on("call", call); + useEffect(() => { + const call = (_data, act) => { + const data = JSON.parse(_data); + newCall({ + id: data.call_id, + phone_number: data.phone_number, + }); + act(); + }; + socket.on("call", call); - return () => { - socket.off("call", call); - }; - }); + return () => { + socket.off("call", call); + }; + }); - useEffect(() => { - if (calls.length === 0) { - setOpenCallDialog(false); - return; - } - setOpenCallDialog(true); - }, [calls.length]); + useEffect(() => { + if (calls.length === 0) { + setOpenCallDialog(false); + return; + } + setOpenCallDialog(true); + }, [calls.length]); - return ( - - - - ); + return ( + + + + ); }; export default CallWidgetDialog; diff --git a/src/components/widget/call/index.jsx b/src/components/widget/call/index.jsx index cc3a565..5f67ea0 100644 --- a/src/components/widget/call/index.jsx +++ b/src/components/widget/call/index.jsx @@ -4,12 +4,12 @@ import { CategoriesProvider } from "@/lib/contexts/category"; import CallWidgetDialog from "./CallWidgetDialog"; const CallWidget = () => { - return ( - - - - - - ); + return ( + + + + + + ); }; export default CallWidget; diff --git a/src/core/components/CustomDatePicker.jsx b/src/core/components/CustomDatePicker.jsx index 27aa544..eb68fa7 100644 --- a/src/core/components/CustomDatePicker.jsx +++ b/src/core/components/CustomDatePicker.jsx @@ -5,56 +5,49 @@ import { LocalizationProvider, MobileDatePicker } from "@mui/x-date-pickers"; import { IconButton, InputAdornment } from "@mui/material"; import ClearIcon from "@mui/icons-material/Clear"; -const CustomDatePicker = ({ - dateValue, - setDateValue, - placeholder = "انتخاب تاریخ", - size = "small", -}) => { - const handleDateChange = (newValue) => { - setDateValue(newValue); - }; +const CustomDatePicker = ({ dateValue, setDateValue, placeholder = "انتخاب تاریخ", size = "small" }) => { + const handleDateChange = (newValue) => { + setDateValue(newValue); + }; - return ( - - - { - event.stopPropagation(); - setDateValue(null); - }} - sx={{ - color: "#bfbfbf", - "&:hover": { - backgroundColor: "rgba(189, 189, 189, 0.1)", - color: "#363434", - }, - }} - > - - - - ), - }, - }, - }} - > - - ); + return ( + + + { + event.stopPropagation(); + setDateValue(null); + }} + sx={{ + color: "#bfbfbf", + "&:hover": { + backgroundColor: "rgba(189, 189, 189, 0.1)", + color: "#363434", + }, + }} + > + + + + ), + }, + }, + }} + > + + ); }; export default CustomDatePicker; diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index 64c8d6a..ef2d81a 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -11,189 +11,169 @@ import { FA_DATATABLE_LOCALIZATION } from "./localization/fa/datatable"; import DataTable_Paper from "./table/Paper"; const rowSelectionReducer = (state, action) => { - switch (action.type) { - case "TOGGLE_ROW": - return { [action.payload]: true }; - case "RESET": - return {}; - default: - return state; - } + switch (action.type) { + case "TOGGLE_ROW": + return { [action.payload]: true }; + case "RESET": + return {}; + default: + return state; + } }; const DataTable_Main = (props) => { - const request = useRequest(); - const [rowSelection, dispatchRowSelection] = useReducer( - rowSelectionReducer, - {}, - ); - const { filterData, sortData, setSortData, hideData } = useDataTable(); - const { - need_filter, - table_url, - user_id, - page_name, - table_name, - columns, - initialStateProps, - TableToolbar, - table_title, - RowActions, - specific_data, - specialFilter, - } = props; - const flatColumns = flattenArrayOfObjects(columns, "columns"); - const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); - const [totalRowCount, setTotalRowCount] = useState(0); - const flattenHideData = flattenObjectOfObjects(hideData); - const onSortingChange = (event) => { - setSortData(event); - }; + const request = useRequest(); + const [rowSelection, dispatchRowSelection] = useReducer(rowSelectionReducer, {}); + const { filterData, sortData, setSortData, hideData } = useDataTable(); + const { + need_filter, + table_url, + user_id, + page_name, + table_name, + columns, + initialStateProps, + TableToolbar, + table_title, + RowActions, + specific_data, + specialFilter, + } = props; + const flatColumns = flattenArrayOfObjects(columns, "columns"); + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); + const [totalRowCount, setTotalRowCount] = useState(0); + const flattenHideData = flattenObjectOfObjects(hideData); + const onSortingChange = (event) => { + setSortData(event); + }; - const fetchUrl = useCallback(() => { - const params = new URLSearchParams(); - params.set("start", `${pagination.pageIndex * pagination.pageSize}`); - params.set("size", pagination.pageSize); - if (specialFilter) { - const filteredSpecialFilterData = Object.values(specialFilter).filter( - (filter) => !isArrayEmpty(filter.value), - ); - params.set("filters", JSON.stringify(filteredSpecialFilterData || [])); - } else { - const filteredFilterData = DataTableFilterDataStructure( - filterData, - isArrayEmpty, - ); - params.set( - "filters", - JSON.stringify( - filteredFilterData.length === 0 ? [] : filteredFilterData, + const fetchUrl = useCallback(() => { + const params = new URLSearchParams(); + params.set("start", `${pagination.pageIndex * pagination.pageSize}`); + params.set("size", pagination.pageSize); + if (specialFilter) { + const filteredSpecialFilterData = Object.values(specialFilter).filter( + (filter) => !isArrayEmpty(filter.value) + ); + params.set("filters", JSON.stringify(filteredSpecialFilterData || [])); + } else { + const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty); + params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData)); + } + params.set( + "sorting", + JSON.stringify( + Object.values(sortData).map(({ id, ...rest }) => ({ + ...rest, + id: id.replace(/__/g, "."), + })) + ) + ); + return `${table_url}?${params}`; + }, [table_url, filterData, pagination, sortData, specialFilter]); + + const fetcher = async (url) => { + try { + const response = await request(url); + setTotalRowCount(response.data?.meta?.totalRowCount); + if (specific_data) { + return specific_data(response.data); + } else { + return response.data?.data; + } + } catch (error) { + throw error; + } + }; + + const { data, isValidating, mutate } = useSWR(props.data ? "" : fetchUrl(), fetcher, { + revalidateIfStale: true, + revalidateOnFocus: false, + revalidateOnReconnect: true, + keepPreviousData: true, + }); + + useEffect(() => { + if (!isValidating) return; + dispatchRowSelection({ type: "RESET" }); + }, [isValidating]); + + const table = useMaterialReactTable({ + localization: FA_DATATABLE_LOCALIZATION, + columns, + data: data ?? [], + muiTableBodyRowProps: ({ row }) => ({ + onClick: () => dispatchRowSelection({ type: "TOGGLE_ROW", payload: row.id }), + selected: !!rowSelection[row.id], + }), + initialState: { + density: "compact", + columnVisibility: flattenHideData, + sorting: sortData, + ...initialStateProps, + }, + state: { + showProgressBars: isValidating || props.loading, + columnVisibility: flattenHideData, + sorting: sortData, + pagination, + rowSelection, + }, + muiTableHeadProps: { + sx: { + borderTop: "1px solid #e1e1e1", + borderBottom: "2px solid #e1e1e1", + }, + }, + muiTableHeadCellProps: { + sx: { + color: "primary.main", + borderLeft: "1px solid #e1e1e1", + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + muiTableBodyCellProps: { + sx: { + borderLeft: "1px solid #e1e1e1", + "&:first-of-type": { + borderLeft: "unset", + }, + }, + }, + manualFiltering: true, + manualPagination: true, + manualSorting: true, + onPaginationChange: setPagination, + onSortingChange: onSortingChange, + rowCount: totalRowCount, + renderTopToolbarCustomActions: ({ table }) => ( + <> + {TableToolbar && ( + + )} + ), - ); - } - params.set( - "sorting", - JSON.stringify( - Object.values(sortData).map(({ id, ...rest }) => ({ - ...rest, - id: id.replace(/__/g, "."), - })), - ), - ); - return `${table_url}?${params}`; - }, [table_url, filterData, pagination, sortData, specialFilter]); + renderRowActions: ({ row }) => , + ...props, + }); - const fetcher = async (url) => { - try { - const response = await request(url); - setTotalRowCount(response.data?.meta?.totalRowCount); - if (specific_data) { - return specific_data(response.data); - } else { - return response.data?.data; - } - } catch (error) { - throw error; - } - }; - - const { data, isValidating, mutate } = useSWR( - props.data ? "" : fetchUrl(), - fetcher, - { - revalidateIfStale: true, - revalidateOnFocus: false, - revalidateOnReconnect: true, - keepPreviousData: true, - }, - ); - - useEffect(() => { - if (!isValidating) return; - dispatchRowSelection({ type: "RESET" }); - }, [isValidating]); - - const table = useMaterialReactTable({ - localization: FA_DATATABLE_LOCALIZATION, - columns, - data: data ?? [], - muiTableBodyRowProps: ({ row }) => ({ - onClick: () => - dispatchRowSelection({ type: "TOGGLE_ROW", payload: row.id }), - selected: !!rowSelection[row.id], - }), - initialState: { - density: "compact", - columnVisibility: flattenHideData, - sorting: sortData, - ...initialStateProps, - }, - state: { - showProgressBars: isValidating || props.loading, - columnVisibility: flattenHideData, - sorting: sortData, - pagination, - rowSelection, - }, - muiTableHeadProps: { - sx: { - borderTop: "1px solid #e1e1e1", - borderBottom: "2px solid #e1e1e1", - }, - }, - muiTableHeadCellProps: { - sx: { - color: "primary.main", - borderLeft: "1px solid #e1e1e1", - "&:first-of-type": { - borderLeft: "unset", - }, - }, - }, - muiTableBodyCellProps: { - sx: { - borderLeft: "1px solid #e1e1e1", - "&:first-of-type": { - borderLeft: "unset", - }, - }, - }, - manualFiltering: true, - manualPagination: true, - manualSorting: true, - onPaginationChange: setPagination, - onSortingChange: onSortingChange, - rowCount: totalRowCount, - renderTopToolbarCustomActions: ({ table }) => ( - <> - {TableToolbar && ( - - )} - - ), - renderRowActions: ({ row }) => , - ...props, - }); - - return ( - - ); + table_url={table_url} + columns={flatColumns} + user_id={user_id} + page_name={page_name} + table_name={table_name} + special_data={props.data} + special_filter={specialFilter} + setFilterData={props.setFilterData} + /> + ); }; export default DataTable_Main; diff --git a/src/core/components/DataTable/body/TableBody.js b/src/core/components/DataTable/body/TableBody.js index c427974..b0750be 100644 --- a/src/core/components/DataTable/body/TableBody.js +++ b/src/core/components/DataTable/body/TableBody.js @@ -2,200 +2,190 @@ import { parseFromValuesOrFunc } from "@/core/utils/utils"; import { TableBody, Typography } from "@mui/material"; import { useMRT_RowVirtualizer, useMRT_Rows } from "material-react-table"; import { memo, useMemo } from "react"; -import DataTable_TableBodyRow, { - Memo_DataTable_TableBodyRow, -} from "./TableBodyRow"; +import DataTable_TableBodyRow, { Memo_DataTable_TableBodyRow } from "./TableBodyRow"; const DataTable_TableBody = ({ columnVirtualizer, table, ...rest }) => { - const { - getBottomRows, - getIsSomeRowsPinned, - getRowModel, - getState, - getTopRows, - options: { - enableStickyFooter, - enableStickyHeader, - layoutMode, - localization, - memoMode, - muiTableBodyProps, - renderDetailPanel, - renderEmptyRowsFallback, - rowPinningDisplayMode, - }, - refs: { tableFooterRef, tableHeadRef, tablePaperRef }, - } = table; - const { columnFilters, globalFilter, isFullScreen, rowPinning } = getState(); + const { + getBottomRows, + getIsSomeRowsPinned, + getRowModel, + getState, + getTopRows, + options: { + enableStickyFooter, + enableStickyHeader, + layoutMode, + localization, + memoMode, + muiTableBodyProps, + renderDetailPanel, + renderEmptyRowsFallback, + rowPinningDisplayMode, + }, + refs: { tableFooterRef, tableHeadRef, tablePaperRef }, + } = table; + const { columnFilters, globalFilter, isFullScreen, rowPinning } = getState(); - const tableBodyProps = { - ...parseFromValuesOrFunc(muiTableBodyProps, { table }), - ...rest, - }; + const tableBodyProps = { + ...parseFromValuesOrFunc(muiTableBodyProps, { table }), + ...rest, + }; - const tableHeadHeight = - ((enableStickyHeader || isFullScreen) && - tableHeadRef.current?.clientHeight) || - 0; - const tableFooterHeight = - (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0; + const tableHeadHeight = ((enableStickyHeader || isFullScreen) && tableHeadRef.current?.clientHeight) || 0; + const tableFooterHeight = (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0; - const pinnedRowIds = useMemo(() => { - if (!rowPinning.bottom?.length && !rowPinning.top?.length) return []; - return getRowModel() - .rows.filter((row) => row.getIsPinned()) - .map((r) => r.id); - }, [rowPinning, getRowModel().rows]); + const pinnedRowIds = useMemo(() => { + if (!rowPinning.bottom?.length && !rowPinning.top?.length) return []; + return getRowModel() + .rows.filter((row) => row.getIsPinned()) + .map((r) => r.id); + }, [rowPinning, getRowModel().rows]); - const rows = useMRT_Rows(table); + const rows = useMRT_Rows(table); - const rowVirtualizer = useMRT_RowVirtualizer(table, rows); + const rowVirtualizer = useMRT_RowVirtualizer(table, rows); - const { virtualRows } = rowVirtualizer ?? {}; + const { virtualRows } = rowVirtualizer ?? {}; - const commonRowProps = { - columnVirtualizer, - numRows: rows.length, - table, - }; + const commonRowProps = { + columnVirtualizer, + numRows: rows.length, + table, + }; - return ( - <> - {!rowPinningDisplayMode?.includes("sticky") && - getIsSomeRowsPinned("top") && ( - ({ - display: layoutMode?.startsWith("grid") ? "grid" : undefined, - position: "sticky", - top: tableHeadHeight - 1, - zIndex: 1, - ...parseFromValuesOrFunc(tableBodyProps?.sx, theme), - })} - > - {getTopRows().map((row, staticRowIndex) => { - const props = { - ...commonRowProps, - row, - staticRowIndex, - }; - return memoMode === "rows" ? ( - - ) : ( - - ); - })} - - )} - ({ - display: layoutMode?.startsWith("grid") ? "grid" : undefined, - height: rowVirtualizer - ? `${rowVirtualizer.getTotalSize()}px` - : undefined, - minHeight: !rows.length ? "100px" : undefined, - position: "relative", - ...parseFromValuesOrFunc(tableBodyProps?.sx, theme), - })} - > - {tableBodyProps?.children ?? - (!rows.length ? ( - + {!rowPinningDisplayMode?.includes("sticky") && getIsSomeRowsPinned("top") && ( + ({ + display: layoutMode?.startsWith("grid") ? "grid" : undefined, + position: "sticky", + top: tableHeadHeight - 1, + zIndex: 1, + ...parseFromValuesOrFunc(tableBodyProps?.sx, theme), + })} + > + {getTopRows().map((row, staticRowIndex) => { + const props = { + ...commonRowProps, + row, + staticRowIndex, + }; + return memoMode === "rows" ? ( + + ) : ( + + ); + })} + + )} + ({ + display: layoutMode?.startsWith("grid") ? "grid" : undefined, + height: rowVirtualizer ? `${rowVirtualizer.getTotalSize()}px` : undefined, + minHeight: !rows.length ? "100px" : undefined, + position: "relative", + ...parseFromValuesOrFunc(tableBodyProps?.sx, theme), + })} > - - {renderEmptyRowsFallback?.({ table }) ?? ( - - {globalFilter || columnFilters.length - ? localization.noResultsFound - : localization.noRecordsToDisplay} - - )} - - - ) : ( - <> - {(virtualRows ?? rows).map((rowOrVirtualRow, staticRowIndex) => { - let row = rowOrVirtualRow; - if (rowVirtualizer) { - if (renderDetailPanel) { - if (rowOrVirtualRow.index % 2 === 1) { - return null; - } else { - staticRowIndex = rowOrVirtualRow.index / 2; - } - } else { - staticRowIndex = rowOrVirtualRow.index; - } - row = rows[staticRowIndex]; - } - const props = { - ...commonRowProps, - pinnedRowIds, - row, - rowVirtualizer, - staticRowIndex, - virtualRow: rowVirtualizer ? rowOrVirtualRow : undefined, - }; - const key = `${row.id}-${row.index}`; - return memoMode === "rows" ? ( - - ) : ( - - ); - })} - - ))} - - {!rowPinningDisplayMode?.includes("sticky") && - getIsSomeRowsPinned("bottom") && ( - ({ - bottom: tableFooterHeight - 1, - display: layoutMode?.startsWith("grid") ? "grid" : undefined, - position: "sticky", - zIndex: 1, - ...parseFromValuesOrFunc(tableBodyProps?.sx, theme), - })} - > - {getBottomRows().map((row, staticRowIndex) => { - const props = { - ...commonRowProps, - row, - staticRowIndex, - }; - return memoMode === "rows" ? ( - - ) : ( - - ); - })} - - )} - - ); + {tableBodyProps?.children ?? + (!rows.length ? ( + + + {renderEmptyRowsFallback?.({ table }) ?? ( + + {globalFilter || columnFilters.length + ? localization.noResultsFound + : localization.noRecordsToDisplay} + + )} + + + ) : ( + <> + {(virtualRows ?? rows).map((rowOrVirtualRow, staticRowIndex) => { + let row = rowOrVirtualRow; + if (rowVirtualizer) { + if (renderDetailPanel) { + if (rowOrVirtualRow.index % 2 === 1) { + return null; + } else { + staticRowIndex = rowOrVirtualRow.index / 2; + } + } else { + staticRowIndex = rowOrVirtualRow.index; + } + row = rows[staticRowIndex]; + } + const props = { + ...commonRowProps, + pinnedRowIds, + row, + rowVirtualizer, + staticRowIndex, + virtualRow: rowVirtualizer ? rowOrVirtualRow : undefined, + }; + const key = `${row.id}-${row.index}`; + return memoMode === "rows" ? ( + + ) : ( + + ); + })} + + ))} + + {!rowPinningDisplayMode?.includes("sticky") && getIsSomeRowsPinned("bottom") && ( + ({ + bottom: tableFooterHeight - 1, + display: layoutMode?.startsWith("grid") ? "grid" : undefined, + position: "sticky", + zIndex: 1, + ...parseFromValuesOrFunc(tableBodyProps?.sx, theme), + })} + > + {getBottomRows().map((row, staticRowIndex) => { + const props = { + ...commonRowProps, + row, + staticRowIndex, + }; + return memoMode === "rows" ? ( + + ) : ( + + ); + })} + + )} + + ); }; export default DataTable_TableBody; export const Memo_DataTable_TableBody = memo( - DataTable_TableBody, - (prev, next) => prev.table.options.data === next.table.options.data, + DataTable_TableBody, + (prev, next) => prev.table.options.data === next.table.options.data ); diff --git a/src/core/components/DataTable/body/TableBodyCell.js b/src/core/components/DataTable/body/TableBodyCell.js index fd36420..292f39e 100644 --- a/src/core/components/DataTable/body/TableBodyCell.js +++ b/src/core/components/DataTable/body/TableBodyCell.js @@ -1,7 +1,4 @@ -import { - getCommonMRTCellStyles, - parseFromValuesOrFunc, -} from "@/core/utils/utils"; +import { getCommonMRTCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils"; import { useTheme } from "@emotion/react"; import { Skeleton, TableCell } from "@mui/material"; import { isCellEditable, openEditingCell } from "material-react-table"; @@ -9,300 +6,250 @@ import { memo, useEffect, useMemo, useState } from "react"; import DataTable_CopyButton from "../buttons/CopyButton"; import DataTable_TableBodyCellValue from "./TableBodyCellValue"; -const DataTable_TableBodyCell = ({ - cell, - numRows, - rowRef, - staticColumnIndex, - staticRowIndex, - table, - ...rest -}) => { - const theme = useTheme(); - const { - getState, - options: { - columnResizeDirection, - columnResizeMode, - createDisplayMode, - editDisplayMode, - enableCellActions, - enableClickToCopy, - enableColumnOrdering, - enableColumnPinning, - enableGrouping, - layoutMode, - mrtTheme: { draggingBorderColor, baseBackgroundColor }, - muiSkeletonProps, - muiTableBodyCellProps, - }, - setHoveredColumn, - } = table; - const { - actionCell, - columnSizingInfo, - creatingRow, - density, - draggingColumn, - draggingRow, - editingCell, - editingRow, - hoveredColumn, - hoveredRow, - isLoading, - showSkeletons, - } = getState(); - const { column, row } = cell; - const { columnDef } = column; - const { columnDefType } = columnDef; - - const args = { cell, column, row, table }; - const tableCellProps = { - ...parseFromValuesOrFunc(muiTableBodyCellProps, args), - ...parseFromValuesOrFunc(columnDef.muiTableBodyCellProps, args), - ...rest, - }; - - const skeletonProps = parseFromValuesOrFunc(muiSkeletonProps, { - cell, - column, - row, - table, - }); - - const [skeletonWidth, setSkeletonWidth] = useState(100); - useEffect(() => { - if ((!isLoading && !showSkeletons) || skeletonWidth !== 100) return; - const size = column.getSize(); - setSkeletonWidth( - columnDefType === "display" - ? size / 2 - : Math.round(Math.random() * (size - size / 3) + size / 3), - ); - }, [isLoading, showSkeletons]); - - const draggingBorders = useMemo(() => { - const isDraggingColumn = draggingColumn?.id === column.id; - const isHoveredColumn = hoveredColumn?.id === column.id; - const isDraggingRow = draggingRow?.id === row.id; - const isHoveredRow = hoveredRow?.id === row.id; - const isFirstColumn = column.getIsFirstColumn(); - const isLastColumn = column.getIsLastColumn(); - const isLastRow = numRows && staticRowIndex === numRows - 1; - const isResizingColumn = columnSizingInfo.isResizingColumn === column.id; - const showResizeBorder = - isResizingColumn && columnResizeMode === "onChange"; - - const borderStyle = showResizeBorder - ? `2px solid ${draggingBorderColor} !important` - : isDraggingColumn || isDraggingRow - ? `1px dashed ${theme.palette.grey[500]} !important` - : isHoveredColumn || isHoveredRow || isResizingColumn - ? `2px dashed ${draggingBorderColor} !important` - : undefined; - - if (showResizeBorder) { - return columnResizeDirection === "ltr" - ? { borderRight: borderStyle } - : { borderLeft: borderStyle }; - } - - return borderStyle - ? { - borderBottom: - isDraggingRow || isHoveredRow || (isLastRow && !isResizingColumn) - ? borderStyle - : undefined, - borderLeft: - isDraggingColumn || - isHoveredColumn || - ((isDraggingRow || isHoveredRow) && isFirstColumn) - ? borderStyle - : undefined, - borderRight: - isDraggingColumn || - isHoveredColumn || - ((isDraggingRow || isHoveredRow) && isLastColumn) - ? borderStyle - : undefined, - borderTop: isDraggingRow || isHoveredRow ? borderStyle : undefined, - } - : undefined; - }, [ - columnSizingInfo.isResizingColumn, - draggingColumn, - draggingRow, - hoveredColumn, - hoveredRow, - staticRowIndex, - ]); - - const isColumnPinned = - enableColumnPinning && - columnDef.columnDefType !== "group" && - column.getIsPinned(); - - const isEditable = isCellEditable({ cell, table }); - - const isEditing = - isEditable && - !["custom", "modal"].includes(editDisplayMode) && - (editDisplayMode === "table" || - editingRow?.id === row.id || - editingCell?.id === cell.id) && - !row.getIsGrouped(); - - const isCreating = - isEditable && createDisplayMode === "row" && creatingRow?.id === row.id; - - const showClickToCopyButton = - (parseFromValuesOrFunc(enableClickToCopy, cell) === true || - parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === true) && - !["context-menu", false].includes( - // @ts-ignore - parseFromValuesOrFunc(columnDef.enableClickToCopy, cell), - ); - - const isRightClickable = parseFromValuesOrFunc(enableCellActions, cell); - - const cellValueProps = { - cell, - table, - }; - - const handleDoubleClick = (event) => { - tableCellProps?.onDoubleClick?.(event); - openEditingCell({ cell, table }); - }; - - const handleDragEnter = (e) => { - tableCellProps?.onDragEnter?.(e); - if (enableGrouping && hoveredColumn?.id === "drop-zone") { - setHoveredColumn(null); - } - if (enableColumnOrdering && draggingColumn) { - setHoveredColumn( - columnDef.enableColumnOrdering !== false ? column : null, - ); - } - }; - - const handleDragOver = (e) => { - if (columnDef.enableColumnOrdering !== false) { - e.preventDefault(); - } - }; - - const handleContextMenu = (e) => { - tableCellProps?.onContextMenu?.(e); - if (isRightClickable) { - e.preventDefault(); - table.setActionCell(cell); - table.refs.actionCellRef.current = e.currentTarget; - } - }; - - return ( - ({ - "&:hover": { - outline: - actionCell?.id === cell.id || - (editDisplayMode === "cell" && isEditable) || - (editDisplayMode === "table" && (isCreating || isEditing)) - ? `1px solid ${theme.palette.grey[500]}` - : undefined, - textOverflow: "clip", +const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, staticRowIndex, table, ...rest }) => { + const theme = useTheme(); + const { + getState, + options: { + columnResizeDirection, + columnResizeMode, + createDisplayMode, + editDisplayMode, + enableCellActions, + enableClickToCopy, + enableColumnOrdering, + enableColumnPinning, + enableGrouping, + layoutMode, + mrtTheme: { draggingBorderColor, baseBackgroundColor }, + muiSkeletonProps, + muiTableBodyCellProps, }, - alignItems: layoutMode?.startsWith("grid") ? "center" : undefined, - cursor: isRightClickable - ? "context-menu" - : isEditable && editDisplayMode === "cell" - ? "pointer" - : "inherit", - outline: - actionCell?.id === cell.id - ? `1px solid ${theme.palette.grey[500]}` - : undefined, - outlineOffset: "-1px", - overflow: "hidden", - p: - density === "compact" - ? columnDefType === "display" - ? "0 0.5rem" - : "0.5rem" - : density === "comfortable" - ? columnDefType === "display" - ? "0.5rem 0.75rem" - : "1rem" - : columnDefType === "display" - ? "1rem 1.25rem" - : "1.5rem", + setHoveredColumn, + } = table; + const { + actionCell, + columnSizingInfo, + creatingRow, + density, + draggingColumn, + draggingRow, + editingCell, + editingRow, + hoveredColumn, + hoveredRow, + isLoading, + showSkeletons, + } = getState(); + const { column, row } = cell; + const { columnDef } = column; + const { columnDefType } = columnDef; - textOverflow: columnDefType !== "display" ? "ellipsis" : undefined, - whiteSpace: - row.getIsPinned() || density === "compact" ? "nowrap" : "normal", - ...getCommonMRTCellStyles({ - column, - table, - tableCellProps, - theme, - }), - ...draggingBorders, - backgroundColor: baseBackgroundColor, - })} - > - {tableCellProps.children ?? ( - <> - {cell.getIsPlaceholder() ? ( - (columnDef.PlaceholderCell?.({ cell, column, row, table }) ?? null) - ) : showSkeletons !== false && (isLoading || showSkeletons) ? ( - - ) : columnDefType === "display" && - (["mrt-row-expand", "mrt-row-numbers", "mrt-row-select"].includes( - column.id, - ) || - !row.getIsGrouped()) ? ( - columnDef.Cell?.({ - cell, - column, - renderedCellValue: cell.renderValue(), - row, - rowRef, - staticColumnIndex, - staticRowIndex, - table, - }) - ) : showClickToCopyButton && columnDef.enableClickToCopy !== false ? ( - - - - ) : ( - - )} - {cell.getIsGrouped() && !columnDef.GroupedCell && ( - <> ({row.subRows?.length}) - )} - - )} - - ); + const args = { cell, column, row, table }; + const tableCellProps = { + ...parseFromValuesOrFunc(muiTableBodyCellProps, args), + ...parseFromValuesOrFunc(columnDef.muiTableBodyCellProps, args), + ...rest, + }; + + const skeletonProps = parseFromValuesOrFunc(muiSkeletonProps, { + cell, + column, + row, + table, + }); + + const [skeletonWidth, setSkeletonWidth] = useState(100); + useEffect(() => { + if ((!isLoading && !showSkeletons) || skeletonWidth !== 100) return; + const size = column.getSize(); + setSkeletonWidth( + columnDefType === "display" ? size / 2 : Math.round(Math.random() * (size - size / 3) + size / 3) + ); + }, [isLoading, showSkeletons]); + + const draggingBorders = useMemo(() => { + const isDraggingColumn = draggingColumn?.id === column.id; + const isHoveredColumn = hoveredColumn?.id === column.id; + const isDraggingRow = draggingRow?.id === row.id; + const isHoveredRow = hoveredRow?.id === row.id; + const isFirstColumn = column.getIsFirstColumn(); + const isLastColumn = column.getIsLastColumn(); + const isLastRow = numRows && staticRowIndex === numRows - 1; + const isResizingColumn = columnSizingInfo.isResizingColumn === column.id; + const showResizeBorder = isResizingColumn && columnResizeMode === "onChange"; + + const borderStyle = showResizeBorder + ? `2px solid ${draggingBorderColor} !important` + : isDraggingColumn || isDraggingRow + ? `1px dashed ${theme.palette.grey[500]} !important` + : isHoveredColumn || isHoveredRow || isResizingColumn + ? `2px dashed ${draggingBorderColor} !important` + : undefined; + + if (showResizeBorder) { + return columnResizeDirection === "ltr" ? { borderRight: borderStyle } : { borderLeft: borderStyle }; + } + + return borderStyle + ? { + borderBottom: + isDraggingRow || isHoveredRow || (isLastRow && !isResizingColumn) ? borderStyle : undefined, + borderLeft: + isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isFirstColumn) + ? borderStyle + : undefined, + borderRight: + isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isLastColumn) + ? borderStyle + : undefined, + borderTop: isDraggingRow || isHoveredRow ? borderStyle : undefined, + } + : undefined; + }, [columnSizingInfo.isResizingColumn, draggingColumn, draggingRow, hoveredColumn, hoveredRow, staticRowIndex]); + + const isColumnPinned = enableColumnPinning && columnDef.columnDefType !== "group" && column.getIsPinned(); + + const isEditable = isCellEditable({ cell, table }); + + const isEditing = + isEditable && + !["custom", "modal"].includes(editDisplayMode) && + (editDisplayMode === "table" || editingRow?.id === row.id || editingCell?.id === cell.id) && + !row.getIsGrouped(); + + const isCreating = isEditable && createDisplayMode === "row" && creatingRow?.id === row.id; + + const showClickToCopyButton = + (parseFromValuesOrFunc(enableClickToCopy, cell) === true || + parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === true) && + !["context-menu", false].includes( + // @ts-ignore + parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) + ); + + const isRightClickable = parseFromValuesOrFunc(enableCellActions, cell); + + const cellValueProps = { + cell, + table, + }; + + const handleDoubleClick = (event) => { + tableCellProps?.onDoubleClick?.(event); + openEditingCell({ cell, table }); + }; + + const handleDragEnter = (e) => { + tableCellProps?.onDragEnter?.(e); + if (enableGrouping && hoveredColumn?.id === "drop-zone") { + setHoveredColumn(null); + } + if (enableColumnOrdering && draggingColumn) { + setHoveredColumn(columnDef.enableColumnOrdering !== false ? column : null); + } + }; + + const handleDragOver = (e) => { + if (columnDef.enableColumnOrdering !== false) { + e.preventDefault(); + } + }; + + const handleContextMenu = (e) => { + tableCellProps?.onContextMenu?.(e); + if (isRightClickable) { + e.preventDefault(); + table.setActionCell(cell); + table.refs.actionCellRef.current = e.currentTarget; + } + }; + + return ( + ({ + "&:hover": { + outline: + actionCell?.id === cell.id || + (editDisplayMode === "cell" && isEditable) || + (editDisplayMode === "table" && (isCreating || isEditing)) + ? `1px solid ${theme.palette.grey[500]}` + : undefined, + textOverflow: "clip", + }, + alignItems: layoutMode?.startsWith("grid") ? "center" : undefined, + cursor: isRightClickable + ? "context-menu" + : isEditable && editDisplayMode === "cell" + ? "pointer" + : "inherit", + outline: actionCell?.id === cell.id ? `1px solid ${theme.palette.grey[500]}` : undefined, + outlineOffset: "-1px", + overflow: "hidden", + p: + density === "compact" + ? columnDefType === "display" + ? "0 0.5rem" + : "0.5rem" + : density === "comfortable" + ? columnDefType === "display" + ? "0.5rem 0.75rem" + : "1rem" + : columnDefType === "display" + ? "1rem 1.25rem" + : "1.5rem", + + textOverflow: columnDefType !== "display" ? "ellipsis" : undefined, + whiteSpace: row.getIsPinned() || density === "compact" ? "nowrap" : "normal", + ...getCommonMRTCellStyles({ + column, + table, + tableCellProps, + theme, + }), + ...draggingBorders, + backgroundColor: baseBackgroundColor, + })} + > + {tableCellProps.children ?? ( + <> + {cell.getIsPlaceholder() ? ( + (columnDef.PlaceholderCell?.({ cell, column, row, table }) ?? null) + ) : showSkeletons !== false && (isLoading || showSkeletons) ? ( + + ) : columnDefType === "display" && + (["mrt-row-expand", "mrt-row-numbers", "mrt-row-select"].includes(column.id) || + !row.getIsGrouped()) ? ( + columnDef.Cell?.({ + cell, + column, + renderedCellValue: cell.renderValue(), + row, + rowRef, + staticColumnIndex, + staticRowIndex, + table, + }) + ) : showClickToCopyButton && columnDef.enableClickToCopy !== false ? ( + + + + ) : ( + + )} + {cell.getIsGrouped() && !columnDef.GroupedCell && <> ({row.subRows?.length})} + + )} + + ); }; export default DataTable_TableBodyCell; -export const Memo_DataTable_TableBodyCell = memo( - DataTable_TableBodyCell, - (prev, next) => next.cell === prev.cell, -); +export const Memo_DataTable_TableBodyCell = memo(DataTable_TableBodyCell, (prev, next) => next.cell === prev.cell); diff --git a/src/core/components/DataTable/body/TableBodyCellValue.js b/src/core/components/DataTable/body/TableBodyCellValue.js index 5610935..aea105f 100644 --- a/src/core/components/DataTable/body/TableBodyCellValue.js +++ b/src/core/components/DataTable/body/TableBodyCellValue.js @@ -2,111 +2,102 @@ import { Box } from "@mui/material"; const allowedTypes = ["string", "number"]; -const DataTable_TableBodyCellValue = ({ - cell, - rowRef, - staticColumnIndex, - staticRowIndex, - table, -}) => { - const { - getState, - options: { - enableFilterMatchHighlighting, - mrtTheme: { matchHighlightColor }, - }, - } = table; - const { column, row } = cell; - const { columnDef } = column; - const { globalFilter, globalFilterFn } = getState(); - const filterValue = column.getFilterValue(); +const DataTable_TableBodyCellValue = ({ cell, rowRef, staticColumnIndex, staticRowIndex, table }) => { + const { + getState, + options: { + enableFilterMatchHighlighting, + mrtTheme: { matchHighlightColor }, + }, + } = table; + const { column, row } = cell; + const { columnDef } = column; + const { globalFilter, globalFilterFn } = getState(); + const filterValue = column.getFilterValue(); - let renderedCellValue = - cell.getIsAggregated() && columnDef.AggregatedCell - ? columnDef.AggregatedCell({ - cell, - column, - row, - table, - }) - : row.getIsGrouped() && !cell.getIsGrouped() - ? null - : cell.getIsGrouped() && columnDef.GroupedCell - ? columnDef.GroupedCell({ - cell, - column, - row, - table, - }) - : undefined; + let renderedCellValue = + cell.getIsAggregated() && columnDef.AggregatedCell + ? columnDef.AggregatedCell({ + cell, + column, + row, + table, + }) + : row.getIsGrouped() && !cell.getIsGrouped() + ? null + : cell.getIsGrouped() && columnDef.GroupedCell + ? columnDef.GroupedCell({ + cell, + column, + row, + table, + }) + : undefined; - const isGroupedValue = renderedCellValue !== undefined; + const isGroupedValue = renderedCellValue !== undefined; - if (!isGroupedValue) { - renderedCellValue = cell.renderValue(); - } - - if ( - enableFilterMatchHighlighting && - columnDef.enableFilterMatchHighlighting !== false && - String(renderedCellValue) && - allowedTypes.includes(typeof renderedCellValue) && - ((filterValue && - allowedTypes.includes(typeof filterValue) && - ["autocomplete", "text"].includes(columnDef.filterVariant)) || - (globalFilter && - allowedTypes.includes(typeof globalFilter) && - column.getCanGlobalFilter())) - ) { - const chunks = highlightWords?.({ - matchExactly: - (filterValue ? columnDef._filterFn : globalFilterFn) !== "fuzzy", - query: (filterValue ?? globalFilter ?? "").toString(), - text: renderedCellValue?.toString(), - }); - if (chunks?.length > 1 || chunks?.[0]?.match) { - renderedCellValue = ( - - {chunks?.map(({ key, match, text }) => ( - - )) ?? renderedCellValue} - - ); + if (!isGroupedValue) { + renderedCellValue = cell.renderValue(); } - } - if (columnDef.Cell && !isGroupedValue) { - renderedCellValue = columnDef.Cell({ - cell, - column, - renderedCellValue, - row, - rowRef, - staticColumnIndex, - staticRowIndex, - table, - }); - } + if ( + enableFilterMatchHighlighting && + columnDef.enableFilterMatchHighlighting !== false && + String(renderedCellValue) && + allowedTypes.includes(typeof renderedCellValue) && + ((filterValue && + allowedTypes.includes(typeof filterValue) && + ["autocomplete", "text"].includes(columnDef.filterVariant)) || + (globalFilter && allowedTypes.includes(typeof globalFilter) && column.getCanGlobalFilter())) + ) { + const chunks = highlightWords?.({ + matchExactly: (filterValue ? columnDef._filterFn : globalFilterFn) !== "fuzzy", + query: (filterValue ?? globalFilter ?? "").toString(), + text: renderedCellValue?.toString(), + }); + if (chunks?.length > 1 || chunks?.[0]?.match) { + renderedCellValue = ( + + {chunks?.map(({ key, match, text }) => ( + + )) ?? renderedCellValue} + + ); + } + } - return renderedCellValue; + if (columnDef.Cell && !isGroupedValue) { + renderedCellValue = columnDef.Cell({ + cell, + column, + renderedCellValue, + row, + rowRef, + staticColumnIndex, + staticRowIndex, + table, + }); + } + + return renderedCellValue; }; export default DataTable_TableBodyCellValue; diff --git a/src/core/components/DataTable/body/TableBodyRow.js b/src/core/components/DataTable/body/TableBodyRow.js index 8d32a9d..2d21f32 100644 --- a/src/core/components/DataTable/body/TableBodyRow.js +++ b/src/core/components/DataTable/body/TableBodyRow.js @@ -1,258 +1,216 @@ -import { - commonCellBeforeAfterStyles, - getCommonPinnedCellStyles, - parseFromValuesOrFunc, -} from "@/core/utils/utils"; +import { commonCellBeforeAfterStyles, getCommonPinnedCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils"; import { useTheme } from "@emotion/react"; import { TableRow, alpha, darken, lighten } from "@mui/material"; import { getIsRowSelected } from "material-react-table"; import { memo, useMemo, useRef } from "react"; -import DataTable_TableBodyCell, { - Memo_DataTable_TableBodyCell, -} from "./TableBodyCell"; +import DataTable_TableBodyCell, { Memo_DataTable_TableBodyCell } from "./TableBodyCell"; import DataTable_TableDetailPanel from "./TableDetailPanel"; const DataTable_TableBodyRow = ({ - columnVirtualizer, - numRows, - pinnedRowIds, - row, - rowVirtualizer, - staticRowIndex, - table, - virtualRow, - ...rest + columnVirtualizer, + numRows, + pinnedRowIds, + row, + rowVirtualizer, + staticRowIndex, + table, + virtualRow, + ...rest }) => { - const theme = useTheme(); + const theme = useTheme(); - const { - getState, - options: { - enableRowOrdering, - enableRowPinning, - enableStickyFooter, - enableStickyHeader, - layoutMode, - memoMode, - mrtTheme: { - baseBackgroundColor, - pinnedRowBackgroundColor, - selectedRowBackgroundColor, - }, - muiTableBodyRowProps, - renderDetailPanel, - rowPinningDisplayMode, - }, - refs: { tableFooterRef, tableHeadRef }, - setHoveredRow, - } = table; - const { - density, - draggingColumn, - draggingRow, - editingCell, - editingRow, - hoveredRow, - isFullScreen, - rowPinning, - } = getState(); + const { + getState, + options: { + enableRowOrdering, + enableRowPinning, + enableStickyFooter, + enableStickyHeader, + layoutMode, + memoMode, + mrtTheme: { baseBackgroundColor, pinnedRowBackgroundColor, selectedRowBackgroundColor }, + muiTableBodyRowProps, + renderDetailPanel, + rowPinningDisplayMode, + }, + refs: { tableFooterRef, tableHeadRef }, + setHoveredRow, + } = table; + const { density, draggingColumn, draggingRow, editingCell, editingRow, hoveredRow, isFullScreen, rowPinning } = + getState(); - const visibleCells = row.getVisibleCells(); + const visibleCells = row.getVisibleCells(); - const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } = - columnVirtualizer ?? {}; + const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } = columnVirtualizer ?? {}; - const isRowSelected = getIsRowSelected({ row, table }); - const isRowPinned = enableRowPinning && row.getIsPinned(); - const isDraggingRow = draggingRow?.id === row.id; - const isHoveredRow = hoveredRow?.id === row.id; + const isRowSelected = getIsRowSelected({ row, table }); + const isRowPinned = enableRowPinning && row.getIsPinned(); + const isDraggingRow = draggingRow?.id === row.id; + const isHoveredRow = hoveredRow?.id === row.id; - const tableRowProps = { - ...parseFromValuesOrFunc(muiTableBodyRowProps, { - row, - staticRowIndex, - table, - }), - ...rest, - }; + const tableRowProps = { + ...parseFromValuesOrFunc(muiTableBodyRowProps, { + row, + staticRowIndex, + table, + }), + ...rest, + }; - const [bottomPinnedIndex, topPinnedIndex] = useMemo(() => { - if ( - !enableRowPinning || - !rowPinningDisplayMode?.includes("sticky") || - !pinnedRowIds || - !row.getIsPinned() - ) - return []; - return [ - [...pinnedRowIds].reverse().indexOf(row.id), - pinnedRowIds.indexOf(row.id), - ]; - }, [pinnedRowIds, rowPinning]); + const [bottomPinnedIndex, topPinnedIndex] = useMemo(() => { + if (!enableRowPinning || !rowPinningDisplayMode?.includes("sticky") || !pinnedRowIds || !row.getIsPinned()) + return []; + return [[...pinnedRowIds].reverse().indexOf(row.id), pinnedRowIds.indexOf(row.id)]; + }, [pinnedRowIds, rowPinning]); - const tableHeadHeight = - ((enableStickyHeader || isFullScreen) && - tableHeadRef.current?.clientHeight) || - 0; - const tableFooterHeight = - (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0; + const tableHeadHeight = ((enableStickyHeader || isFullScreen) && tableHeadRef.current?.clientHeight) || 0; + const tableFooterHeight = (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0; - const sx = parseFromValuesOrFunc(tableRowProps?.sx, theme); + const sx = parseFromValuesOrFunc(tableRowProps?.sx, theme); - const defaultRowHeight = - density === "compact" ? 37 : density === "comfortable" ? 53 : 69; + const defaultRowHeight = density === "compact" ? 37 : density === "comfortable" ? 53 : 69; - const customRowHeight = - // @ts-ignore - parseInt(tableRowProps?.style?.height ?? sx?.height, 10) || undefined; + const customRowHeight = + // @ts-ignore + parseInt(tableRowProps?.style?.height ?? sx?.height, 10) || undefined; - const rowHeight = customRowHeight || defaultRowHeight; + const rowHeight = customRowHeight || defaultRowHeight; - const handleDragEnter = (_e) => { - if (enableRowOrdering && draggingRow) { - setHoveredRow(row); - } - }; + const handleDragEnter = (_e) => { + if (enableRowOrdering && draggingRow) { + setHoveredRow(row); + } + }; - const handleDragOver = (e) => { - e.preventDefault(); - }; + const handleDragOver = (e) => { + e.preventDefault(); + }; - const rowRef = useRef(null); + const rowRef = useRef(null); - const cellHighlightColor = isRowSelected - ? selectedRowBackgroundColor - : isRowPinned - ? pinnedRowBackgroundColor - : undefined; + const cellHighlightColor = isRowSelected + ? selectedRowBackgroundColor + : isRowPinned + ? pinnedRowBackgroundColor + : undefined; - const cellHighlightColorHover = - tableRowProps?.hover !== false - ? isRowSelected - ? cellHighlightColor - : theme.palette.mode === "dark" - ? `${lighten(baseBackgroundColor, 0.2)}` - : `${darken(baseBackgroundColor, 0.2)}` - : undefined; + const cellHighlightColorHover = + tableRowProps?.hover !== false + ? isRowSelected + ? cellHighlightColor + : theme.palette.mode === "dark" + ? `${lighten(baseBackgroundColor, 0.2)}` + : `${darken(baseBackgroundColor, 0.2)}` + : undefined; - return ( - <> - { - if (node) { - rowRef.current = node; - rowVirtualizer?.measureElement(node); - } - }} - selected={isRowSelected} - {...tableRowProps} - style={{ - transform: virtualRow - ? `translateY(${virtualRow.start}px)` - : undefined, - ...tableRowProps?.style, - }} - sx={(theme) => ({ - "&:hover td:after": cellHighlightColorHover - ? { - backgroundColor: alpha(cellHighlightColorHover, 0.3), - ...commonCellBeforeAfterStyles, - } - : undefined, - bottom: - !virtualRow && bottomPinnedIndex !== undefined && isRowPinned - ? `${bottomPinnedIndex * rowHeight + (enableStickyFooter ? tableFooterHeight - 1 : 0)}px` - : undefined, - boxSizing: "border-box", - display: layoutMode?.startsWith("grid") ? "flex" : undefined, - opacity: isRowPinned ? 0.97 : isDraggingRow || isHoveredRow ? 0.5 : 1, - position: virtualRow - ? "absolute" - : rowPinningDisplayMode?.includes("sticky") && isRowPinned - ? "sticky" - : "relative", - td: { - ...getCommonPinnedCellStyles({ table, theme }), - }, - "td:after": cellHighlightColor - ? { - backgroundColor: cellHighlightColor, - ...commonCellBeforeAfterStyles, - } - : undefined, - top: virtualRow - ? 0 - : topPinnedIndex !== undefined && isRowPinned - ? `${ - topPinnedIndex * rowHeight + - (enableStickyHeader || isFullScreen ? tableHeadHeight - 1 : 0) - }px` - : undefined, - transition: virtualRow ? "none" : "all 150ms ease-in-out", - width: "100%", - zIndex: - rowPinningDisplayMode?.includes("sticky") && isRowPinned ? 2 : 0, - ...sx, - })} - > - {virtualPaddingLeft ? ( - - ) : null} - {(virtualColumns ?? visibleCells).map( - (cellOrVirtualCell, staticColumnIndex) => { - let cell = cellOrVirtualCell; - if (columnVirtualizer) { - staticColumnIndex = cellOrVirtualCell.index; - cell = visibleCells[staticColumnIndex]; - } - const props = { - cell, - numRows, - rowRef, - staticColumnIndex, - staticRowIndex, - table, - }; - return cell ? ( - memoMode === "cells" && - cell.column.columnDef.columnDefType === "data" && - !draggingColumn && - !draggingRow && - editingCell?.id !== cell.id && - editingRow?.id !== row.id ? ( - - ) : ( - - ) - ) : null; - }, - )} - {virtualPaddingRight ? ( - - ) : null} - - {renderDetailPanel && !row.getIsGrouped() && ( - - )} - - ); + return ( + <> + { + if (node) { + rowRef.current = node; + rowVirtualizer?.measureElement(node); + } + }} + selected={isRowSelected} + {...tableRowProps} + style={{ + transform: virtualRow ? `translateY(${virtualRow.start}px)` : undefined, + ...tableRowProps?.style, + }} + sx={(theme) => ({ + "&:hover td:after": cellHighlightColorHover + ? { + backgroundColor: alpha(cellHighlightColorHover, 0.3), + ...commonCellBeforeAfterStyles, + } + : undefined, + bottom: + !virtualRow && bottomPinnedIndex !== undefined && isRowPinned + ? `${bottomPinnedIndex * rowHeight + (enableStickyFooter ? tableFooterHeight - 1 : 0)}px` + : undefined, + boxSizing: "border-box", + display: layoutMode?.startsWith("grid") ? "flex" : undefined, + opacity: isRowPinned ? 0.97 : isDraggingRow || isHoveredRow ? 0.5 : 1, + position: virtualRow + ? "absolute" + : rowPinningDisplayMode?.includes("sticky") && isRowPinned + ? "sticky" + : "relative", + td: { + ...getCommonPinnedCellStyles({ table, theme }), + }, + "td:after": cellHighlightColor + ? { + backgroundColor: cellHighlightColor, + ...commonCellBeforeAfterStyles, + } + : undefined, + top: virtualRow + ? 0 + : topPinnedIndex !== undefined && isRowPinned + ? `${ + topPinnedIndex * rowHeight + + (enableStickyHeader || isFullScreen ? tableHeadHeight - 1 : 0) + }px` + : undefined, + transition: virtualRow ? "none" : "all 150ms ease-in-out", + width: "100%", + zIndex: rowPinningDisplayMode?.includes("sticky") && isRowPinned ? 2 : 0, + ...sx, + })} + > + {virtualPaddingLeft ? : null} + {(virtualColumns ?? visibleCells).map((cellOrVirtualCell, staticColumnIndex) => { + let cell = cellOrVirtualCell; + if (columnVirtualizer) { + staticColumnIndex = cellOrVirtualCell.index; + cell = visibleCells[staticColumnIndex]; + } + const props = { + cell, + numRows, + rowRef, + staticColumnIndex, + staticRowIndex, + table, + }; + return cell ? ( + memoMode === "cells" && + cell.column.columnDef.columnDefType === "data" && + !draggingColumn && + !draggingRow && + editingCell?.id !== cell.id && + editingRow?.id !== row.id ? ( + + ) : ( + + ) + ) : null; + })} + {virtualPaddingRight ? : null} + + {renderDetailPanel && !row.getIsGrouped() && ( + + )} + + ); }; export default DataTable_TableBodyRow; export const Memo_DataTable_TableBodyRow = memo( - DataTable_TableBodyRow, - (prev, next) => - prev.row === next.row && prev.staticRowIndex === next.staticRowIndex, + DataTable_TableBodyRow, + (prev, next) => prev.row === next.row && prev.staticRowIndex === next.staticRowIndex ); diff --git a/src/core/components/DataTable/body/TableDetailPanel.js b/src/core/components/DataTable/body/TableDetailPanel.js index b997947..853aab5 100644 --- a/src/core/components/DataTable/body/TableDetailPanel.js +++ b/src/core/components/DataTable/body/TableDetailPanel.js @@ -2,90 +2,86 @@ import { parseFromValuesOrFunc } from "@/core/utils/utils"; import { Collapse, TableCell, TableRow } from "@mui/material"; const DataTable_TableDetailPanel = ({ - parentRowRef, - row, - rowVirtualizer, - staticRowIndex, - table, - virtualRow, - ...rest -}) => { - const { - getState, - getVisibleLeafColumns, - options: { - layoutMode, - mrtTheme: { baseBackgroundColor }, - muiDetailPanelProps, - muiTableBodyRowProps, - renderDetailPanel, - }, - } = table; - const { isLoading } = getState(); - - const tableRowProps = parseFromValuesOrFunc(muiTableBodyRowProps, { - isDetailPanel: true, + parentRowRef, row, + rowVirtualizer, staticRowIndex, table, - }); + virtualRow, + ...rest +}) => { + const { + getState, + getVisibleLeafColumns, + options: { + layoutMode, + mrtTheme: { baseBackgroundColor }, + muiDetailPanelProps, + muiTableBodyRowProps, + renderDetailPanel, + }, + } = table; + const { isLoading } = getState(); - const tableCellProps = { - ...parseFromValuesOrFunc(muiDetailPanelProps, { - row, - table, - }), - ...rest, - }; + const tableRowProps = parseFromValuesOrFunc(muiTableBodyRowProps, { + isDetailPanel: true, + row, + staticRowIndex, + table, + }); - const DetailPanel = !isLoading && renderDetailPanel?.({ row, table }); + const tableCellProps = { + ...parseFromValuesOrFunc(muiDetailPanelProps, { + row, + table, + }), + ...rest, + }; - return ( - { - if (node) { - rowVirtualizer?.measureElement?.(node); - } - }} - {...tableRowProps} - sx={(theme) => ({ - display: layoutMode?.startsWith("grid") ? "flex" : undefined, - position: virtualRow ? "absolute" : undefined, - top: virtualRow - ? `${parentRowRef.current?.getBoundingClientRect()?.height}px` - : undefined, - transform: virtualRow - ? `translateY(${virtualRow?.start}px)` - : undefined, - width: "100%", - ...parseFromValuesOrFunc(tableRowProps?.sx, theme), - })} - > - ({ - backgroundColor: virtualRow ? baseBackgroundColor : undefined, - borderBottom: !row.getIsExpanded() ? "none" : undefined, - display: layoutMode?.startsWith("grid") ? "flex" : undefined, - py: !!DetailPanel && row.getIsExpanded() ? "1rem" : 0, - transition: !virtualRow ? "all 150ms ease-in-out" : undefined, - width: `100%`, - ...parseFromValuesOrFunc(tableCellProps?.sx, theme), - })} - > - {virtualRow ? ( - row.getIsExpanded() && DetailPanel - ) : ( - - {DetailPanel} - - )} - - - ); + const DetailPanel = !isLoading && renderDetailPanel?.({ row, table }); + + return ( + { + if (node) { + rowVirtualizer?.measureElement?.(node); + } + }} + {...tableRowProps} + sx={(theme) => ({ + display: layoutMode?.startsWith("grid") ? "flex" : undefined, + position: virtualRow ? "absolute" : undefined, + top: virtualRow ? `${parentRowRef.current?.getBoundingClientRect()?.height}px` : undefined, + transform: virtualRow ? `translateY(${virtualRow?.start}px)` : undefined, + width: "100%", + ...parseFromValuesOrFunc(tableRowProps?.sx, theme), + })} + > + ({ + backgroundColor: virtualRow ? baseBackgroundColor : undefined, + borderBottom: !row.getIsExpanded() ? "none" : undefined, + display: layoutMode?.startsWith("grid") ? "flex" : undefined, + py: !!DetailPanel && row.getIsExpanded() ? "1rem" : 0, + transition: !virtualRow ? "all 150ms ease-in-out" : undefined, + width: `100%`, + ...parseFromValuesOrFunc(tableCellProps?.sx, theme), + })} + > + {virtualRow ? ( + row.getIsExpanded() && DetailPanel + ) : ( + + {DetailPanel} + + )} + + + ); }; export default DataTable_TableDetailPanel; diff --git a/src/core/components/DataTable/buttons/CopyButton.js b/src/core/components/DataTable/buttons/CopyButton.js index 3e2ac04..c4dfe4b 100644 --- a/src/core/components/DataTable/buttons/CopyButton.js +++ b/src/core/components/DataTable/buttons/CopyButton.js @@ -1,74 +1,68 @@ -import { - getCommonTooltipProps, - parseFromValuesOrFunc, -} from "@/core/utils/utils"; +import { getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils"; import { Button, Tooltip } from "@mui/material"; import { useState } from "react"; const DataTable_CopyButton = ({ cell, table, ...rest }) => { - const { - options: { localization, muiCopyButtonProps }, - } = table; - const { column, row } = cell; - const { columnDef } = column; + const { + options: { localization, muiCopyButtonProps }, + } = table; + const { column, row } = cell; + const { columnDef } = column; - const [copied, setCopied] = useState(false); + const [copied, setCopied] = useState(false); - const handleCopy = (event, text) => { - event.stopPropagation(); - navigator.clipboard.writeText(text); - setCopied(true); - setTimeout(() => setCopied(false), 4000); - }; + const handleCopy = (event, text) => { + event.stopPropagation(); + navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => setCopied(false), 4000); + }; - const buttonProps = { - ...parseFromValuesOrFunc(muiCopyButtonProps, { - cell, - column, - row, - table, - }), - ...parseFromValuesOrFunc(columnDef.muiCopyButtonProps, { - cell, - column, - row, - table, - }), - ...rest, - }; + const buttonProps = { + ...parseFromValuesOrFunc(muiCopyButtonProps, { + cell, + column, + row, + table, + }), + ...parseFromValuesOrFunc(columnDef.muiCopyButtonProps, { + cell, + column, + row, + table, + }), + ...rest, + }; - return ( - - + + + + )} + ); - - setValidationSchema(schema); - }, [filterData]); - - const { - handleSubmit, - control, - reset, - formState: { errors, isDirty, isValid }, - } = useForm({ - defaultValues: filterData, - resolver: yupResolver(validationSchema), - mode: "all", - }); - - const onSubmit = (data) => { - setDrawerState(false); - setFilterData(data); - }; - - return ( - <> - - {Object.keys(filterData).length > 0 && ( - -
- - {columns.map((column) => - column.enableColumnFilter ? ( - column.dependencyId ? ( - - ) : ( - - ) - ) : null, - )} - - - - -
-
- )} - - ); } export default FilterBody; diff --git a/src/core/components/DataTable/filter/FilterBodyController.jsx b/src/core/components/DataTable/filter/FilterBodyController.jsx index 201f84d..40ccdf7 100644 --- a/src/core/components/DataTable/filter/FilterBodyController.jsx +++ b/src/core/components/DataTable/filter/FilterBodyController.jsx @@ -2,24 +2,24 @@ import { Controller, useWatch } from "react-hook-form"; import FilterBodyField from "./FilterBodyField"; const FilterBodyController = ({ column, control, reset, errors }) => { - return ( - { - return ( - reset()} - errors={errors} - /> - ); - }} - /> - ); + return ( + { + return ( + reset()} + errors={errors} + /> + ); + }} + /> + ); }; export default FilterBodyController; diff --git a/src/core/components/DataTable/filter/FilterBodyControllerWithDependency.jsx b/src/core/components/DataTable/filter/FilterBodyControllerWithDependency.jsx index 285da0a..f531c48 100644 --- a/src/core/components/DataTable/filter/FilterBodyControllerWithDependency.jsx +++ b/src/core/components/DataTable/filter/FilterBodyControllerWithDependency.jsx @@ -1,32 +1,27 @@ import { Controller, useWatch } from "react-hook-form"; import FilterBodyField from "./FilterBodyField"; -const FilterBodyControllerWithDependency = ({ - column, - control, - reset, - errors, -}) => { - const dependencyField = useWatch({ control, name: column.dependencyId }); +const FilterBodyControllerWithDependency = ({ column, control, reset, errors }) => { + const dependencyField = useWatch({ control, name: column.dependencyId }); - return ( - { - return ( - reset()} - errors={errors} - /> - ); - }} - /> - ); + return ( + { + return ( + reset()} + errors={errors} + /> + ); + }} + /> + ); }; export default FilterBodyControllerWithDependency; diff --git a/src/core/components/DataTable/filter/FilterBodyField.jsx b/src/core/components/DataTable/filter/FilterBodyField.jsx index 3c9abab..869c354 100644 --- a/src/core/components/DataTable/filter/FilterBodyField.jsx +++ b/src/core/components/DataTable/filter/FilterBodyField.jsx @@ -8,98 +8,97 @@ import CustomTextFieldRange from "@/core/components/DataTable/filter/fieldsType/ import { useState } from "react"; const columnFilterModeOptionFa = { - equals: "برابر", - notEquals: "نابرابر", - contains: "شامل", - lessThan: "کوچکتر", - greaterThan: "بزرگتر", - fuzzy: "فازی", - between: "مابین", + equals: "برابر", + notEquals: "نابرابر", + contains: "شامل", + lessThan: "کوچکتر", + greaterThan: "بزرگتر", + fuzzy: "فازی", + between: "مابین", }; function FilterBodyField({ - column, - filterParameters, - handleChange, - handleBlur, - dependencyFieldValue, - setFieldValue, - resetForm, - errors, + column, + filterParameters, + handleChange, + handleBlur, + dependencyFieldValue, + setFieldValue, + resetForm, + errors, }) { - const [anchorEl, setAnchorEl] = useState(null); - const defaultFilterTranslation = - columnFilterModeOptionFa[filterParameters.filterMode] || - filterParameters.filterMode; + const [anchorEl, setAnchorEl] = useState(null); + const defaultFilterTranslation = + columnFilterModeOptionFa[filterParameters.filterMode] || filterParameters.filterMode; - const handleOpenFilterBox = (event) => { - setAnchorEl(event.currentTarget); - }; - - const renderField = () => { - const commonProps = { - column, - filterParameters, - defaultFilterTranslation, - handleOpenFilterBox, - dependencyFieldValue, - setFieldValue, - handleChange, - handleBlur, - errors, + const handleOpenFilterBox = (event) => { + setAnchorEl(event.currentTarget); }; - switch (filterParameters.datatype) { - case "numeric": - if (filterParameters.filterMode === "between") { - return ; - } - if (filterParameters.filterMode === "equals") { - return column.ColumnSelectComponent ? ( - - ) : ( - - ); - } - break; - case "date": - if (filterParameters.filterMode === "equals") { - return ; - } - if (filterParameters.filterMode === "between") { - return ; - } - break; + const renderField = () => { + const commonProps = { + column, + filterParameters, + defaultFilterTranslation, + handleOpenFilterBox, + dependencyFieldValue, + setFieldValue, + handleChange, + handleBlur, + errors, + }; - case "array": - if (filterParameters.filterMode === "equals") { - return ; + switch (filterParameters.datatype) { + case "numeric": + if (filterParameters.filterMode === "between") { + return ; + } + if (filterParameters.filterMode === "equals") { + return column.ColumnSelectComponent ? ( + + ) : ( + + ); + } + break; + case "date": + if (filterParameters.filterMode === "equals") { + return ; + } + if (filterParameters.filterMode === "between") { + return ; + } + break; + + case "array": + if (filterParameters.filterMode === "equals") { + return ; + } + break; + + default: + return ; } - break; + }; - default: - return ; - } - }; - - return ( - <> - {renderField()} - {Array.isArray(column.columnFilterModeOptions) && ( - - )} - - ); + return ( + <> + {renderField()} + {Array.isArray(column.columnFilterModeOptions) && ( + + )} + + ); } export default FilterBodyField; diff --git a/src/core/components/DataTable/filter/FilterButton.jsx b/src/core/components/DataTable/filter/FilterButton.jsx index e8c1d85..79cc879 100644 --- a/src/core/components/DataTable/filter/FilterButton.jsx +++ b/src/core/components/DataTable/filter/FilterButton.jsx @@ -4,36 +4,34 @@ import { IconButton, Tooltip, Badge } from "@mui/material"; import useDataTable from "@/lib/hooks/useDataTable"; function FilterButton({ drawerState, setDrawerState }) { - const { filterData } = useDataTable(); - const isValueEmpty = (value) => { - if (Array.isArray(value)) { - return value.length === 0 || value.every((v) => v === ""); - } - return value === "" || value === null || value === undefined; - }; - const filteredFilterData = Object.values(filterData).filter( - (filter) => !isValueEmpty(filter.value), - ); - return ( - - { - setDrawerState(!drawerState); - }} - aria-label="filter table" - > - - - - - - ); + const { filterData } = useDataTable(); + const isValueEmpty = (value) => { + if (Array.isArray(value)) { + return value.length === 0 || value.every((v) => v === ""); + } + return value === "" || value === null || value === undefined; + }; + const filteredFilterData = Object.values(filterData).filter((filter) => !isValueEmpty(filter.value)); + return ( + + { + setDrawerState(!drawerState); + }} + aria-label="filter table" + > + + + + + + ); } export default FilterButton; diff --git a/src/core/components/DataTable/filter/FilterCustom.jsx b/src/core/components/DataTable/filter/FilterCustom.jsx index 04a2cd1..a8e4e1e 100644 --- a/src/core/components/DataTable/filter/FilterCustom.jsx +++ b/src/core/components/DataTable/filter/FilterCustom.jsx @@ -4,35 +4,35 @@ import { Box, Drawer } from "@mui/material"; import FilterDrawer from "../../FilterDrawer"; const FilterCustom = ({ filterData, setFilterData }) => { - const [open, setOpen] = useState(false); + const [open, setOpen] = useState(false); - const closeDrawer = useCallback(() => setOpen(false), []); + const closeDrawer = useCallback(() => setOpen(false), []); - return ( - <> - - setOpen(false)} - sx={{ - overflowY: "hidden", - display: "flex", - flexDirection: "column", - height: "100%", - zIndex: "1300", - }} - > - - {open && ( - - )} - - - - ); + return ( + <> + + setOpen(false)} + sx={{ + overflowY: "hidden", + display: "flex", + flexDirection: "column", + height: "100%", + zIndex: "1300", + }} + > + + {open && ( + + )} + + + + ); }; export default FilterCustom; diff --git a/src/core/components/DataTable/filter/FilterHeader.jsx b/src/core/components/DataTable/filter/FilterHeader.jsx index 6a0572d..1aac54e 100644 --- a/src/core/components/DataTable/filter/FilterHeader.jsx +++ b/src/core/components/DataTable/filter/FilterHeader.jsx @@ -5,31 +5,30 @@ import FilterAltIcon from "@mui/icons-material/FilterAlt"; import { Box, IconButton, Typography } from "@mui/material"; function FilterHeader({ setDrawerState }) { - return ( - theme.palette.primary.main, - boxShadow: - "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px", - maxWidth: "450px", - }} - > - - - - فیلتر - - - setDrawerState(false)}> - - - - ); + return ( + theme.palette.primary.main, + boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px", + maxWidth: "450px", + }} + > + + + + فیلتر + + + setDrawerState(false)}> + + + + ); } export default FilterHeader; diff --git a/src/core/components/DataTable/filter/FilterOptionList.jsx b/src/core/components/DataTable/filter/FilterOptionList.jsx index 205b25b..517d1f2 100644 --- a/src/core/components/DataTable/filter/FilterOptionList.jsx +++ b/src/core/components/DataTable/filter/FilterOptionList.jsx @@ -4,55 +4,49 @@ import { ListItem, Menu } from "@mui/material"; import { useState } from "react"; function FilterOptionList({ - filterType, - filterOption, - filterParameters, - anchorEl, - columnFilterModeOptionFa, - setAnchorEl, - handleChange, + filterType, + filterOption, + filterParameters, + anchorEl, + columnFilterModeOptionFa, + setAnchorEl, + handleChange, }) { - const [selectedFilter, setSelectedFilter] = useState(filterType); + const [selectedFilter, setSelectedFilter] = useState(filterType); - const handleChangeItem = (event, index) => { - handleChange({ - ...filterParameters, - value: filterOption[index] === "between" ? ["", ""] : "", - filterMode: filterOption[index], - }); - setSelectedFilter(filterOption[index]); - setAnchorEl(null); - }; + const handleChangeItem = (event, index) => { + handleChange({ + ...filterParameters, + value: filterOption[index] === "between" ? ["", ""] : "", + filterMode: filterOption[index], + }); + setSelectedFilter(filterOption[index]); + setAnchorEl(null); + }; - const handleCloseFilterBox = () => { - setAnchorEl(null); - }; + const handleCloseFilterBox = () => { + setAnchorEl(null); + }; - return ( - - {filterOption.map((option, index) => ( - handleChangeItem(event, index)} - selected={option === selectedFilter} - sx={{ - cursor: "pointer", - width: "100px", - display: "flex", - justifyContent: "center", - }} - > - {columnFilterModeOptionFa[option]} - - ))} - - ); + return ( + + {filterOption.map((option, index) => ( + handleChangeItem(event, index)} + selected={option === selectedFilter} + sx={{ + cursor: "pointer", + width: "100px", + display: "flex", + justifyContent: "center", + }} + > + {columnFilterModeOptionFa[option]} + + ))} + + ); } export default FilterOptionList; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePicker.jsx b/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePicker.jsx index 85e2b08..5666a43 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePicker.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePicker.jsx @@ -2,30 +2,22 @@ import React from "react"; import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker"; import { Typography } from "@mui/material"; -function CustomDatePicker({ - column, - filterParameters, - defaultFilterTranslation, - handleChange, -}) { - return ( - { - handleChange({ ...filterParameters, value: formattedDate }); - }} - placeholder={column.header} - helperText={ - theme.palette.primary.main }} - > - نوع فیلتر: {defaultFilterTranslation} (تاریخ) - - } - /> - ); +function CustomDatePicker({ column, filterParameters, defaultFilterTranslation, handleChange }) { + return ( + { + handleChange({ ...filterParameters, value: formattedDate }); + }} + placeholder={column.header} + helperText={ + theme.palette.primary.main }}> + نوع فیلتر: {defaultFilterTranslation} (تاریخ) + + } + /> + ); } export default CustomDatePicker; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePickerRange.jsx b/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePickerRange.jsx index 3b47437..36404b9 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePickerRange.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomDate/CustomDatePickerRange.jsx @@ -4,57 +4,44 @@ import React from "react"; import { Box, Typography } from "@mui/material"; import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker"; -function CustomDatePickerRange({ - column, - filterParameters, - defaultFilterTranslation, - handleChange, - errors, -}) { - return ( - - { - handleChange({ - ...filterParameters, - value: [formattedDate, filterParameters.value[1]], - }); - }} - maxDate={filterParameters.value[1]} - placeholder={`از تاریخ`} - helperText={ - theme.palette.primary.main }} - > - نوع فیلتر: {defaultFilterTranslation} (تاریخ) - - } - /> - { - handleChange({ - ...filterParameters, - value: [filterParameters.value[0], formattedDate], - }); - }} - minDate={filterParameters.value[0]} - placeholder={`تا تاریخ`} - helperText={ - errors?.[`${column.id}`]?.value - ? errors?.[`${column.id}`]?.value.message - : null - } - error={Boolean(errors?.[`${column.id}`]?.value)} - /> - - ); +function CustomDatePickerRange({ column, filterParameters, defaultFilterTranslation, handleChange, errors }) { + return ( + + { + handleChange({ + ...filterParameters, + value: [formattedDate, filterParameters.value[1]], + }); + }} + maxDate={filterParameters.value[1]} + placeholder={`از تاریخ`} + helperText={ + theme.palette.primary.main }}> + نوع فیلتر: {defaultFilterTranslation} (تاریخ) + + } + /> + { + handleChange({ + ...filterParameters, + value: [filterParameters.value[0], formattedDate], + }); + }} + minDate={filterParameters.value[0]} + placeholder={`تا تاریخ`} + helperText={errors?.[`${column.id}`]?.value ? errors?.[`${column.id}`]?.value.message : null} + error={Boolean(errors?.[`${column.id}`]?.value)} + /> + + ); } export default CustomDatePickerRange; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx b/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx index f98e929..d2d9df0 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx @@ -6,81 +6,67 @@ import { Box, FormHelperText, IconButton, InputAdornment } from "@mui/material"; import ClearIcon from "@mui/icons-material/Clear"; import moment from "jalali-moment"; -function MuiDatePicker({ - label, - value, - setFieldValue, - name, - minDate, - maxDate, - helperText, - placeholder, - error, -}) { - return ( - - - { - const date = new Date(value); - const formattedDate = moment(date) - .locale("en") - .format("YYYY-MM-DD"); - setFieldValue(name, formattedDate); - }} - minDate={minDate ? new Date(minDate) : null} - maxDate={maxDate ? new Date(maxDate) : null} - slotProps={{ - textField: { - size: "small", - error: error, - placeholder: placeholder, - InputProps: { - endAdornment: ( - - { - event.stopPropagation(); - setFieldValue(name, ""); - }} - sx={{ - color: "#bfbfbf", - "&:hover": { - backgroundColor: "rgba(189, 189, 189, 0.1)", - color: "#363434", +function MuiDatePicker({ label, value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error }) { + return ( + + + { + const date = new Date(value); + const formattedDate = moment(date).locale("en").format("YYYY-MM-DD"); + setFieldValue(name, formattedDate); + }} + minDate={minDate ? new Date(minDate) : null} + maxDate={maxDate ? new Date(maxDate) : null} + slotProps={{ + textField: { + size: "small", + error: error, + placeholder: placeholder, + InputProps: { + endAdornment: ( + + { + event.stopPropagation(); + setFieldValue(name, ""); + }} + sx={{ + color: "#bfbfbf", + "&:hover": { + backgroundColor: "rgba(189, 189, 189, 0.1)", + color: "#363434", + }, + }} + > + + + + ), + }, + InputLabelProps: { + shrink: true, + }, }, - }} - > - - - - ), - }, - InputLabelProps: { - shrink: true, - }, - }, - }} - /> - {/* + }} + /> + {/* {helperText ? helperText : ""} */} - - - ); + + + ); } export default MuiDatePicker; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomSelect.jsx b/src/core/components/DataTable/filter/fieldsType/CustomSelect.jsx index c1e5821..f008c5e 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomSelect.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomSelect.jsx @@ -1,38 +1,30 @@ "use client"; -import { - FormControl, - InputLabel, - MenuItem, - OutlinedInput, - Select, -} from "@mui/material"; +import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material"; function CustomSelect({ column, filterParameters, handleChange }) { - return ( - - - {column.header} - - - - ); + return ( + + + {column.header} + + + + ); } export default CustomSelect; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomSelectByDependency.jsx b/src/core/components/DataTable/filter/fieldsType/CustomSelectByDependency.jsx index 4e828c3..0501dbb 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomSelectByDependency.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomSelectByDependency.jsx @@ -1,49 +1,39 @@ "use client"; -import { - FormControl, - FormHelperText, - InputLabel, - MenuItem, - OutlinedInput, - Select, - Typography, -} from "@mui/material"; +import { FormControl, FormHelperText, InputLabel, MenuItem, OutlinedInput, Select, Typography } from "@mui/material"; import { useCallback, useEffect } from "react"; function CustomSelectByDependency({ - column, - filterParameters, - value, - defaultFilterTranslation, - handleChange, - columnSelectOption, + column, + filterParameters, + value, + defaultFilterTranslation, + handleChange, + columnSelectOption, }) { - return ( - - - {column.header} - - - - ); + return ( + + + {column.header} + + + + ); } export default CustomSelectByDependency; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomSelectMultiple.jsx b/src/core/components/DataTable/filter/fieldsType/CustomSelectMultiple.jsx index 19843f5..424ab4c 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomSelectMultiple.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomSelectMultiple.jsx @@ -1,62 +1,55 @@ "use client"; import { - Box, - Chip, - FormControl, - FormHelperText, - InputLabel, - MenuItem, - OutlinedInput, - Select, - Typography, + Box, + Chip, + FormControl, + FormHelperText, + InputLabel, + MenuItem, + OutlinedInput, + Select, + Typography, } from "@mui/material"; -function CustomSelectMultiple({ - column, - filterParameters, - defaultFilterTranslation, - handleChange, -}) { - const columnSelectOption = column.columnSelectOption; +function CustomSelectMultiple({ column, filterParameters, defaultFilterTranslation, handleChange }) { + const columnSelectOption = column.columnSelectOption; - const getLabelForValue = (value) => { - const option = columnSelectOption.find((opt) => opt.value === value); - return option ? option.label : value; - }; + const getLabelForValue = (value) => { + const option = columnSelectOption.find((opt) => opt.value === value); + return option ? option.label : value; + }; - return ( - - - {column.header} - - - - ); + return ( + + + {column.header} + + + + ); } export default CustomSelectMultiple; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomTextField.jsx b/src/core/components/DataTable/filter/fieldsType/CustomTextField.jsx index be54a9f..c6555f2 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomTextField.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomTextField.jsx @@ -2,41 +2,35 @@ import { InputAdornment, TextField, Typography } from "@mui/material"; import FilterListIcon from "@mui/icons-material/FilterList"; function CustomTextField({ - column, - defaultFilterTranslation, - filterParameters, - handleOpenFilterBox, - handleBlur, - handleChange, + column, + defaultFilterTranslation, + filterParameters, + handleOpenFilterBox, + handleBlur, + handleChange, }) { - return ( - - handleChange({ ...filterParameters, value: e.target.value }) - } - onBlur={handleBlur} - fullWidth - variant="outlined" - size="small" - sx={{ my: 1 }} - InputProps={{ - endAdornment: ( - - - - ), - }} - InputLabelProps={{ shrink: true }} - /> - ); + return ( + handleChange({ ...filterParameters, value: e.target.value })} + onBlur={handleBlur} + fullWidth + variant="outlined" + size="small" + sx={{ my: 1 }} + InputProps={{ + endAdornment: ( + + + + ), + }} + InputLabelProps={{ shrink: true }} + /> + ); } export default CustomTextField; diff --git a/src/core/components/DataTable/filter/fieldsType/CustomTextFieldRange.jsx b/src/core/components/DataTable/filter/fieldsType/CustomTextFieldRange.jsx index fc55634..0e434ec 100644 --- a/src/core/components/DataTable/filter/fieldsType/CustomTextFieldRange.jsx +++ b/src/core/components/DataTable/filter/fieldsType/CustomTextFieldRange.jsx @@ -2,84 +2,73 @@ import { Box, InputAdornment, TextField, Typography } from "@mui/material"; import FilterListIcon from "@mui/icons-material/FilterList"; function CustomTextFieldRange({ - column, - defaultFilterTranslation, - handleOpenFilterBox, - handleChange, - filterParameters, - handleBlur, - errors, + column, + defaultFilterTranslation, + handleOpenFilterBox, + handleChange, + filterParameters, + handleBlur, + errors, }) { - return ( - - - handleChange({ - ...filterParameters, - value: [e.target.value, filterParameters.value[1]], - }) - } - onBlur={handleBlur} - label={از {column.header}} - value={filterParameters.value[0]} - fullWidth - error={ - touched?.[`${column.id}`]?.value && - Boolean(errors?.[`${column.id}`]?.value) - } - helperText={ - theme.palette.primary.main, - fontWeight: "bold", - }} - > - نوع فیلتر: {defaultFilterTranslation} - - } - variant="outlined" - size="small" - sx={{ my: 1, marginRight: 1 }} - /> - - handleChange({ - ...filterParameters, - value: [filterParameters.value[0], e.target.value], - }) - } - onBlur={handleBlur} - error={Boolean(errors?.[`${column.id}`]?.value)} - helperText={ - errors?.[`${column.id}`]?.value - ? errors?.[`${column.id}`]?.value.message - : null - } - label={تا {column.header}} - value={filterParameters.value[1]} - fullWidth - variant="outlined" - size="small" - sx={{ my: 1 }} - InputProps={{ - endAdornment: ( - - - - ), - }} - /> - - ); + return ( + + + handleChange({ + ...filterParameters, + value: [e.target.value, filterParameters.value[1]], + }) + } + onBlur={handleBlur} + label={از {column.header}} + value={filterParameters.value[0]} + fullWidth + error={touched?.[`${column.id}`]?.value && Boolean(errors?.[`${column.id}`]?.value)} + helperText={ + theme.palette.primary.main, + fontWeight: "bold", + }} + > + نوع فیلتر: {defaultFilterTranslation} + + } + variant="outlined" + size="small" + sx={{ my: 1, marginRight: 1 }} + /> + + handleChange({ + ...filterParameters, + value: [filterParameters.value[0], e.target.value], + }) + } + onBlur={handleBlur} + error={Boolean(errors?.[`${column.id}`]?.value)} + helperText={errors?.[`${column.id}`]?.value ? errors?.[`${column.id}`]?.value.message : null} + label={تا {column.header}} + value={filterParameters.value[1]} + fullWidth + variant="outlined" + size="small" + sx={{ my: 1 }} + InputProps={{ + endAdornment: ( + + + + ), + }} + /> + + ); } export default CustomTextFieldRange; diff --git a/src/core/components/DataTable/filter/index.jsx b/src/core/components/DataTable/filter/index.jsx index a03159d..5dfbb22 100644 --- a/src/core/components/DataTable/filter/index.jsx +++ b/src/core/components/DataTable/filter/index.jsx @@ -5,37 +5,37 @@ import FilterBody from "@/core/components/DataTable/filter/FilterBody"; import { Box, Drawer } from "@mui/material"; function FilterColumn({ columns, user_id, page_name, table_name }) { - const [open, setOpen] = useState(false); + const [open, setOpen] = useState(false); - return ( - <> - - setOpen(false)} - sx={{ - overflowY: "hidden", - display: "flex", - flexDirection: "column", - height: "100%", - zIndex: "1300", - }} - > - - {open && ( - - )} - - - - ); + return ( + <> + + setOpen(false)} + sx={{ + overflowY: "hidden", + display: "flex", + flexDirection: "column", + height: "100%", + zIndex: "1300", + }} + > + + {open && ( + + )} + + + + ); } export default FilterColumn; diff --git a/src/core/components/DataTable/head/TableHead.js b/src/core/components/DataTable/head/TableHead.js index 828cc48..39ee214 100644 --- a/src/core/components/DataTable/head/TableHead.js +++ b/src/core/components/DataTable/head/TableHead.js @@ -3,54 +3,49 @@ import { TableHead } from "@mui/material"; import DataTable_TableHeadRow from "./TableHeadRow"; const DataTable_TableHead = ({ columnVirtualizer, table, ...rest }) => { - const { - getState, - options: { - enableStickyHeader, - layoutMode, - muiTableHeadProps, - positionToolbarAlertBanner, - }, - refs: { tableHeadRef }, - } = table; - const { isFullScreen, showAlertBanner } = getState(); + const { + getState, + options: { enableStickyHeader, layoutMode, muiTableHeadProps, positionToolbarAlertBanner }, + refs: { tableHeadRef }, + } = table; + const { isFullScreen, showAlertBanner } = getState(); - const tableHeadProps = { - ...parseFromValuesOrFunc(muiTableHeadProps, { table }), - ...rest, - }; + const tableHeadProps = { + ...parseFromValuesOrFunc(muiTableHeadProps, { table }), + ...rest, + }; - const stickyHeader = enableStickyHeader || isFullScreen; + const stickyHeader = enableStickyHeader || isFullScreen; - return ( - { - tableHeadRef.current = ref; - if (tableHeadProps?.ref) { - // @ts-ignore - tableHeadProps.ref.current = ref; - } - }} - sx={(theme) => ({ - display: layoutMode?.startsWith("grid") ? "grid" : undefined, - opacity: 0.97, - position: stickyHeader ? "sticky" : "relative", - top: stickyHeader && layoutMode?.startsWith("grid") ? 0 : undefined, - zIndex: stickyHeader ? 2 : undefined, - ...parseFromValuesOrFunc(tableHeadProps?.sx, theme), - })} - > - {table.getHeaderGroups().map((headerGroup, index) => ( - - ))} - - ); + return ( + { + tableHeadRef.current = ref; + if (tableHeadProps?.ref) { + // @ts-ignore + tableHeadProps.ref.current = ref; + } + }} + sx={(theme) => ({ + display: layoutMode?.startsWith("grid") ? "grid" : undefined, + opacity: 0.97, + position: stickyHeader ? "sticky" : "relative", + top: stickyHeader && layoutMode?.startsWith("grid") ? 0 : undefined, + zIndex: stickyHeader ? 2 : undefined, + ...parseFromValuesOrFunc(tableHeadProps?.sx, theme), + })} + > + {table.getHeaderGroups().map((headerGroup, index) => ( + + ))} + + ); }; export default DataTable_TableHead; diff --git a/src/core/components/DataTable/head/TableHeadCell.js b/src/core/components/DataTable/head/TableHeadCell.js index febf64c..631a122 100644 --- a/src/core/components/DataTable/head/TableHeadCell.js +++ b/src/core/components/DataTable/head/TableHeadCell.js @@ -1,290 +1,244 @@ -import { - getCommonMRTCellStyles, - parseFromValuesOrFunc, -} from "@/core/utils/utils"; +import { getCommonMRTCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils"; import { useTheme } from "@emotion/react"; import { Box, TableCell } from "@mui/material"; import { MRT_TableHeadCellSortLabel } from "material-react-table"; import { useMemo } from "react"; -const DataTable_TableHeadCell = ({ - columnVirtualizer, - header, - staticColumnIndex, - backgroundColor, - table, - ...rest -}) => { - const theme = useTheme(); - const { - getState, - options: { - columnResizeDirection, - columnResizeMode, - enableColumnActions, - enableColumnDragging, - enableColumnOrdering, - enableColumnPinning, - enableGrouping, - enableMultiSort, - layoutMode, - mrtTheme: { draggingBorderColor }, - muiTableHeadCellProps, - }, - refs: { tableHeadCellRefs }, - setHoveredColumn, - } = table; - const { - columnSizingInfo, - density, - draggingColumn, - grouping, - hoveredColumn, - showColumnFilters, - } = getState(); - const { column } = header; - const { columnDef } = column; - const { columnDefType } = columnDef; - - const tableCellProps = { - ...parseFromValuesOrFunc(muiTableHeadCellProps, { column, table }), - ...parseFromValuesOrFunc(columnDef.muiTableHeadCellProps, { - column, - table, - }), - ...rest, - }; - - const isColumnPinned = - enableColumnPinning && - columnDef.columnDefType !== "group" && - column.getIsPinned(); - - const showColumnActions = - (enableColumnActions || columnDef.enableColumnActions) && - columnDef.enableColumnActions !== false; - - const showDragHandle = - enableColumnDragging !== false && - columnDef.enableColumnDragging !== false && - (enableColumnDragging || - (enableColumnOrdering && columnDef.enableColumnOrdering !== false) || - (enableGrouping && - columnDef.enableGrouping !== false && - !grouping.includes(column.id))); - - const headerPL = useMemo(() => { - let pl = 0; - if (column.getCanSort()) pl += 1; - if (showColumnActions) pl += 1.75; - if (showDragHandle) pl += 1.5; - return pl; - }, [showColumnActions, showDragHandle]); - - const draggingBorders = useMemo(() => { - const showResizeBorder = - columnSizingInfo.isResizingColumn === column.id && - columnResizeMode === "onChange" && - !header.subHeaders.length; - - const borderStyle = showResizeBorder - ? `2px solid ${draggingBorderColor} !important` - : draggingColumn?.id === column.id - ? `1px dashed ${theme.palette.grey[500]}` - : hoveredColumn?.id === column.id - ? `2px dashed ${draggingBorderColor}` - : undefined; - - if (showResizeBorder) { - return columnResizeDirection === "ltr" - ? { borderRight: borderStyle } - : { borderLeft: borderStyle }; - } - const draggingBorders = borderStyle - ? { - borderLeft: borderStyle, - borderRight: borderStyle, - borderTop: borderStyle, - } - : undefined; - - return draggingBorders; - }, [draggingColumn, hoveredColumn, columnSizingInfo.isResizingColumn]); - - const handleDragEnter = (_e) => { - if (enableGrouping && hoveredColumn?.id === "drop-zone") { - setHoveredColumn(null); - } - if (enableColumnOrdering && draggingColumn && columnDefType !== "group") { - setHoveredColumn( - columnDef.enableColumnOrdering !== false ? column : null, - ); - } - }; - - const handleDragOver = (e) => { - if (columnDef.enableColumnOrdering !== false) { - e.preventDefault(); - } - }; - - const HeaderElement = - parseFromValuesOrFunc(columnDef.Header, { - column, - header, - table, - }) ?? columnDef.header; - - const columnRelativeDepth = header.depth - column.depth; - - if (columnRelativeDepth > 1) { - return null; - } - - let rowSpan = 1; - if (header.isPlaceholder) { - const leafs = header.getLeafHeaders(); - rowSpan = leafs[leafs.length - 1].depth - header.depth; - } - - return ( - { - if (node) { - tableHeadCellRefs.current[column.id] = node; - if (columnDefType !== "group") { - columnVirtualizer?.measureElement?.(node); - } - } - }} - {...tableCellProps} - sx={(theme) => ({ - "& :hover": { - ".MuiButtonBase-root": { - opacity: 1, - }, +const DataTable_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, backgroundColor, table, ...rest }) => { + const theme = useTheme(); + const { + getState, + options: { + columnResizeDirection, + columnResizeMode, + enableColumnActions, + enableColumnDragging, + enableColumnOrdering, + enableColumnPinning, + enableGrouping, + enableMultiSort, + layoutMode, + mrtTheme: { draggingBorderColor }, + muiTableHeadCellProps, }, - flexDirection: layoutMode?.startsWith("grid") ? "column" : undefined, - fontWeight: "bold", - overflow: "visible", - p: - density === "compact" - ? "0.5rem" - : density === "comfortable" - ? columnDefType === "display" - ? "0.75rem" - : "1rem" - : columnDefType === "display" - ? "1rem 1.25rem" - : "1.5rem", - pb: - columnDefType === "display" - ? 0 - : showColumnFilters || density === "compact" - ? "0.4rem" - : "0.6rem", - pt: - columnDefType === "group" || density === "compact" - ? "0.25rem" - : density === "comfortable" - ? ".75rem" - : "1.25rem", - userSelect: enableMultiSort && column.getCanSort() ? "none" : undefined, - verticalAlign: "middle", - ...getCommonMRTCellStyles({ - column, - header, - table, - tableCellProps, - theme, + refs: { tableHeadCellRefs }, + setHoveredColumn, + } = table; + const { columnSizingInfo, density, draggingColumn, grouping, hoveredColumn, showColumnFilters } = getState(); + const { column } = header; + const { columnDef } = column; + const { columnDefType } = columnDef; + + const tableCellProps = { + ...parseFromValuesOrFunc(muiTableHeadCellProps, { column, table }), + ...parseFromValuesOrFunc(columnDef.muiTableHeadCellProps, { + column, + table, }), - ...draggingBorders, - backgroundColor: backgroundColor, - })} - > - {tableCellProps.children ?? ( - - { + let pl = 0; + if (column.getCanSort()) pl += 1; + if (showColumnActions) pl += 1.75; + if (showDragHandle) pl += 1.5; + return pl; + }, [showColumnActions, showDragHandle]); + + const draggingBorders = useMemo(() => { + const showResizeBorder = + columnSizingInfo.isResizingColumn === column.id && + columnResizeMode === "onChange" && + !header.subHeaders.length; + + const borderStyle = showResizeBorder + ? `2px solid ${draggingBorderColor} !important` + : draggingColumn?.id === column.id + ? `1px dashed ${theme.palette.grey[500]}` + : hoveredColumn?.id === column.id + ? `2px dashed ${draggingBorderColor}` + : undefined; + + if (showResizeBorder) { + return columnResizeDirection === "ltr" ? { borderRight: borderStyle } : { borderLeft: borderStyle }; + } + const draggingBorders = borderStyle + ? { + borderLeft: borderStyle, + borderRight: borderStyle, + borderTop: borderStyle, + } + : undefined; + + return draggingBorders; + }, [draggingColumn, hoveredColumn, columnSizingInfo.isResizingColumn]); + + const handleDragEnter = (_e) => { + if (enableGrouping && hoveredColumn?.id === "drop-zone") { + setHoveredColumn(null); + } + if (enableColumnOrdering && draggingColumn && columnDefType !== "group") { + setHoveredColumn(columnDef.enableColumnOrdering !== false ? column : null); + } + }; + + const handleDragOver = (e) => { + if (columnDef.enableColumnOrdering !== false) { + e.preventDefault(); + } + }; + + const HeaderElement = + parseFromValuesOrFunc(columnDef.Header, { + column, + header, + table, + }) ?? columnDef.header; + + const columnRelativeDepth = header.depth - column.depth; + + if (columnRelativeDepth > 1) { + return null; + } + + let rowSpan = 1; + if (header.isPlaceholder) { + const leafs = header.getLeafHeaders(); + rowSpan = leafs[leafs.length - 1].depth - header.depth; + } + + return ( + { + if (node) { + tableHeadCellRefs.current[column.id] = node; + if (columnDefType !== "group") { + columnVirtualizer?.measureElement?.(node); + } + } }} - > - ({ + "& :hover": { + ".MuiButtonBase-root": { + opacity: 1, + }, }, - minWidth: `${Math.min(columnDef.header?.length ?? 0, 4)}ch`, - overflow: columnDefType === "data" ? "hidden" : undefined, - textOverflow: "ellipsis", - textAlign: "start", - color: "#fff", - fontWeight: "400", - whiteSpace: "nowrap", - }} - > - {HeaderElement} - - {column.getCanSort() && columnDefType !== "group" && ( - + flexDirection: layoutMode?.startsWith("grid") ? "column" : undefined, + fontWeight: "bold", + overflow: "visible", + p: + density === "compact" + ? "0.5rem" + : density === "comfortable" + ? columnDefType === "display" + ? "0.75rem" + : "1rem" + : columnDefType === "display" + ? "1rem 1.25rem" + : "1.5rem", + pb: columnDefType === "display" ? 0 : showColumnFilters || density === "compact" ? "0.4rem" : "0.6rem", + pt: + columnDefType === "group" || density === "compact" + ? "0.25rem" + : density === "comfortable" + ? ".75rem" + : "1.25rem", + userSelect: enableMultiSort && column.getCanSort() ? "none" : undefined, + verticalAlign: "middle", + ...getCommonMRTCellStyles({ + column, + header, + table, + tableCellProps, + theme, + }), + ...draggingBorders, + backgroundColor: backgroundColor, + })} + > + {tableCellProps.children ?? ( + + + + {HeaderElement} + + {column.getCanSort() && columnDefType !== "group" && ( + + )} + + )} - - - )} - - ); + + ); }; export default DataTable_TableHeadCell; diff --git a/src/core/components/DataTable/head/TableHeadRow.js b/src/core/components/DataTable/head/TableHeadRow.js index bee809f..94a50f2 100644 --- a/src/core/components/DataTable/head/TableHeadRow.js +++ b/src/core/components/DataTable/head/TableHeadRow.js @@ -3,67 +3,58 @@ import { TableRow, useTheme } from "@mui/material"; import DataTable_TableHeadCell from "./TableHeadCell"; const DataTable_TableHeadRow = ({ - columnVirtualizer, - headerGroup, - table, - index, // Add index prop - ...rest + columnVirtualizer, + headerGroup, + table, + index, // Add index prop + ...rest }) => { - const { palette } = useTheme(); + const { palette } = useTheme(); - const { - options: { enableStickyHeader, layoutMode, muiTableHeadRowProps }, - } = table; - const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } = - columnVirtualizer ?? {}; + const { + options: { enableStickyHeader, layoutMode, muiTableHeadRowProps }, + } = table; + const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } = columnVirtualizer ?? {}; - const backgroundColor = - index % 2 === 0 ? palette.primary.main : palette.secondary.main; + const backgroundColor = index % 2 === 0 ? palette.primary.main : palette.secondary.main; - const tableRowProps = { - ...parseFromValuesOrFunc(muiTableHeadRowProps, { - headerGroup, - table, - }), - ...rest, - sx: (theme) => ({ - // Access theme from the sx function - ...(parseFromValuesOrFunc(muiTableHeadRowProps?.sx, theme) || {}), - display: layoutMode?.startsWith("grid") ? "flex" : undefined, - position: - enableStickyHeader && layoutMode === "semantic" ? "sticky" : "relative", - top: 0, - }), - }; + const tableRowProps = { + ...parseFromValuesOrFunc(muiTableHeadRowProps, { + headerGroup, + table, + }), + ...rest, + sx: (theme) => ({ + // Access theme from the sx function + ...(parseFromValuesOrFunc(muiTableHeadRowProps?.sx, theme) || {}), + display: layoutMode?.startsWith("grid") ? "flex" : undefined, + position: enableStickyHeader && layoutMode === "semantic" ? "sticky" : "relative", + top: 0, + }), + }; - return ( - - {virtualPaddingLeft && ( - - )} - {(virtualColumns ?? headerGroup.headers).map( - (headerOrVirtualHeader, staticColumnIndex) => { - const header = columnVirtualizer - ? headerGroup.headers[headerOrVirtualHeader.index] - : headerOrVirtualHeader; + return ( + + {virtualPaddingLeft && } + {(virtualColumns ?? headerGroup.headers).map((headerOrVirtualHeader, staticColumnIndex) => { + const header = columnVirtualizer + ? headerGroup.headers[headerOrVirtualHeader.index] + : headerOrVirtualHeader; - return header ? ( - - ) : null; - }, - )} - {virtualPaddingRight && ( - - )} - - ); + return header ? ( + + ) : null; + })} + {virtualPaddingRight && } + + ); }; export default DataTable_TableHeadRow; diff --git a/src/core/components/DataTable/hide/HideBody.jsx b/src/core/components/DataTable/hide/HideBody.jsx index 47c96ee..9cf76f6 100644 --- a/src/core/components/DataTable/hide/HideBody.jsx +++ b/src/core/components/DataTable/hide/HideBody.jsx @@ -8,36 +8,31 @@ import HideOrShowAll from "@/core/components/DataTable/hide/HideOrShowAll"; import ScrollBox from "../../ScrollBox"; function HideBody({ columns, drawerState, setDrawerState }) { - const { hideData, setHideData } = useDataTable(); + const { hideData, setHideData } = useDataTable(); - return ( - setDrawerState(false)} - sx={{ - overflowY: "hidden", - display: "flex", - flexDirection: "column", - height: "100%", - zIndex: "1300", - }} - > - - - - - {columns.map((column) => ( - - ))} - - - - ); + return ( + setDrawerState(false)} + sx={{ + overflowY: "hidden", + display: "flex", + flexDirection: "column", + height: "100%", + zIndex: "1300", + }} + > + + + + + {columns.map((column) => ( + + ))} + + + + ); } export default HideBody; diff --git a/src/core/components/DataTable/hide/HideBodyField.jsx b/src/core/components/DataTable/hide/HideBodyField.jsx index c008514..6b60966 100644 --- a/src/core/components/DataTable/hide/HideBodyField.jsx +++ b/src/core/components/DataTable/hide/HideBodyField.jsx @@ -3,78 +3,74 @@ import { SimpleTreeView } from "@mui/x-tree-view"; import { TreeItem, treeItemClasses } from "@mui/x-tree-view/TreeItem"; const CustomTreeItem = styled(TreeItem)(({ theme }) => ({ - [`& .${treeItemClasses.content}`]: { - padding: theme.spacing(0.5, 0.5), - margin: theme.spacing(0.2, 0), - gap: 0, - }, - [`& .${treeItemClasses.iconContainer}`]: { - "& .close": { - opacity: 0.3, + [`& .${treeItemClasses.content}`]: { + padding: theme.spacing(0.5, 0.5), + margin: theme.spacing(0.2, 0), + gap: 0, + }, + [`& .${treeItemClasses.iconContainer}`]: { + "& .close": { + opacity: 0.3, + }, + }, + [`& .${treeItemClasses.groupTransition}`]: { + marginLeft: 16, + paddingLeft: 16, + borderLeft: `1px dashed ${alpha(theme.palette.text.primary, 0.4)}`, }, - }, - [`& .${treeItemClasses.groupTransition}`]: { - marginLeft: 16, - paddingLeft: 16, - borderLeft: `1px dashed ${alpha(theme.palette.text.primary, 0.4)}`, - }, })); function HideBodyField({ column, hideData, setHideData }) { - const handleCheckboxChange = () => { - setHideData((prevData) => { - const updateHideData = (data, id) => { - if (data.hasOwnProperty(id)) { - return { ...data, [id]: !data[id] }; + const handleCheckboxChange = () => { + setHideData((prevData) => { + const updateHideData = (data, id) => { + if (data.hasOwnProperty(id)) { + return { ...data, [id]: !data[id] }; + } + const updatedData = { ...data }; + for (const key in data) { + if (data[key] && typeof data[key] === "object") { + updatedData[key] = updateHideData(data[key], id); + } + } + return updatedData; + }; + + return updateHideData(prevData, column.id); + }); + }; + + const labelContent = (() => { + if (typeof hideData[column.id] === "boolean") { + return ( + + + {column.header} + + ); + } else { + return ( + + {column.header} + + ); } - const updatedData = { ...data }; - for (const key in data) { - if (data[key] && typeof data[key] === "object") { - updatedData[key] = updateHideData(data[key], id); - } - } - return updatedData; - }; + })(); - return updateHideData(prevData, column.id); - }); - }; - - const labelContent = (() => { - if (typeof hideData[column.id] === "boolean") { - return ( - - - {column.header} - - ); - } else { - return ( - - {column.header} - - ); - } - })(); - - return ( - - - {column.columns?.map((subColumn) => ( - - ))} - - - ); + return ( + + + {column.columns?.map((subColumn) => ( + + ))} + + + ); } export default HideBodyField; diff --git a/src/core/components/DataTable/hide/HideButton.jsx b/src/core/components/DataTable/hide/HideButton.jsx index 4ada7c7..fa93857 100644 --- a/src/core/components/DataTable/hide/HideButton.jsx +++ b/src/core/components/DataTable/hide/HideButton.jsx @@ -5,33 +5,31 @@ import useDataTable from "@/lib/hooks/useDataTable"; import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects"; function HideButton({ drawerState, setDrawerState }) { - const { hideData } = useDataTable(); - const flattenHideData = flattenObjectOfObjects(hideData); - const falseCount = Object.values(flattenHideData).filter( - (value) => value === false, - ).length; + const { hideData } = useDataTable(); + const flattenHideData = flattenObjectOfObjects(hideData); + const falseCount = Object.values(flattenHideData).filter((value) => value === false).length; - return ( - - { - setDrawerState(!drawerState); - }} - aria-label="hide table column" - > - - - - - - ); + return ( + + { + setDrawerState(!drawerState); + }} + aria-label="hide table column" + > + + + + + + ); } export default HideButton; diff --git a/src/core/components/DataTable/hide/HideHeader.jsx b/src/core/components/DataTable/hide/HideHeader.jsx index 034271e..5adcf25 100644 --- a/src/core/components/DataTable/hide/HideHeader.jsx +++ b/src/core/components/DataTable/hide/HideHeader.jsx @@ -5,31 +5,30 @@ import CancelIcon from "@mui/icons-material/Cancel"; import ViewColumnIcon from "@mui/icons-material/ViewColumn"; function FilterHeader({ setDrawerState }) { - return ( - - - - - نمایش/مخفی کردن ستون ها - - - setDrawerState(false)}> - - - - ); + return ( + + + + + نمایش/مخفی کردن ستون ها + + + setDrawerState(false)}> + + + + ); } export default FilterHeader; diff --git a/src/core/components/DataTable/hide/HideOrShowAll.jsx b/src/core/components/DataTable/hide/HideOrShowAll.jsx index 27c8849..c0d2e8d 100644 --- a/src/core/components/DataTable/hide/HideOrShowAll.jsx +++ b/src/core/components/DataTable/hide/HideOrShowAll.jsx @@ -5,66 +5,66 @@ import VisibilityIcon from "@mui/icons-material/Visibility"; import VisibilityOffIcon from "@mui/icons-material/VisibilityOff"; const setAllValues = (obj, value) => { - const result = {}; - for (const key in obj) { - if (typeof obj[key] === "object" && obj[key] !== null) { - result[key] = setAllValues(obj[key], value); - } else { - result[key] = value; + const result = {}; + for (const key in obj) { + if (typeof obj[key] === "object" && obj[key] !== null) { + result[key] = setAllValues(obj[key], value); + } else { + result[key] = value; + } } - } - return result; + return result; }; const allValuesAre = (obj, value) => { - for (const key in obj) { - if (typeof obj[key] === "object" && obj[key] !== null) { - if (!allValuesAre(obj[key], value)) { - return false; - } - } else if (obj[key] !== value) { - return false; + for (const key in obj) { + if (typeof obj[key] === "object" && obj[key] !== null) { + if (!allValuesAre(obj[key], value)) { + return false; + } + } else if (obj[key] !== value) { + return false; + } } - } - return true; + return true; }; function HideOrShowAll({ hideData, setHideData }) { - const handleShowAll = () => { - const newHideData = setAllValues(hideData, true); - setHideData(newHideData); - }; + const handleShowAll = () => { + const newHideData = setAllValues(hideData, true); + setHideData(newHideData); + }; - const handleHideAll = () => { - const newHideData = setAllValues(hideData, false); - setHideData(newHideData); - }; + const handleHideAll = () => { + const newHideData = setAllValues(hideData, false); + setHideData(newHideData); + }; - const allHidden = allValuesAre(hideData, false); - const allVisible = allValuesAre(hideData, true); + const allHidden = allValuesAre(hideData, false); + const allVisible = allValuesAre(hideData, true); - return ( - - - - - ); + return ( + + + + + ); } export default HideOrShowAll; diff --git a/src/core/components/DataTable/hide/index.jsx b/src/core/components/DataTable/hide/index.jsx index 865c0e2..b917c56 100644 --- a/src/core/components/DataTable/hide/index.jsx +++ b/src/core/components/DataTable/hide/index.jsx @@ -5,20 +5,20 @@ import HideButton from "@/core/components/DataTable/hide/HideButton"; import HideBody from "@/core/components/DataTable/hide/HideBody"; function HideColumn({ columns, user_id, page_name, table_name }) { - const [open, setOpen] = useState(false); - return ( - <> - - - - ); + const [open, setOpen] = useState(false); + return ( + <> + + + + ); } export default HideColumn; diff --git a/src/core/components/DataTable/index.js b/src/core/components/DataTable/index.js index 6f1c07e..1e881f9 100644 --- a/src/core/components/DataTable/index.js +++ b/src/core/components/DataTable/index.js @@ -2,17 +2,17 @@ import DataTable_Main from "./Main"; import DataTableProvider from "@/lib/contexts/DataTable"; const DataTable = (props) => { - return ( - - - - ); + return ( + + + + ); }; export default DataTable; diff --git a/src/core/components/DataTable/localization/fa/datatable.js b/src/core/components/DataTable/localization/fa/datatable.js index 819a84b..e36f366 100644 --- a/src/core/components/DataTable/localization/fa/datatable.js +++ b/src/core/components/DataTable/localization/fa/datatable.js @@ -1,92 +1,91 @@ export const FA_DATATABLE_LOCALIZATION = { - actions: "عملیات", - and: "و", - cancel: "لغو", - changeFilterMode: "تغییر حالت فیلتر", - changeSearchMode: "تغییر حالت جستجو", - clearFilter: "پاک کردن فیلتر", - clearSearch: "پاک کردن جستجو", - clearSort: "پاک کردن مرتب سازی", - clickToCopy: "کلیک برای کپی", - collapse: "جمع شدن", - collapseAll: "جمع شدن همه", - columnActions: "عملیات ستون", - copiedToClipboard: "کپی شد", - dropToGroupBy: "رها کردن برای گروه بندی بر اساس {column}", - edit: "ویرایش", - expand: "باز شدن", - expandAll: "باز شدن همه", - filterArrIncludes: "شامل", - filterArrIncludesAll: "شامل همه", - filterArrIncludesSome: "شامل", - filterBetween: "میان", - filterBetweenInclusive: "میان با احتساب هر دو", - filterByColumn: "فیلتر بر اساس {column}", - filterContains: "شامل", - filterEmpty: "خالی", - filterEndsWith: "به پایان می‌رسد با", - filterEquals: "برابر", - filterEqualsString: "برابر", - filterFuzzy: "نزدیک", - filterGreaterThan: "بزرگتر از", - filterGreaterThanOrEqualTo: "بزرگتر یا مساوی", - filterInNumberRange: "میان", - filterIncludesString: "شامل", - filterIncludesStringSensitive: "شامل", - filterLessThan: "کوچکتر از", - filterLessThanOrEqualTo: "کوچکتر یا مساوی", - filterMode: "حالت فیلتر: {filterType}", - filterNotEmpty: "غیر خالی", - filterNotEquals: "نا برابر", - filterStartsWith: "شروع می‌شود با", - filterWeakEquals: "برابر", - filteringByColumn: "فیلتر بر اساس {column} - {filterType} {filterValue}", - goToFirstPage: "رفتن به صفحه اول", - goToLastPage: "رفتن به صفحه آخر", - goToNextPage: "رفتن به صفحه بعدی", - goToPreviousPage: "رفتن به صفحه قبلی", - grab: "گرفتن", - groupByColumn: "گروه بندی بر اساس {column}", - groupedBy: "گروه بندی شده بر اساس", - hideAll: "پنهان کردن همه", - hideColumn: "پنهان کردن ستون {column}", - max: "حداکثر", - min: "حداقل", - move: "انتقال", - noRecordsToDisplay: "هیچ رکوردی برای نمایش وجود ندارد", - noResultsFound: "نتیجه‌ای یافت نشد", - of: "از", - or: "یا", - pinToLeft: "چسباندن به سمت چپ", - pinToRight: "چسباندن به سمت راست", - resetColumnSize: "بازنشانی اندازه ستون", - resetOrder: "بازنشانی ترتیب", - rowActions: "عملیات ردیف", - rowNumber: "#", - rowNumbers: "شماره ردیف", - rowsPerPage: "ردیف در هر صفحه", - save: "ذخیره", - search: "جستجو", - selectedCountOfRowCountRowsSelected: - "{selectedCount} از {rowCount} ردیف انتخاب شده", - select: "انتخاب", - showAll: "نمایش همه", - showAllColumns: "نمایش همه ستون‌ها", - showHideColumns: "نمایش/مخفی کردن ستون‌ها", - showHideFilters: "نمایش/مخفی کردن فیلترها", - showHideSearch: "نمایش/مخفی کردن جستجو", - sortByColumnAsc: "مرتب سازی بر اساس {column} صعودی", - sortByColumnDesc: "مرتب سازی بر اساس {column} نزولی", - sortedByColumnAsc: "مرتب شده بر اساس {column} صعودی", - sortedByColumnDesc: "مرتب شده بر اساس {column} نزولی", - thenBy: "، سپس بر اساس ", - toggleDensity: "تغییر تراکم", - toggleFullScreen: "تغییر حالت تمام صفحه", - toggleSelectAll: "انتخاب/عدم انتخاب همه", - toggleSelectRow: "انتخاب/عدم انتخاب ردیف", - toggleVisibility: "تغییر پیدا/پنهان", - ungroupByColumn: "لغو گروه بندی بر اساس {column}", - unpin: "رها کردن", - unpinAll: "رها کردن همه", - unsorted: "بدون مرتب سازی", + actions: "عملیات", + and: "و", + cancel: "لغو", + changeFilterMode: "تغییر حالت فیلتر", + changeSearchMode: "تغییر حالت جستجو", + clearFilter: "پاک کردن فیلتر", + clearSearch: "پاک کردن جستجو", + clearSort: "پاک کردن مرتب سازی", + clickToCopy: "کلیک برای کپی", + collapse: "جمع شدن", + collapseAll: "جمع شدن همه", + columnActions: "عملیات ستون", + copiedToClipboard: "کپی شد", + dropToGroupBy: "رها کردن برای گروه بندی بر اساس {column}", + edit: "ویرایش", + expand: "باز شدن", + expandAll: "باز شدن همه", + filterArrIncludes: "شامل", + filterArrIncludesAll: "شامل همه", + filterArrIncludesSome: "شامل", + filterBetween: "میان", + filterBetweenInclusive: "میان با احتساب هر دو", + filterByColumn: "فیلتر بر اساس {column}", + filterContains: "شامل", + filterEmpty: "خالی", + filterEndsWith: "به پایان می‌رسد با", + filterEquals: "برابر", + filterEqualsString: "برابر", + filterFuzzy: "نزدیک", + filterGreaterThan: "بزرگتر از", + filterGreaterThanOrEqualTo: "بزرگتر یا مساوی", + filterInNumberRange: "میان", + filterIncludesString: "شامل", + filterIncludesStringSensitive: "شامل", + filterLessThan: "کوچکتر از", + filterLessThanOrEqualTo: "کوچکتر یا مساوی", + filterMode: "حالت فیلتر: {filterType}", + filterNotEmpty: "غیر خالی", + filterNotEquals: "نا برابر", + filterStartsWith: "شروع می‌شود با", + filterWeakEquals: "برابر", + filteringByColumn: "فیلتر بر اساس {column} - {filterType} {filterValue}", + goToFirstPage: "رفتن به صفحه اول", + goToLastPage: "رفتن به صفحه آخر", + goToNextPage: "رفتن به صفحه بعدی", + goToPreviousPage: "رفتن به صفحه قبلی", + grab: "گرفتن", + groupByColumn: "گروه بندی بر اساس {column}", + groupedBy: "گروه بندی شده بر اساس", + hideAll: "پنهان کردن همه", + hideColumn: "پنهان کردن ستون {column}", + max: "حداکثر", + min: "حداقل", + move: "انتقال", + noRecordsToDisplay: "هیچ رکوردی برای نمایش وجود ندارد", + noResultsFound: "نتیجه‌ای یافت نشد", + of: "از", + or: "یا", + pinToLeft: "چسباندن به سمت چپ", + pinToRight: "چسباندن به سمت راست", + resetColumnSize: "بازنشانی اندازه ستون", + resetOrder: "بازنشانی ترتیب", + rowActions: "عملیات ردیف", + rowNumber: "#", + rowNumbers: "شماره ردیف", + rowsPerPage: "ردیف در هر صفحه", + save: "ذخیره", + search: "جستجو", + selectedCountOfRowCountRowsSelected: "{selectedCount} از {rowCount} ردیف انتخاب شده", + select: "انتخاب", + showAll: "نمایش همه", + showAllColumns: "نمایش همه ستون‌ها", + showHideColumns: "نمایش/مخفی کردن ستون‌ها", + showHideFilters: "نمایش/مخفی کردن فیلترها", + showHideSearch: "نمایش/مخفی کردن جستجو", + sortByColumnAsc: "مرتب سازی بر اساس {column} صعودی", + sortByColumnDesc: "مرتب سازی بر اساس {column} نزولی", + sortedByColumnAsc: "مرتب شده بر اساس {column} صعودی", + sortedByColumnDesc: "مرتب شده بر اساس {column} نزولی", + thenBy: "، سپس بر اساس ", + toggleDensity: "تغییر تراکم", + toggleFullScreen: "تغییر حالت تمام صفحه", + toggleSelectAll: "انتخاب/عدم انتخاب همه", + toggleSelectRow: "انتخاب/عدم انتخاب ردیف", + toggleVisibility: "تغییر پیدا/پنهان", + ungroupByColumn: "لغو گروه بندی بر اساس {column}", + unpin: "رها کردن", + unpinAll: "رها کردن همه", + unsorted: "بدون مرتب سازی", }; diff --git a/src/core/components/DataTable/menus/ActionMenuItem.js b/src/core/components/DataTable/menus/ActionMenuItem.js index a7a03b3..012fcc5 100644 --- a/src/core/components/DataTable/menus/ActionMenuItem.js +++ b/src/core/components/DataTable/menus/ActionMenuItem.js @@ -1,49 +1,38 @@ import { Box, IconButton, ListItemIcon, MenuItem } from "@mui/material"; -const DataTable_ActionMenuItem = ({ - icon, - label, - onOpenSubMenu, - table, - ...rest -}) => { - const { - options: { - icons: { ArrowRightIcon }, - }, - } = table; +const DataTable_ActionMenuItem = ({ icon, label, onOpenSubMenu, table, ...rest }) => { + const { + options: { + icons: { ArrowRightIcon }, + }, + } = table; - return ( - - - {icon} - {label} - - {onOpenSubMenu && ( - - - - )} - - ); + + {icon} + {label} + + {onOpenSubMenu && ( + + + + )} + + ); }; export default DataTable_ActionMenuItem; diff --git a/src/core/components/DataTable/menus/CellActionMenu.js b/src/core/components/DataTable/menus/CellActionMenu.js index 12256ab..5b27ca9 100644 --- a/src/core/components/DataTable/menus/CellActionMenu.js +++ b/src/core/components/DataTable/menus/CellActionMenu.js @@ -3,94 +3,92 @@ import { Menu } from "@mui/material"; import DataTable_ActionMenuItem from "./ActionMenuItem"; const DataTable_CellActionMenu = ({ table, ...rest }) => { - const { - getState, - options: { - editDisplayMode, - enableClickToCopy, - enableEditing, - icons: { ContentCopy, EditIcon }, - localization, - mrtTheme: { menuBackgroundColor }, - renderCellActionMenuItems, - }, - refs: { actionCellRef }, - } = table; - const { actionCell, density } = getState(); - const cell = actionCell || null; - const { row } = cell; - const { column } = cell; - const { columnDef } = column; + const { + getState, + options: { + editDisplayMode, + enableClickToCopy, + enableEditing, + icons: { ContentCopy, EditIcon }, + localization, + mrtTheme: { menuBackgroundColor }, + renderCellActionMenuItems, + }, + refs: { actionCellRef }, + } = table; + const { actionCell, density } = getState(); + const cell = actionCell || null; + const { row } = cell; + const { column } = cell; + const { columnDef } = column; - const handleClose = (event) => { - event?.stopPropagation(); - table.setActionCell(null); - actionCellRef.current = null; - }; + const handleClose = (event) => { + event?.stopPropagation(); + table.setActionCell(null); + actionCellRef.current = null; + }; - const internalMenuItems = [ - (parseFromValuesOrFunc(enableClickToCopy, cell) === "context-menu" || - parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === - "context-menu") && ( - } - key={"mrt-copy"} - label={localization.copy} - onClick={(event) => { - event.stopPropagation(); - navigator.clipboard.writeText(cell.getValue()); - handleClose(); - }} - table={table} - /> - ), - parseFromValuesOrFunc(enableEditing, row) && editDisplayMode === "cell" && ( - } - key={"mrt-edit"} - label={localization.edit} - onClick={() => { - openEditingCell({ cell, table }); - handleClose(); - }} - table={table} - /> - ), - ].filter(Boolean); + const internalMenuItems = [ + (parseFromValuesOrFunc(enableClickToCopy, cell) === "context-menu" || + parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === "context-menu") && ( + } + key={"mrt-copy"} + label={localization.copy} + onClick={(event) => { + event.stopPropagation(); + navigator.clipboard.writeText(cell.getValue()); + handleClose(); + }} + table={table} + /> + ), + parseFromValuesOrFunc(enableEditing, row) && editDisplayMode === "cell" && ( + } + key={"mrt-edit"} + label={localization.edit} + onClick={() => { + openEditingCell({ cell, table }); + handleClose(); + }} + table={table} + /> + ), + ].filter(Boolean); - const renderActionProps = { - cell, - closeMenu: handleClose, - column, - internalMenuItems, - row, - table, - }; + const renderActionProps = { + cell, + closeMenu: handleClose, + column, + internalMenuItems, + row, + table, + }; - const menuItems = - columnDef.renderCellActionMenuItems?.(renderActionProps) ?? - renderCellActionMenuItems?.(renderActionProps); + const menuItems = + columnDef.renderCellActionMenuItems?.(renderActionProps) ?? renderCellActionMenuItems?.(renderActionProps); - return ( - (!!menuItems?.length || !!internalMenuItems?.length) && ( - event.stopPropagation()} - onClose={handleClose} - open={!!cell} - transformOrigin={{ horizontal: -100, vertical: 8 }} - {...rest} - > - {menuItems ?? internalMenuItems} - - ) - ); + return ( + (!!menuItems?.length || !!internalMenuItems?.length) && ( + event.stopPropagation()} + onClose={handleClose} + open={!!cell} + transformOrigin={{ horizontal: -100, vertical: 8 }} + {...rest} + > + {menuItems ?? internalMenuItems} + + ) + ); }; export default DataTable_CellActionMenu; diff --git a/src/core/components/DataTable/reset/ResetStorage.jsx b/src/core/components/DataTable/reset/ResetStorage.jsx index 76edf58..7994867 100644 --- a/src/core/components/DataTable/reset/ResetStorage.jsx +++ b/src/core/components/DataTable/reset/ResetStorage.jsx @@ -5,32 +5,32 @@ import useTableSetting from "@/lib/hooks/useTableSetting"; import useDataTable from "@/lib/hooks/useDataTable"; function ResetStorage({ user_id, page_name, table_name }) { - const { resetAction } = useTableSetting(); - const { isAnyDirty } = useDataTable(); - const reset = () => { - resetAction(user_id, page_name, table_name); - }; + const { resetAction } = useTableSetting(); + const { isAnyDirty } = useDataTable(); + const reset = () => { + resetAction(user_id, page_name, table_name); + }; - return ( - - - {isAnyDirty ? ( - - - - ) : ( - - )} - - - ); + return ( + + + {isAnyDirty ? ( + + + + ) : ( + + )} + + + ); } export default ResetStorage; diff --git a/src/core/components/DataTable/table/Paper.js b/src/core/components/DataTable/table/Paper.js index cdca182..9ce08fc 100644 --- a/src/core/components/DataTable/table/Paper.js +++ b/src/core/components/DataTable/table/Paper.js @@ -5,98 +5,96 @@ import DataTable_TopToolbar from "../toolbar/TopToolbar"; import DataTable_TableContainer from "./TableContainer"; const DataTable_Paper = ({ - table, - table_name, - columns, - user_id, - page_name, - mutate, - need_filter, - table_url, - table_title, - setFilterData, - ...rest + table, + table_name, + columns, + user_id, + page_name, + mutate, + need_filter, + table_url, + table_title, + setFilterData, + ...rest }) => { - const { - getState, - options: { - enableBottomToolbar, - enableTopToolbar, - mrtTheme: { baseBackgroundColor }, - muiTablePaperProps, - renderBottomToolbar, - renderTopToolbar, - }, - refs: { tablePaperRef }, - } = table; + const { + getState, + options: { + enableBottomToolbar, + enableTopToolbar, + mrtTheme: { baseBackgroundColor }, + muiTablePaperProps, + renderBottomToolbar, + renderTopToolbar, + }, + refs: { tablePaperRef }, + } = table; - const { isFullScreen } = getState(); + const { isFullScreen } = getState(); - const paperProps = { - ...parseFromValuesOrFunc(muiTablePaperProps, { table }), - ...rest, - }; + const paperProps = { + ...parseFromValuesOrFunc(muiTablePaperProps, { table }), + ...rest, + }; - return ( - { - tablePaperRef.current = ref; - if (paperProps?.ref) { - //@ts-ignore - paperProps.ref.current = ref; - } - }} - style={{ - ...(isFullScreen - ? { - bottom: 0, - height: "100dvh", - left: 0, - margin: 0, - maxHeight: "100dvh", - maxWidth: "100dvw", - padding: 0, - position: "fixed", - right: 0, - top: 0, - width: "100dvw", - zIndex: 999, - } - : {}), - ...paperProps?.style, - }} - sx={(theme) => ({ - backgroundColor: baseBackgroundColor, - backgroundImage: "unset", - overflow: "hidden", - transition: "all 100ms ease-in-out", - ...parseFromValuesOrFunc(paperProps?.sx, theme), - })} - > - {enableTopToolbar && - (parseFromValuesOrFunc(renderTopToolbar, { table }) ?? ( - - ))} - - {enableBottomToolbar && - (parseFromValuesOrFunc(renderBottomToolbar, { table }) ?? ( - - ))} - - ); + ref={(ref) => { + tablePaperRef.current = ref; + if (paperProps?.ref) { + //@ts-ignore + paperProps.ref.current = ref; + } + }} + style={{ + ...(isFullScreen + ? { + bottom: 0, + height: "100dvh", + left: 0, + margin: 0, + maxHeight: "100dvh", + maxWidth: "100dvw", + padding: 0, + position: "fixed", + right: 0, + top: 0, + width: "100dvw", + zIndex: 999, + } + : {}), + ...paperProps?.style, + }} + sx={(theme) => ({ + backgroundColor: baseBackgroundColor, + backgroundImage: "unset", + overflow: "hidden", + transition: "all 100ms ease-in-out", + ...parseFromValuesOrFunc(paperProps?.sx, theme), + })} + > + {enableTopToolbar && + (parseFromValuesOrFunc(renderTopToolbar, { table }) ?? ( + + ))} + + {enableBottomToolbar && + (parseFromValuesOrFunc(renderBottomToolbar, { table }) ?? )} + + ); }; export default DataTable_Paper; diff --git a/src/core/components/DataTable/table/Table.js b/src/core/components/DataTable/table/Table.js index cfcb591..1bf6b69 100644 --- a/src/core/components/DataTable/table/Table.js +++ b/src/core/components/DataTable/table/Table.js @@ -2,75 +2,72 @@ import { parseCSSVarId, parseFromValuesOrFunc } from "@/core/utils/utils"; import { Table } from "@mui/material"; import { useMRT_ColumnVirtualizer } from "material-react-table"; import { useMemo } from "react"; -import DataTable_TableBody, { - Memo_DataTable_TableBody, -} from "../body/TableBody"; +import DataTable_TableBody, { Memo_DataTable_TableBody } from "../body/TableBody"; import DataTable_TableHead from "../head/TableHead"; const DataTable_Table = ({ table, ...rest }) => { - const { - getFlatHeaders, - getState, - options: { - columns, - enableStickyHeader, - enableTableFooter, - enableTableHead, - layoutMode, - memoMode, - muiTableProps, - renderCaption, - }, - } = table; - const { columnSizing, columnSizingInfo, columnVisibility, isFullScreen } = - getState(); + const { + getFlatHeaders, + getState, + options: { + columns, + enableStickyHeader, + enableTableFooter, + enableTableHead, + layoutMode, + memoMode, + muiTableProps, + renderCaption, + }, + } = table; + const { columnSizing, columnSizingInfo, columnVisibility, isFullScreen } = getState(); - const tableProps = { - ...parseFromValuesOrFunc(muiTableProps, { table }), - ...rest, - }; + const tableProps = { + ...parseFromValuesOrFunc(muiTableProps, { table }), + ...rest, + }; - const Caption = parseFromValuesOrFunc(renderCaption, { table }); + const Caption = parseFromValuesOrFunc(renderCaption, { table }); - const columnSizeVars = useMemo(() => { - const headers = getFlatHeaders(); - const colSizes = {}; - for (let i = 0; i < headers.length; i++) { - const header = headers[i]; - const colSize = header.getSize(); - colSizes[`--header-${parseCSSVarId(header.id)}-size`] = colSize; - colSizes[`--col-${parseCSSVarId(header.column.id)}-size`] = colSize; - } - return colSizes; - }, [columns, columnSizing, columnSizingInfo, columnVisibility]); + const columnSizeVars = useMemo(() => { + const headers = getFlatHeaders(); + const colSizes = {}; + for (let i = 0; i < headers.length; i++) { + const header = headers[i]; + const colSize = header.getSize(); + colSizes[`--header-${parseCSSVarId(header.id)}-size`] = colSize; + colSizes[`--col-${parseCSSVarId(header.column.id)}-size`] = colSize; + } + return colSizes; + }, [columns, columnSizing, columnSizingInfo, columnVisibility]); - const columnVirtualizer = useMRT_ColumnVirtualizer(table); + const columnVirtualizer = useMRT_ColumnVirtualizer(table); - const commonTableGroupProps = { - columnVirtualizer, - table, - }; + const commonTableGroupProps = { + columnVirtualizer, + table, + }; - return ( - ({ - display: layoutMode?.startsWith("grid") ? "grid" : undefined, - position: "relative", - ...parseFromValuesOrFunc(tableProps?.sx, theme), - })} - > - {!!Caption && } - {enableTableHead && } - {memoMode === "table-body" || columnSizingInfo.isResizingColumn ? ( - - ) : ( - - )} - {/* {enableTableFooter && } */} -
{Caption}
- ); + return ( + ({ + display: layoutMode?.startsWith("grid") ? "grid" : undefined, + position: "relative", + ...parseFromValuesOrFunc(tableProps?.sx, theme), + })} + > + {!!Caption && } + {enableTableHead && } + {memoMode === "table-body" || columnSizingInfo.isResizingColumn ? ( + + ) : ( + + )} + {/* {enableTableFooter && } */} +
{Caption}
+ ); }; export default DataTable_Table; diff --git a/src/core/components/DataTable/table/TableContainer.js b/src/core/components/DataTable/table/TableContainer.js index 67ee485..3e1320e 100644 --- a/src/core/components/DataTable/table/TableContainer.js +++ b/src/core/components/DataTable/table/TableContainer.js @@ -5,80 +5,68 @@ import DataTable_CellActionMenu from "../menus/CellActionMenu"; import DataTable_Table from "./Table"; import DataTable_TableLoadingOverlay from "./TableLoadingOverlay"; -const useIsomorphicLayoutEffect = - typeof window !== "undefined" ? useLayoutEffect : useEffect; +const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect; const DataTable_TableContainer = ({ table, ...rest }) => { - const { - getState, - options: { enableCellActions, enableStickyHeader, muiTableContainerProps }, - refs: { bottomToolbarRef, tableContainerRef, topToolbarRef }, - } = table; - const { actionCell, isFullScreen, isLoading, showLoadingOverlay } = - getState(); + const { + getState, + options: { enableCellActions, enableStickyHeader, muiTableContainerProps }, + refs: { bottomToolbarRef, tableContainerRef, topToolbarRef }, + } = table; + const { actionCell, isFullScreen, isLoading, showLoadingOverlay } = getState(); - const loading = - showLoadingOverlay !== false && (isLoading || showLoadingOverlay); + const loading = showLoadingOverlay !== false && (isLoading || showLoadingOverlay); - const [totalToolbarHeight, setTotalToolbarHeight] = useState(0); + const [totalToolbarHeight, setTotalToolbarHeight] = useState(0); - const tableContainerProps = { - ...parseFromValuesOrFunc(muiTableContainerProps, { - table, - }), - ...rest, - }; + const tableContainerProps = { + ...parseFromValuesOrFunc(muiTableContainerProps, { + table, + }), + ...rest, + }; - useIsomorphicLayoutEffect(() => { - const topToolbarHeight = - typeof document !== "undefined" - ? (topToolbarRef.current?.offsetHeight ?? 0) - : 0; + useIsomorphicLayoutEffect(() => { + const topToolbarHeight = typeof document !== "undefined" ? (topToolbarRef.current?.offsetHeight ?? 0) : 0; - const bottomToolbarHeight = - typeof document !== "undefined" - ? (bottomToolbarRef?.current?.offsetHeight ?? 0) - : 0; + const bottomToolbarHeight = + typeof document !== "undefined" ? (bottomToolbarRef?.current?.offsetHeight ?? 0) : 0; - setTotalToolbarHeight(topToolbarHeight + bottomToolbarHeight); - }); + setTotalToolbarHeight(topToolbarHeight + bottomToolbarHeight); + }); - return ( - { - if (node) { - tableContainerRef.current = node; - if (tableContainerProps?.ref) { - //@ts-ignore - tableContainerProps.ref.current = node; - } - } - }} - style={{ - maxHeight: isFullScreen - ? `calc(100vh - ${totalToolbarHeight}px)` - : undefined, - ...tableContainerProps?.style, - }} - sx={(theme) => ({ - maxHeight: enableStickyHeader - ? `clamp(350px, calc(100vh - ${totalToolbarHeight}px), 9999px)` - : undefined, - maxWidth: "100%", - overflow: "auto", - position: "relative", - ...parseFromValuesOrFunc(tableContainerProps?.sx, theme), - })} - > - {loading ? : null} - - {enableCellActions && actionCell && ( - - )} - - ); + return ( + { + if (node) { + tableContainerRef.current = node; + if (tableContainerProps?.ref) { + //@ts-ignore + tableContainerProps.ref.current = node; + } + } + }} + style={{ + maxHeight: isFullScreen ? `calc(100vh - ${totalToolbarHeight}px)` : undefined, + ...tableContainerProps?.style, + }} + sx={(theme) => ({ + maxHeight: enableStickyHeader + ? `clamp(350px, calc(100vh - ${totalToolbarHeight}px), 9999px)` + : undefined, + maxWidth: "100%", + overflow: "auto", + position: "relative", + ...parseFromValuesOrFunc(tableContainerProps?.sx, theme), + })} + > + {loading ? : null} + + {enableCellActions && actionCell && } + + ); }; export default DataTable_TableContainer; diff --git a/src/core/components/DataTable/table/TableLoadingOverlay.js b/src/core/components/DataTable/table/TableLoadingOverlay.js index 946fff7..0c417dd 100644 --- a/src/core/components/DataTable/table/TableLoadingOverlay.js +++ b/src/core/components/DataTable/table/TableLoadingOverlay.js @@ -1,44 +1,44 @@ import { Box, CircularProgress } from "@mui/material"; const DataTable_TableLoadingOverlay = ({ table, ...rest }) => { - const { - options: { - localization, - mrtTheme: { baseBackgroundColor }, - muiCircularProgressProps, - }, - } = table; + const { + options: { + localization, + mrtTheme: { baseBackgroundColor }, + muiCircularProgressProps, + }, + } = table; - const circularProgressProps = { - ...parseFromValuesOrFunc(muiCircularProgressProps, { table }), - ...rest, - }; + const circularProgressProps = { + ...parseFromValuesOrFunc(muiCircularProgressProps, { table }), + ...rest, + }; - return ( - - {circularProgressProps?.Component ?? ( - - )} - - ); + return ( + + {circularProgressProps?.Component ?? ( + + )} + + ); }; export default DataTable_TableLoadingOverlay; diff --git a/src/core/components/DataTable/toolbar/BottomToolbar.js b/src/core/components/DataTable/toolbar/BottomToolbar.js index 809a390..ced2c06 100644 --- a/src/core/components/DataTable/toolbar/BottomToolbar.js +++ b/src/core/components/DataTable/toolbar/BottomToolbar.js @@ -1,85 +1,72 @@ -import { - getCommonToolbarStyles, - parseFromValuesOrFunc, -} from "@/core/utils/utils"; +import { getCommonToolbarStyles, parseFromValuesOrFunc } from "@/core/utils/utils"; import { Box, alpha, useMediaQuery } from "@mui/material"; import DataTable_LinearProgressBar from "./LinearProgressBar"; import DataTable_TablePagination from "./TablePagination"; const DataTable_BottomToolbar = ({ table, ...rest }) => { - const { - getState, - options: { - enablePagination, - muiBottomToolbarProps, - positionPagination, - renderBottomToolbarCustomActions, - }, - refs: { bottomToolbarRef }, - } = table; - const { isFullScreen } = getState(); + const { + getState, + options: { enablePagination, muiBottomToolbarProps, positionPagination, renderBottomToolbarCustomActions }, + refs: { bottomToolbarRef }, + } = table; + const { isFullScreen } = getState(); - const isMobile = useMediaQuery("(max-width:720px)"); - const toolbarProps = { - ...parseFromValuesOrFunc(muiBottomToolbarProps, { table }), - ...rest, - }; + const isMobile = useMediaQuery("(max-width:720px)"); + const toolbarProps = { + ...parseFromValuesOrFunc(muiBottomToolbarProps, { table }), + ...rest, + }; - const stackAlertBanner = isMobile || !!renderBottomToolbarCustomActions; - return ( - { - if (node) { - bottomToolbarRef.current = node; - if (toolbarProps?.ref) { - // @ts-ignore - toolbarProps.ref.current = node; - } - } - }} - sx={(theme) => ({ - ...getCommonToolbarStyles({ table, theme }), - bottom: isFullScreen ? "0" : undefined, - boxShadow: `0 1px 2px -1px ${alpha(theme.palette.grey[700], 0.5)} inset`, - left: 0, - position: isFullScreen ? "fixed" : "relative", - right: 0, - ...parseFromValuesOrFunc(toolbarProps?.sx, theme), - })} - > - - - {renderBottomToolbarCustomActions ? ( - renderBottomToolbarCustomActions({ table }) - ) : ( - - )} + const stackAlertBanner = isMobile || !!renderBottomToolbarCustomActions; + return ( { + if (node) { + bottomToolbarRef.current = node; + if (toolbarProps?.ref) { + // @ts-ignore + toolbarProps.ref.current = node; + } + } + }} + sx={(theme) => ({ + ...getCommonToolbarStyles({ table, theme }), + bottom: isFullScreen ? "0" : undefined, + boxShadow: `0 1px 2px -1px ${alpha(theme.palette.grey[700], 0.5)} inset`, + left: 0, + position: isFullScreen ? "fixed" : "relative", + right: 0, + ...parseFromValuesOrFunc(toolbarProps?.sx, theme), + })} > - {enablePagination && - ["both", "bottom"].includes(positionPagination ?? "") && ( - - )} + + + {renderBottomToolbarCustomActions ? renderBottomToolbarCustomActions({ table }) : } + + {enablePagination && ["both", "bottom"].includes(positionPagination ?? "") && ( + + )} + + - - - ); + ); }; export default DataTable_BottomToolbar; diff --git a/src/core/components/DataTable/toolbar/LinearProgressBar.js b/src/core/components/DataTable/toolbar/LinearProgressBar.js index 9c40fc7..74c465f 100644 --- a/src/core/components/DataTable/toolbar/LinearProgressBar.js +++ b/src/core/components/DataTable/toolbar/LinearProgressBar.js @@ -2,39 +2,39 @@ import { parseFromValuesOrFunc } from "@/core/utils/utils"; import { Collapse, LinearProgress } from "@mui/material"; const DataTable_LinearProgressBar = ({ isTopToolbar, table, ...rest }) => { - const { - getState, - options: { muiLinearProgressProps }, - } = table; - const { isSaving, showProgressBars } = getState(); + const { + getState, + options: { muiLinearProgressProps }, + } = table; + const { isSaving, showProgressBars } = getState(); - const linearProgressProps = { - ...parseFromValuesOrFunc(muiLinearProgressProps, { - isTopToolbar, - table, - }), - ...rest, - }; + const linearProgressProps = { + ...parseFromValuesOrFunc(muiLinearProgressProps, { + isTopToolbar, + table, + }), + ...rest, + }; - return ( - - - - ); + return ( + + + + ); }; export default DataTable_LinearProgressBar; diff --git a/src/core/components/DataTable/toolbar/TablePagination.js b/src/core/components/DataTable/toolbar/TablePagination.js index 7942a3a..6492b41 100644 --- a/src/core/components/DataTable/toolbar/TablePagination.js +++ b/src/core/components/DataTable/toolbar/TablePagination.js @@ -1,228 +1,218 @@ -import { - flipIconStyles, - getCommonTooltipProps, - parseFromValuesOrFunc, -} from "@/core/utils/utils"; +import { flipIconStyles, getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils"; import { useTheme } from "@emotion/react"; import { - Box, - IconButton, - InputLabel, - MenuItem, - Pagination, - PaginationItem, - Select, - Tooltip, - Typography, - useMediaQuery, + Box, + IconButton, + InputLabel, + MenuItem, + Pagination, + PaginationItem, + Select, + Tooltip, + Typography, + useMediaQuery, } from "@mui/material"; const defaultRowsPerPage = [5, 10, 15, 20, 25, 30, 50, 100]; const DataTable_TablePagination = ({ position = "bottom", table, ...rest }) => { - const theme = useTheme(); - const isMobile = useMediaQuery("(max-width: 720px)"); + const theme = useTheme(); + const isMobile = useMediaQuery("(max-width: 720px)"); - const { - getState, - options: { - enableToolbarInternalActions, - icons: { ChevronLeftIcon, ChevronRightIcon, FirstPageIcon, LastPageIcon }, - localization, - muiPaginationProps, - paginationDisplayMode, - }, - } = table; + const { + getState, + options: { + enableToolbarInternalActions, + icons: { ChevronLeftIcon, ChevronRightIcon, FirstPageIcon, LastPageIcon }, + localization, + muiPaginationProps, + paginationDisplayMode, + }, + } = table; - const { - pagination: { pageIndex = 0, pageSize = 10 }, - showGlobalFilter, - } = getState(); + const { + pagination: { pageIndex = 0, pageSize = 10 }, + showGlobalFilter, + } = getState(); - const paginationProps = { - ...parseFromValuesOrFunc(muiPaginationProps, { - table, - }), - ...rest, - }; + const paginationProps = { + ...parseFromValuesOrFunc(muiPaginationProps, { + table, + }), + ...rest, + }; - const totalRowCount = table.getRowCount(); - const numberOfPages = table.getPageCount(); - const showFirstLastPageButtons = numberOfPages > 2; - const firstRowIndex = pageIndex * pageSize; - const lastRowIndex = Math.min(pageIndex * pageSize + pageSize, totalRowCount); + const totalRowCount = table.getRowCount(); + const numberOfPages = table.getPageCount(); + const showFirstLastPageButtons = numberOfPages > 2; + const firstRowIndex = pageIndex * pageSize; + const lastRowIndex = Math.min(pageIndex * pageSize + pageSize, totalRowCount); - const { - SelectProps = {}, - disabled = false, - rowsPerPageOptions = defaultRowsPerPage, - showFirstButton = showFirstLastPageButtons, - showLastButton = showFirstLastPageButtons, - showRowsPerPage = true, - ...restPaginationProps - } = paginationProps ?? {}; + const { + SelectProps = {}, + disabled = false, + rowsPerPageOptions = defaultRowsPerPage, + showFirstButton = showFirstLastPageButtons, + showLastButton = showFirstLastPageButtons, + showRowsPerPage = true, + ...restPaginationProps + } = paginationProps ?? {}; - const disableBack = pageIndex <= 0 || disabled; - const disableNext = lastRowIndex >= totalRowCount || disabled; + const disableBack = pageIndex <= 0 || disabled; + const disableNext = lastRowIndex >= totalRowCount || disabled; - if (isMobile && SelectProps?.native !== false) { - SelectProps.native = true; - } + if (isMobile && SelectProps?.native !== false) { + SelectProps.native = true; + } - const tooltipProps = getCommonTooltipProps(); + const tooltipProps = getCommonTooltipProps(); - return ( - - {showRowsPerPage && ( - - - {localization.rowsPerPage} - - + > + {showRowsPerPage && ( + + + {localization.rowsPerPage} + + + + )} + {paginationDisplayMode === "pages" ? ( + table.setPageIndex(newPageIndex - 1)} + page={pageIndex + 1} + renderItem={(item) => ( + + )} + showFirstButton={showFirstButton} + showLastButton={showLastButton} + {...restPaginationProps} + /> + ) : paginationDisplayMode === "default" ? ( + <> + {`${ + lastRowIndex === 0 ? 0 : (firstRowIndex + 1).toLocaleString() + }-${lastRowIndex.toLocaleString()} ${ + localization.of + } ${totalRowCount.toLocaleString()}`} + + {showFirstButton && ( + + + table.firstPage()} + size="small" + > + + + + + )} + + + table.previousPage()} + size="small" + > + + + + + + + table.nextPage()} + size="small" + > + + + + + {showLastButton && ( + + + table.lastPage()} + size="small" + > + + + + + )} + + + ) : null} - )} - {paginationDisplayMode === "pages" ? ( - table.setPageIndex(newPageIndex - 1)} - page={pageIndex + 1} - renderItem={(item) => ( - - )} - showFirstButton={showFirstButton} - showLastButton={showLastButton} - {...restPaginationProps} - /> - ) : paginationDisplayMode === "default" ? ( - <> - {`${ - lastRowIndex === 0 ? 0 : (firstRowIndex + 1).toLocaleString() - }-${lastRowIndex.toLocaleString()} ${ - localization.of - } ${totalRowCount.toLocaleString()}`} - - {showFirstButton && ( - - - table.firstPage()} - size="small" - > - - - - - )} - - - table.previousPage()} - size="small" - > - - - - - - - table.nextPage()} - size="small" - > - - - - - {showLastButton && ( - - - table.lastPage()} - size="small" - > - - - - - )} - - - ) : null} - - ); + ); }; export default DataTable_TablePagination; diff --git a/src/core/components/DataTable/toolbar/TopToolbar.js b/src/core/components/DataTable/toolbar/TopToolbar.js index a1c0aeb..6a34164 100644 --- a/src/core/components/DataTable/toolbar/TopToolbar.js +++ b/src/core/components/DataTable/toolbar/TopToolbar.js @@ -1,7 +1,4 @@ -import { - getCommonToolbarStyles, - parseFromValuesOrFunc, -} from "@/core/utils/utils"; +import { getCommonToolbarStyles, parseFromValuesOrFunc } from "@/core/utils/utils"; import { Box, Typography, useMediaQuery } from "@mui/material"; import DataTable_LinearProgressBar from "./LinearProgressBar"; import DataTable_TablePagination from "./TablePagination"; @@ -12,145 +9,134 @@ import HideColumn from "@/core/components/DataTable/hide"; import FilterCustom from "../filter/FilterCustom"; const DataTable_TopToolbar = ({ - mutate, - need_filter, - table, - columns, - table_url, - user_id, - page_name, - table_name, - table_title, - special_data, - special_filter, - setFilterData, + mutate, + need_filter, + table, + columns, + table_url, + user_id, + page_name, + table_name, + table_title, + special_data, + special_filter, + setFilterData, }) => { - const { - getState, - options: { - enablePagination, - enableToolbarInternalActions, - muiTopToolbarProps, - positionPagination, - renderTopToolbarCustomActions, - }, - refs: { topToolbarRef }, - } = table; - const { isFullScreen, showGlobalFilter } = getState(); + const { + getState, + options: { + enablePagination, + enableToolbarInternalActions, + muiTopToolbarProps, + positionPagination, + renderTopToolbarCustomActions, + }, + refs: { topToolbarRef }, + } = table; + const { isFullScreen, showGlobalFilter } = getState(); - const isMobile = useMediaQuery("(max-width:720px)"); - const isTablet = useMediaQuery("(max-width:1024px)"); + const isMobile = useMediaQuery("(max-width:720px)"); + const isTablet = useMediaQuery("(max-width:1024px)"); - const toolbarProps = parseFromValuesOrFunc(muiTopToolbarProps, { table }); + const toolbarProps = parseFromValuesOrFunc(muiTopToolbarProps, { table }); - const stackAlertBanner = - isMobile || - !!renderTopToolbarCustomActions || - (showGlobalFilter && isTablet); + const stackAlertBanner = isMobile || !!renderTopToolbarCustomActions || (showGlobalFilter && isTablet); - return ( - { - topToolbarRef.current = ref; - if (toolbarProps?.ref) { - // @ts-ignore - toolbarProps.ref.current = ref; - } - }} - sx={(theme) => ({ - ...getCommonToolbarStyles({ table, theme }), - position: isFullScreen ? "sticky" : "relative", - top: isFullScreen ? "0" : undefined, - ...parseFromValuesOrFunc(toolbarProps?.sx, theme), - })} - > - + return ( - {renderTopToolbarCustomActions?.({ table })} - - - {table_title || ""} - - {enableToolbarInternalActions && ( - { + topToolbarRef.current = ref; + if (toolbarProps?.ref) { + // @ts-ignore + toolbarProps.ref.current = ref; + } }} - > - {!special_data && ( - <> - - - + sx={(theme) => ({ + ...getCommonToolbarStyles({ table, theme }), + position: isFullScreen ? "sticky" : "relative", + top: isFullScreen ? "0" : undefined, + ...parseFromValuesOrFunc(toolbarProps?.sx, theme), + })} + > + + + {renderTopToolbarCustomActions?.({ table })} + + + {table_title || ""} + + {enableToolbarInternalActions && ( + + {!special_data && ( + <> + + + + )} + + {need_filter && ( + + )} + {special_filter && setFilterData && ( + + )} + + )} + + {enablePagination && ["both", "top"].includes(positionPagination ?? "") && ( + )} - - {need_filter && ( - - )} - {special_filter && setFilterData && ( - - )} - - )} - - {enablePagination && - ["both", "top"].includes(positionPagination ?? "") && ( - - )} - - - ); + + + ); }; export default DataTable_TopToolbar; diff --git a/src/core/components/DataTable/update/UpdateTable.jsx b/src/core/components/DataTable/update/UpdateTable.jsx index 93b54b7..8a60c8d 100644 --- a/src/core/components/DataTable/update/UpdateTable.jsx +++ b/src/core/components/DataTable/update/UpdateTable.jsx @@ -3,17 +3,17 @@ import { IconButton, Tooltip } from "@mui/material"; import RestartAltIcon from "@mui/icons-material/RestartAlt"; function UpdateTable({ mutate }) { - const update = () => { - mutate(); - }; + const update = () => { + mutate(); + }; - return ( - - - - - - ); + return ( + + + + + + ); } export default UpdateTable; diff --git a/src/core/components/DataTableWithAuth.jsx b/src/core/components/DataTableWithAuth.jsx index 2ef70ab..3363495 100644 --- a/src/core/components/DataTableWithAuth.jsx +++ b/src/core/components/DataTableWithAuth.jsx @@ -2,7 +2,7 @@ import DataTable from "@/core/components/DataTable"; import { useAuth } from "@/lib/contexts/auth"; const DataTableWithAuth = (props) => { - const { user } = useAuth(); - return ; + const { user } = useAuth(); + return ; }; export default DataTableWithAuth; diff --git a/src/core/components/DialogTransition.jsx b/src/core/components/DialogTransition.jsx index de09a75..ad476e8 100644 --- a/src/core/components/DialogTransition.jsx +++ b/src/core/components/DialogTransition.jsx @@ -1,8 +1,6 @@ import { forwardRef } from "react"; import { Slide } from "@mui/material"; -export const DialogTransition = forwardRef( - function DialogTransition(props, ref) { +export const DialogTransition = forwardRef(function DialogTransition(props, ref) { return ; - }, -); +}); diff --git a/src/core/components/FilterDrawer/FilterController.jsx b/src/core/components/FilterDrawer/FilterController.jsx index b8121d2..4a6a125 100644 --- a/src/core/components/FilterDrawer/FilterController.jsx +++ b/src/core/components/FilterDrawer/FilterController.jsx @@ -2,24 +2,24 @@ import { Controller } from "react-hook-form"; import FilterField from "./FilterField"; const FilterController = ({ item, control, reset, errors }) => { - return ( - { - return ( - reset()} - errors={errors} - /> - ); - }} - /> - ); + return ( + { + return ( + reset()} + errors={errors} + /> + ); + }} + /> + ); }; export default FilterController; diff --git a/src/core/components/FilterDrawer/FilterControllerWithDependency.jsx b/src/core/components/FilterDrawer/FilterControllerWithDependency.jsx index 699d592..361941f 100644 --- a/src/core/components/FilterDrawer/FilterControllerWithDependency.jsx +++ b/src/core/components/FilterDrawer/FilterControllerWithDependency.jsx @@ -2,26 +2,26 @@ import { Controller, useWatch } from "react-hook-form"; import FilterField from "./FilterField"; const FilterControllerWithDependency = ({ item, control, reset, errors }) => { - const dependencyField = useWatch({ control, name: item.dependencyId }); + const dependencyField = useWatch({ control, name: item.dependencyId }); - return ( - { - return ( - reset()} - errors={errors} - /> - ); - }} - /> - ); + return ( + { + return ( + reset()} + errors={errors} + /> + ); + }} + /> + ); }; export default FilterControllerWithDependency; diff --git a/src/core/components/FilterDrawer/FilterField.jsx b/src/core/components/FilterDrawer/FilterField.jsx index 7210315..ed86df8 100644 --- a/src/core/components/FilterDrawer/FilterField.jsx +++ b/src/core/components/FilterDrawer/FilterField.jsx @@ -8,98 +8,96 @@ import CustomTextField from "./fieldsType/CustomTextField"; import FilterOptionList from "./FilterOptionList"; const filterModeOptionFa = { - equals: "برابر", - notEquals: "نابرابر", - contains: "شامل", - lessThan: "کوچکتر", - greaterThan: "بزرگتر", - fuzzy: "فازی", - between: "مابین", + equals: "برابر", + notEquals: "نابرابر", + contains: "شامل", + lessThan: "کوچکتر", + greaterThan: "بزرگتر", + fuzzy: "فازی", + between: "مابین", }; function FilterField({ - item, - filterParameters, - handleChange, - handleBlur, - dependencyFieldValue, - setFieldValue, - resetForm, - errors, + item, + filterParameters, + handleChange, + handleBlur, + dependencyFieldValue, + setFieldValue, + resetForm, + errors, }) { - const [anchorEl, setAnchorEl] = useState(null); - const defaultFilterTranslation = - filterModeOptionFa[filterParameters.filterMode] || - filterParameters.filterMode; + const [anchorEl, setAnchorEl] = useState(null); + const defaultFilterTranslation = filterModeOptionFa[filterParameters.filterMode] || filterParameters.filterMode; - const handleOpenFilterBox = (event) => { - setAnchorEl(event.currentTarget); - }; - - const renderField = () => { - const commonProps = { - item, - filterParameters, - defaultFilterTranslation, - handleOpenFilterBox, - dependencyFieldValue, - setFieldValue, - handleChange, - handleBlur, - errors, + const handleOpenFilterBox = (event) => { + setAnchorEl(event.currentTarget); }; - switch (filterParameters.datatype) { - case "numeric": - if (filterParameters.filterMode === "between") { - return ; - } - if (filterParameters.filterMode === "equals") { - return item.SelectComponent ? ( - - ) : ( - - ); - } - break; - case "date": - if (filterParameters.filterMode === "equals") { - return ; - } - if (filterParameters.filterMode === "between") { - return ; - } - break; + const renderField = () => { + const commonProps = { + item, + filterParameters, + defaultFilterTranslation, + handleOpenFilterBox, + dependencyFieldValue, + setFieldValue, + handleChange, + handleBlur, + errors, + }; - case "array": - if (filterParameters.filterMode === "equals") { - return ; + switch (filterParameters.datatype) { + case "numeric": + if (filterParameters.filterMode === "between") { + return ; + } + if (filterParameters.filterMode === "equals") { + return item.SelectComponent ? ( + + ) : ( + + ); + } + break; + case "date": + if (filterParameters.filterMode === "equals") { + return ; + } + if (filterParameters.filterMode === "between") { + return ; + } + break; + + case "array": + if (filterParameters.filterMode === "equals") { + return ; + } + break; + + default: + return ; } - break; + }; - default: - return ; - } - }; - - return ( - <> - {renderField()} - {Array.isArray(item.filterModeOptions) && ( - - )} - - ); + return ( + <> + {renderField()} + {Array.isArray(item.filterModeOptions) && ( + + )} + + ); } export default FilterField; diff --git a/src/core/components/FilterDrawer/FilterOptionList.jsx b/src/core/components/FilterDrawer/FilterOptionList.jsx index 19d4d0b..a8571c7 100644 --- a/src/core/components/FilterDrawer/FilterOptionList.jsx +++ b/src/core/components/FilterDrawer/FilterOptionList.jsx @@ -4,55 +4,49 @@ import { ListItem, Menu } from "@mui/material"; import { useState } from "react"; function FilterOptionList({ - filterType, - filterOption, - filterParameters, - anchorEl, - filterModeOptionFa, - setAnchorEl, - handleChange, + filterType, + filterOption, + filterParameters, + anchorEl, + filterModeOptionFa, + setAnchorEl, + handleChange, }) { - const [selectedFilter, setSelectedFilter] = useState(filterType); + const [selectedFilter, setSelectedFilter] = useState(filterType); - const handleChangeItem = (event, index) => { - handleChange({ - ...filterParameters, - value: filterOption[index] === "between" ? ["", ""] : "", - filterMode: filterOption[index], - }); - setSelectedFilter(filterOption[index]); - setAnchorEl(null); - }; + const handleChangeItem = (event, index) => { + handleChange({ + ...filterParameters, + value: filterOption[index] === "between" ? ["", ""] : "", + filterMode: filterOption[index], + }); + setSelectedFilter(filterOption[index]); + setAnchorEl(null); + }; - const handleCloseFilterBox = () => { - setAnchorEl(null); - }; + const handleCloseFilterBox = () => { + setAnchorEl(null); + }; - return ( - - {filterOption.map((option, index) => ( - handleChangeItem(event, index)} - selected={option === selectedFilter} - sx={{ - cursor: "pointer", - width: "100px", - display: "flex", - justifyContent: "center", - }} - > - {filterModeOptionFa[option]} - - ))} - - ); + return ( + + {filterOption.map((option, index) => ( + handleChangeItem(event, index)} + selected={option === selectedFilter} + sx={{ + cursor: "pointer", + width: "100px", + display: "flex", + justifyContent: "center", + }} + > + {filterModeOptionFa[option]} + + ))} + + ); } export default FilterOptionList; diff --git a/src/core/components/FilterDrawer/fieldsType/CustomDate/CustomDatePicker.jsx b/src/core/components/FilterDrawer/fieldsType/CustomDate/CustomDatePicker.jsx index 85e2b08..5666a43 100644 --- a/src/core/components/FilterDrawer/fieldsType/CustomDate/CustomDatePicker.jsx +++ b/src/core/components/FilterDrawer/fieldsType/CustomDate/CustomDatePicker.jsx @@ -2,30 +2,22 @@ import React from "react"; import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker"; import { Typography } from "@mui/material"; -function CustomDatePicker({ - column, - filterParameters, - defaultFilterTranslation, - handleChange, -}) { - return ( - { - handleChange({ ...filterParameters, value: formattedDate }); - }} - placeholder={column.header} - helperText={ - theme.palette.primary.main }} - > - نوع فیلتر: {defaultFilterTranslation} (تاریخ) - - } - /> - ); +function CustomDatePicker({ column, filterParameters, defaultFilterTranslation, handleChange }) { + return ( + { + handleChange({ ...filterParameters, value: formattedDate }); + }} + placeholder={column.header} + helperText={ + theme.palette.primary.main }}> + نوع فیلتر: {defaultFilterTranslation} (تاریخ) + + } + /> + ); } export default CustomDatePicker; diff --git a/src/core/components/FilterDrawer/fieldsType/CustomDate/CustomDatePickerRange.jsx b/src/core/components/FilterDrawer/fieldsType/CustomDate/CustomDatePickerRange.jsx index e10be45..bb36d02 100644 --- a/src/core/components/FilterDrawer/fieldsType/CustomDate/CustomDatePickerRange.jsx +++ b/src/core/components/FilterDrawer/fieldsType/CustomDate/CustomDatePickerRange.jsx @@ -4,57 +4,44 @@ import React from "react"; import { Box, Typography } from "@mui/material"; import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker"; -function CustomDatePickerRange({ - item, - filterParameters, - defaultFilterTranslation, - handleChange, - errors, -}) { - return ( - - { - handleChange({ - ...filterParameters, - value: [formattedDate, filterParameters.value[1]], - }); - }} - maxDate={filterParameters.value[1]} - placeholder={`از تاریخ`} - helperText={ - theme.palette.primary.main }} - > - نوع فیلتر: {defaultFilterTranslation} (تاریخ) - - } - /> - { - handleChange({ - ...filterParameters, - value: [filterParameters.value[0], formattedDate], - }); - }} - minDate={filterParameters.value[0]} - placeholder={`تا تاریخ`} - helperText={ - errors?.[`${item.id}`]?.value - ? errors?.[`${item.id}`]?.value.message - : null - } - error={Boolean(errors?.[`${item.id}`]?.value)} - /> - - ); +function CustomDatePickerRange({ item, filterParameters, defaultFilterTranslation, handleChange, errors }) { + return ( + + { + handleChange({ + ...filterParameters, + value: [formattedDate, filterParameters.value[1]], + }); + }} + maxDate={filterParameters.value[1]} + placeholder={`از تاریخ`} + helperText={ + theme.palette.primary.main }}> + نوع فیلتر: {defaultFilterTranslation} (تاریخ) + + } + /> + { + handleChange({ + ...filterParameters, + value: [filterParameters.value[0], formattedDate], + }); + }} + minDate={filterParameters.value[0]} + placeholder={`تا تاریخ`} + helperText={errors?.[`${item.id}`]?.value ? errors?.[`${item.id}`]?.value.message : null} + error={Boolean(errors?.[`${item.id}`]?.value)} + /> + + ); } export default CustomDatePickerRange; diff --git a/src/core/components/FilterDrawer/fieldsType/CustomDate/MuiDatePicker.jsx b/src/core/components/FilterDrawer/fieldsType/CustomDate/MuiDatePicker.jsx index f98e929..d2d9df0 100644 --- a/src/core/components/FilterDrawer/fieldsType/CustomDate/MuiDatePicker.jsx +++ b/src/core/components/FilterDrawer/fieldsType/CustomDate/MuiDatePicker.jsx @@ -6,81 +6,67 @@ import { Box, FormHelperText, IconButton, InputAdornment } from "@mui/material"; import ClearIcon from "@mui/icons-material/Clear"; import moment from "jalali-moment"; -function MuiDatePicker({ - label, - value, - setFieldValue, - name, - minDate, - maxDate, - helperText, - placeholder, - error, -}) { - return ( - - - { - const date = new Date(value); - const formattedDate = moment(date) - .locale("en") - .format("YYYY-MM-DD"); - setFieldValue(name, formattedDate); - }} - minDate={minDate ? new Date(minDate) : null} - maxDate={maxDate ? new Date(maxDate) : null} - slotProps={{ - textField: { - size: "small", - error: error, - placeholder: placeholder, - InputProps: { - endAdornment: ( - - { - event.stopPropagation(); - setFieldValue(name, ""); - }} - sx={{ - color: "#bfbfbf", - "&:hover": { - backgroundColor: "rgba(189, 189, 189, 0.1)", - color: "#363434", +function MuiDatePicker({ label, value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error }) { + return ( + + + { + const date = new Date(value); + const formattedDate = moment(date).locale("en").format("YYYY-MM-DD"); + setFieldValue(name, formattedDate); + }} + minDate={minDate ? new Date(minDate) : null} + maxDate={maxDate ? new Date(maxDate) : null} + slotProps={{ + textField: { + size: "small", + error: error, + placeholder: placeholder, + InputProps: { + endAdornment: ( + + { + event.stopPropagation(); + setFieldValue(name, ""); + }} + sx={{ + color: "#bfbfbf", + "&:hover": { + backgroundColor: "rgba(189, 189, 189, 0.1)", + color: "#363434", + }, + }} + > + + + + ), + }, + InputLabelProps: { + shrink: true, + }, }, - }} - > - - - - ), - }, - InputLabelProps: { - shrink: true, - }, - }, - }} - /> - {/* + }} + /> + {/* {helperText ? helperText : ""} */} - - - ); + + + ); } export default MuiDatePicker; diff --git a/src/core/components/FilterDrawer/fieldsType/CustomSelect.jsx b/src/core/components/FilterDrawer/fieldsType/CustomSelect.jsx index 24e6b37..61172e6 100644 --- a/src/core/components/FilterDrawer/fieldsType/CustomSelect.jsx +++ b/src/core/components/FilterDrawer/fieldsType/CustomSelect.jsx @@ -1,38 +1,30 @@ "use client"; -import { - FormControl, - InputLabel, - MenuItem, - OutlinedInput, - Select, -} from "@mui/material"; +import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material"; function CustomSelect({ item, filterParameters, handleChange }) { - return ( - - - {item.header} - - - - ); + return ( + + + {item.header} + + + + ); } export default CustomSelect; diff --git a/src/core/components/FilterDrawer/fieldsType/CustomSelectByDependency.jsx b/src/core/components/FilterDrawer/fieldsType/CustomSelectByDependency.jsx index 6db3d11..69536cd 100644 --- a/src/core/components/FilterDrawer/fieldsType/CustomSelectByDependency.jsx +++ b/src/core/components/FilterDrawer/fieldsType/CustomSelectByDependency.jsx @@ -1,44 +1,30 @@ "use client"; -import { - FormControl, - InputLabel, - MenuItem, - OutlinedInput, - Select, -} from "@mui/material"; -function CustomSelectByDependency({ - item, - filterParameters, - value, - handleChange, - selectOption, -}) { - return ( - - - {item.header} - - - - ); +import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material"; +function CustomSelectByDependency({ item, filterParameters, value, handleChange, selectOption }) { + return ( + + + {item.header} + + + + ); } export default CustomSelectByDependency; diff --git a/src/core/components/FilterDrawer/fieldsType/CustomSelectMultiple.jsx b/src/core/components/FilterDrawer/fieldsType/CustomSelectMultiple.jsx index 4602f8c..c1fd7fa 100644 --- a/src/core/components/FilterDrawer/fieldsType/CustomSelectMultiple.jsx +++ b/src/core/components/FilterDrawer/fieldsType/CustomSelectMultiple.jsx @@ -1,57 +1,55 @@ "use client"; import { - Box, - Chip, - FormControl, - FormHelperText, - InputLabel, - MenuItem, - OutlinedInput, - Select, - Typography, + Box, + Chip, + FormControl, + FormHelperText, + InputLabel, + MenuItem, + OutlinedInput, + Select, + Typography, } from "@mui/material"; function CustomSelectMultiple({ item, filterParameters, handleChange }) { - const selectOption = item.selectOption; + const selectOption = item.selectOption; - const getLabelForValue = (value) => { - const option = selectOption.find((opt) => opt.value === value); - return option ? option.label : value; - }; + const getLabelForValue = (value) => { + const option = selectOption.find((opt) => opt.value === value); + return option ? option.label : value; + }; - return ( - - - {item.header} - - - - ); + return ( + + + {item.header} + + + + ); } export default CustomSelectMultiple; diff --git a/src/core/components/FilterDrawer/fieldsType/CustomTextField.jsx b/src/core/components/FilterDrawer/fieldsType/CustomTextField.jsx index e0e361d..86a9c57 100644 --- a/src/core/components/FilterDrawer/fieldsType/CustomTextField.jsx +++ b/src/core/components/FilterDrawer/fieldsType/CustomTextField.jsx @@ -1,41 +1,29 @@ import { InputAdornment, TextField, Typography } from "@mui/material"; import FilterListIcon from "@mui/icons-material/FilterList"; -function CustomTextField({ - item, - filterParameters, - handleOpenFilterBox, - handleBlur, - handleChange, -}) { - return ( - - handleChange({ ...filterParameters, value: e.target.value }) - } - onBlur={handleBlur} - fullWidth - variant="outlined" - size="small" - sx={{ my: 1 }} - InputProps={{ - endAdornment: ( - - - - ), - }} - InputLabelProps={{ shrink: true }} - /> - ); +function CustomTextField({ item, filterParameters, handleOpenFilterBox, handleBlur, handleChange }) { + return ( + handleChange({ ...filterParameters, value: e.target.value })} + onBlur={handleBlur} + fullWidth + variant="outlined" + size="small" + sx={{ my: 1 }} + InputProps={{ + endAdornment: ( + + + + ), + }} + InputLabelProps={{ shrink: true }} + /> + ); } export default CustomTextField; diff --git a/src/core/components/FilterDrawer/fieldsType/CustomTextFieldRange.jsx b/src/core/components/FilterDrawer/fieldsType/CustomTextFieldRange.jsx index 84fd028..f892564 100644 --- a/src/core/components/FilterDrawer/fieldsType/CustomTextFieldRange.jsx +++ b/src/core/components/FilterDrawer/fieldsType/CustomTextFieldRange.jsx @@ -2,84 +2,73 @@ import { Box, InputAdornment, TextField, Typography } from "@mui/material"; import FilterListIcon from "@mui/icons-material/FilterList"; function CustomTextFieldRange({ - item, - defaultFilterTranslation, - handleOpenFilterBox, - handleChange, - filterParameters, - handleBlur, - errors, + item, + defaultFilterTranslation, + handleOpenFilterBox, + handleChange, + filterParameters, + handleBlur, + errors, }) { - return ( - - - handleChange({ - ...filterParameters, - value: [e.target.value, filterParameters.value[1]], - }) - } - onBlur={handleBlur} - label={از {item.header}} - value={filterParameters.value[0]} - fullWidth - error={ - touched?.[`${item.id}`]?.value && - Boolean(errors?.[`${item.id}`]?.value) - } - helperText={ - theme.palette.primary.main, - fontWeight: "bold", - }} - > - نوع فیلتر: {defaultFilterTranslation} - - } - variant="outlined" - size="small" - sx={{ my: 1, marginRight: 1 }} - /> - - handleChange({ - ...filterParameters, - value: [filterParameters.value[0], e.target.value], - }) - } - onBlur={handleBlur} - error={Boolean(errors?.[`${item.id}`]?.value)} - helperText={ - errors?.[`${item.id}`]?.value - ? errors?.[`${item.id}`]?.value.message - : null - } - label={تا {item.header}} - value={filterParameters.value[1]} - fullWidth - variant="outlined" - size="small" - sx={{ my: 1 }} - InputProps={{ - endAdornment: ( - - - - ), - }} - /> - - ); + return ( + + + handleChange({ + ...filterParameters, + value: [e.target.value, filterParameters.value[1]], + }) + } + onBlur={handleBlur} + label={از {item.header}} + value={filterParameters.value[0]} + fullWidth + error={touched?.[`${item.id}`]?.value && Boolean(errors?.[`${item.id}`]?.value)} + helperText={ + theme.palette.primary.main, + fontWeight: "bold", + }} + > + نوع فیلتر: {defaultFilterTranslation} + + } + variant="outlined" + size="small" + sx={{ my: 1, marginRight: 1 }} + /> + + handleChange({ + ...filterParameters, + value: [filterParameters.value[0], e.target.value], + }) + } + onBlur={handleBlur} + error={Boolean(errors?.[`${item.id}`]?.value)} + helperText={errors?.[`${item.id}`]?.value ? errors?.[`${item.id}`]?.value.message : null} + label={تا {item.header}} + value={filterParameters.value[1]} + fullWidth + variant="outlined" + size="small" + sx={{ my: 1 }} + InputProps={{ + endAdornment: ( + + + + ), + }} + /> + + ); } export default CustomTextFieldRange; diff --git a/src/core/components/FilterDrawer/index.jsx b/src/core/components/FilterDrawer/index.jsx index 318f048..69cca10 100644 --- a/src/core/components/FilterDrawer/index.jsx +++ b/src/core/components/FilterDrawer/index.jsx @@ -8,15 +8,14 @@ import FilterController from "./FilterController"; import FilterControllerWithDependency from "./FilterControllerWithDependency"; const headerSx = { - display: "flex", - alignItems: "center", - justifyContent: "space-between", - px: 2, - py: 1, - backgroundColor: (theme) => theme.palette.primary.main, - boxShadow: - "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px", - maxWidth: "450px", + display: "flex", + alignItems: "center", + justifyContent: "space-between", + px: 2, + py: 1, + backgroundColor: (theme) => theme.palette.primary.main, + boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px", + maxWidth: "450px", }; const headerTitleSx = { display: "flex", alignItems: "center" }; @@ -25,136 +24,135 @@ const iconButtonSx = { color: "#fff" }; const formContainerSx = { px: 2, py: 3 }; const footerSx = { - display: "flex", - justifyContent: "center", - alignItems: "center", - pb: 2, + display: "flex", + justifyContent: "center", + alignItems: "center", + pb: 2, }; const submitButtonSx = { - px: 8, - boxShadow: - "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px", - backgroundColor: "primary2", - ":hover": { backgroundColor: "primary2" }, + px: 8, + boxShadow: "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px", + backgroundColor: "primary2", + ":hover": { backgroundColor: "primary2" }, }; const validationSchema = Yup.object({ - activity_date_time: Yup.array() - .of(Yup.string().nullable()) - .test({ - test(value, ctx) { - const [start, end] = value || ["", ""]; - if ((start && !end) || (!start && end)) { - return ctx.createError({ message: "این بخش را تکمیل نمایید" }); - } - return true; - }, - }), + activity_date_time: Yup.array() + .of(Yup.string().nullable()) + .test({ + test(value, ctx) { + const [start, end] = value || ["", ""]; + if ((start && !end) || (!start && end)) { + return ctx.createError({ message: "این بخش را تکمیل نمایید" }); + } + return true; + }, + }), }); const FilterDrawer = ({ defaultValues, setFilterData, closeDrawer }) => { - const { - control, - errors, - reset, - handleSubmit, - formState: { isDirty }, - } = useForm({ - defaultValues, - resolver: yupResolver( - Yup.object( - Object.keys(defaultValues).reduce((acc, key) => { - const initialValue = defaultValues[key]; - if (initialValue.filterMode === "between") { - acc[key] = Yup.object().shape({ - value: Yup.array() - .of(Yup.string().nullable()) - .test({ - test(value, ctx) { - const [start, end] = value || ["", ""]; - if ( - initialValue.datatype === "numeric" && - parseInt(end, 10) <= parseInt(start, 10) - ) { - return ctx.createError({ - message: `مقدار وارده باید بیشتر از (${start}) باشد`, - }); - } else if ((start && !end) || (!start && end)) { - return ctx.createError({ - message: "این بخش را تکمیل نمایید", - }); + const { + control, + errors, + reset, + handleSubmit, + formState: { isDirty }, + } = useForm({ + defaultValues, + resolver: yupResolver( + Yup.object( + Object.keys(defaultValues).reduce((acc, key) => { + const initialValue = defaultValues[key]; + if (initialValue.filterMode === "between") { + acc[key] = Yup.object().shape({ + value: Yup.array() + .of(Yup.string().nullable()) + .test({ + test(value, ctx) { + const [start, end] = value || ["", ""]; + if ( + initialValue.datatype === "numeric" && + parseInt(end, 10) <= parseInt(start, 10) + ) { + return ctx.createError({ + message: `مقدار وارده باید بیشتر از (${start}) باشد`, + }); + } else if ((start && !end) || (!start && end)) { + return ctx.createError({ + message: "این بخش را تکمیل نمایید", + }); + } + return true; + }, + }), + }); } - return true; - }, - }), - }); - } - return acc; - }, {}), - ), - ), - mode: "all", - }); + return acc; + }, {}) + ) + ), + mode: "all", + }); - const onSubmit = (data) => { - setFilterData(data); - closeDrawer(); - }; + const onSubmit = (data) => { + setFilterData(data); + closeDrawer(); + }; - return ( - <> - - - - - فیلتر - - - - - - - -
- - {Object.values(defaultValues).map( - (item) => - item.enable && - (item.dependencyId ? ( - - ) : ( - - )), - )} - - - + return ( + <> + + + + + فیلتر + + + + + - - -
- - ); + +
+ + {Object.values(defaultValues).map( + (item) => + item.enable && + (item.dependencyId ? ( + + ) : ( + + )) + )} + + + + + +
+
+ + ); }; export default FilterDrawer; diff --git a/src/core/components/LoadingHardPage.jsx b/src/core/components/LoadingHardPage.jsx index 4e9125a..5c61646 100644 --- a/src/core/components/LoadingHardPage.jsx +++ b/src/core/components/LoadingHardPage.jsx @@ -4,79 +4,65 @@ import SvgLoading from "@/core/components/svgs/SvgLoading"; import { Backdrop, Box, Stack, styled, useTheme } from "@mui/material"; const LoadingImage = styled(Box)({ - "@keyframes load": { - "0%": { - transform: "scale(1)", + "@keyframes load": { + "0%": { + transform: "scale(1)", + }, + "50%": { + transform: "scale(.5)", + }, + "100%": { + transform: "scale(1)", + }, }, - "50%": { - transform: "scale(.5)", - }, - "100%": { - transform: "scale(1)", - }, - }, - animation: "load 2s infinite", + animation: "load 2s infinite", }); const LoadingHardPage = ({ - children, - loading, - authState = false, - sx = {}, - icon = null, - width = 200, - height = 200, - label = "", + children, + loading, + authState = false, + sx = {}, + icon = null, + width = 200, + height = 200, + label = "", }) => { - const theme = useTheme(); - return ( - <> - theme.zIndex.drawer + 1, - ...sx, - }} - open={loading} - > - - {authState ? ( - - {icon ? ( - - {icon} - - ) : ( - - )} - - ) : ( - - {icon ? ( - - {icon} - - ) : ( - - )} - - )} - - {label} - - - - {children} - - ); + const theme = useTheme(); + return ( + <> + theme.zIndex.drawer + 1, + ...sx, + }} + open={loading} + > + + {authState ? ( + + {icon ? ( + {icon} + ) : ( + + )} + + ) : ( + + {icon ? ( + {icon} + ) : ( + + )} + + )} + {label} + + + {children} + + ); }; export default LoadingHardPage; diff --git a/src/core/components/LtrTextField.jsx b/src/core/components/LtrTextField.jsx index fd58d17..ea17042 100644 --- a/src/core/components/LtrTextField.jsx +++ b/src/core/components/LtrTextField.jsx @@ -1,10 +1,10 @@ import { styled, TextField } from "@mui/material"; const LtrTextField = styled(TextField)` - .MuiInputBase-input { - /* @noflip */ - direction: ltr; - } + .MuiInputBase-input { + /* @noflip */ + direction: ltr; + } `; export default LtrTextField; diff --git a/src/core/components/NotificationDesign/AskForKeepData.jsx b/src/core/components/NotificationDesign/AskForKeepData.jsx index 3fe7f2e..18eceb3 100644 --- a/src/core/components/NotificationDesign/AskForKeepData.jsx +++ b/src/core/components/NotificationDesign/AskForKeepData.jsx @@ -7,88 +7,66 @@ import { toast } from "react-toastify"; import useTableSetting from "@/lib/hooks/useTableSetting"; import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects"; -function AskForKeepData({ - filterData, - sortData, - hideData, - user_id, - page_name, - table_name, - columns, -}) { - const { filterAction, sortAction, hideAction } = useTableSetting(); +function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, table_name, columns }) { + const { filterAction, sortAction, hideAction } = useTableSetting(); - const filteredHideData = Object.fromEntries( - Object.entries(hideData).filter(([key, value]) => value === false), - ); + const filteredHideData = Object.fromEntries(Object.entries(hideData).filter(([key, value]) => value === false)); - const flattenHideData = flattenObjectOfObjects(filteredHideData); + const flattenHideData = flattenObjectOfObjects(filteredHideData); - const onSaveFilter = () => { - const filteredItems = Object.keys(filterData) - .map((key) => { - const value = filterData[key].value; - if ( - value !== "" && - !( - Array.isArray(value) && - (value.length === 0 || - (value.length === 2 && value[0] === "" && value[1] === "")) - ) - ) { - return filterData[key]; - } - }) - .filter(Boolean); - filterAction(user_id, page_name, table_name, filteredItems, columns); - sortAction(user_id, page_name, table_name, sortData, columns); - hideAction(user_id, page_name, table_name, flattenHideData, columns); - toast.dismiss({ containerId: "datatable" }); - }; + const onSaveFilter = () => { + const filteredItems = Object.keys(filterData) + .map((key) => { + const value = filterData[key].value; + if ( + value !== "" && + !( + Array.isArray(value) && + (value.length === 0 || (value.length === 2 && value[0] === "" && value[1] === "")) + ) + ) { + return filterData[key]; + } + }) + .filter(Boolean); + filterAction(user_id, page_name, table_name, filteredItems, columns); + sortAction(user_id, page_name, table_name, sortData, columns); + hideAction(user_id, page_name, table_name, flattenHideData, columns); + toast.dismiss({ containerId: "datatable" }); + }; - const handleDismiss = () => { - toast.dismiss({ containerId: "datatable" }); - }; + const handleDismiss = () => { + toast.dismiss({ containerId: "datatable" }); + }; - return ( - - - - ذخیره سازی تغییرات - - - - - - آیا مایل به ذخیره تغییر های اعمال شده برای دفعات بعد هستید؟ - - - - - - - - ); + return ( + + + + ذخیره سازی تغییرات + + + + + آیا مایل به ذخیره تغییر های اعمال شده برای دفعات بعد هستید؟ + + + + + + + ); } export default AskForKeepData; diff --git a/src/core/components/PageLoading.jsx b/src/core/components/PageLoading.jsx index 5b36836..186e1ae 100644 --- a/src/core/components/PageLoading.jsx +++ b/src/core/components/PageLoading.jsx @@ -3,23 +3,18 @@ import { Paper } from "@mui/material"; import LoadingHardPage from "./LoadingHardPage"; const PageLoading = () => { - return ( - - - - ); + return ( + + + + ); }; export default PageLoading; diff --git a/src/core/components/PageTitle.jsx b/src/core/components/PageTitle.jsx index 675b6b8..4c93098 100644 --- a/src/core/components/PageTitle.jsx +++ b/src/core/components/PageTitle.jsx @@ -3,16 +3,16 @@ import { Chip, Divider, Typography } from "@mui/material"; const PageTitle = ({ title }) => { - return ( - - - {title} - - } - /> - - ); + return ( + + + {title} + + } + /> + + ); }; export default PageTitle; diff --git a/src/core/components/Profile/ChangePassword/Form.jsx b/src/core/components/Profile/ChangePassword/Form.jsx index 19dec1a..b708625 100644 --- a/src/core/components/Profile/ChangePassword/Form.jsx +++ b/src/core/components/Profile/ChangePassword/Form.jsx @@ -1,15 +1,15 @@ "use client"; import { - Chip, - Divider, - FormControl, - FormHelperText, - Grid, - IconButton, - InputAdornment, - InputLabel, - OutlinedInput, + Chip, + Divider, + FormControl, + FormHelperText, + Grid, + IconButton, + InputAdornment, + InputLabel, + OutlinedInput, } from "@mui/material"; import StyledForm from "@/core/components/StyledForm"; import { useForm } from "react-hook-form"; @@ -22,164 +22,133 @@ import VisibilityOff from "@mui/icons-material/VisibilityOff"; import useRequest from "@/lib/hooks/useRequest"; const validationSchema = object({ - current_password: string().required("اجباری"), - new_password: string().required("اجباری"), - repeat_new_password: string() - .required("اجباری") - .test( - "password-match", - "رمز عبور جدید و تکرار آن باید یکسان باشند", - function (value) { - return this.parent.new_password === value; - }, - ), + current_password: string().required("اجباری"), + new_password: string().required("اجباری"), + repeat_new_password: string() + .required("اجباری") + .test("password-match", "رمز عبور جدید و تکرار آن باید یکسان باشند", function (value) { + return this.parent.new_password === value; + }), }); const defaultValues = { - current_password: "", - new_password: "", - repeat_new_password: "", + current_password: "", + new_password: "", + repeat_new_password: "", }; const Form = ({ handleCloseForm, setLoading }) => { - const request = useRequest(); - const [showNewPassword, setShowNewPassword] = useState(); - const [showRepeatNewPassword, setShowRepeatNewPassword] = useState(); + const request = useRequest(); + const [showNewPassword, setShowNewPassword] = useState(); + const [showRepeatNewPassword, setShowRepeatNewPassword] = useState(); - const { - register, - handleSubmit, - formState: { isSubmitting, errors }, - } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); + const { + register, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); - useEffect(() => { - setLoading(isSubmitting); - }, [isSubmitting]); + useEffect(() => { + setLoading(isSubmitting); + }, [isSubmitting]); - const onSubmit = async (data) => { - console.log(data); + const onSubmit = async (data) => { + console.log(data); - const formData = new FormData(); - formData.append("current_password", data.current_password); - formData.append("new_password", data.new_password); - try { - await request(CHANGE_USER_PASSWORD, "post", { data: formData }); - handleCloseForm(); - } catch (error) {} - }; + const formData = new FormData(); + formData.append("current_password", data.current_password); + formData.append("new_password", data.new_password); + try { + await request(CHANGE_USER_PASSWORD, "post", { data: formData }); + handleCloseForm(); + } catch (error) {} + }; - return ( - <> - - - - - - - - رمز عبور فعلی - - - {errors.current_password - ? errors.current_password.message - : null} - - - - - - رمز عبور جدید - - setShowNewPassword(!showNewPassword)} - onMouseDown={(event) => event.preventDefault()} - edge="end" - > - {showNewPassword ? : } - - - } - /> - - {errors.new_password ? errors.new_password.message : null} - - - - - - - تکرار رمز عبور جدید - - - - setShowRepeatNewPassword(!showRepeatNewPassword) - } - onMouseDown={(event) => event.preventDefault()} - edge="end" - > - {showRepeatNewPassword ? ( - - ) : ( - - )} - - - } - /> - - {errors.repeat_new_password - ? errors.repeat_new_password.message - : null} - - - - - - - ); + return ( + <> + + + + + + + + رمز عبور فعلی + + + {errors.current_password ? errors.current_password.message : null} + + + + + + رمز عبور جدید + + setShowNewPassword(!showNewPassword)} + onMouseDown={(event) => event.preventDefault()} + edge="end" + > + {showNewPassword ? : } + + + } + /> + + {errors.new_password ? errors.new_password.message : null} + + + + + + تکرار رمز عبور جدید + + setShowRepeatNewPassword(!showRepeatNewPassword)} + onMouseDown={(event) => event.preventDefault()} + edge="end" + > + {showRepeatNewPassword ? : } + + + } + /> + + {errors.repeat_new_password ? errors.repeat_new_password.message : null} + + + + + + + ); }; export default Form; diff --git a/src/core/components/Profile/ChangePassword/index.jsx b/src/core/components/Profile/ChangePassword/index.jsx index 366584b..3a3a828 100644 --- a/src/core/components/Profile/ChangePassword/index.jsx +++ b/src/core/components/Profile/ChangePassword/index.jsx @@ -6,40 +6,34 @@ import { useState } from "react"; import Form from "./Form"; const ChangePassword = ({ open, setOpen }) => { - const [loading, setLoading] = useState(false); + const [loading, setLoading] = useState(false); - const handleCloseForm = () => { - setOpen(false); - }; + const handleCloseForm = () => { + setOpen(false); + }; - return ( - - -
- - - - - -
- ); + return ( + + + + + + + + + + ); }; export default ChangePassword; diff --git a/src/core/components/Profile/ProfileActions.jsx b/src/core/components/Profile/ProfileActions.jsx index 46dcc92..3c93fd3 100644 --- a/src/core/components/Profile/ProfileActions.jsx +++ b/src/core/components/Profile/ProfileActions.jsx @@ -10,25 +10,25 @@ import { useState } from "react"; import ChangePassword from "./ChangePassword"; const ProfileActions = () => { - const { getUser, logout } = useAuth(); - const requestServer = useRequest(); - const [openUpdate, setOpenUpdate] = useState(false); - const [openChangePass, setOpenChangePass] = useState(false); + const { getUser, logout } = useAuth(); + const requestServer = useRequest(); + const [openUpdate, setOpenUpdate] = useState(false); + const [openChangePass, setOpenChangePass] = useState(false); - const openUpdateProfile = () => { - getUser(); - setOpenUpdate(true); - }; - const handleLogout = () => { - requestServer(GET_USER_LOGOUT_ROUTE, "post").then(() => { - logout(); - }); - }; + const openUpdateProfile = () => { + getUser(); + setOpenUpdate(true); + }; + const handleLogout = () => { + requestServer(GET_USER_LOGOUT_ROUTE, "post").then(() => { + logout(); + }); + }; - return ( - <> - - {/* + return ( + <> + + {/* { flexItem sx={{ mx: 1 }} /> */} - - - - - - - - { - setOpenChangePass(true); - }} - > - - - - - {/* */} - - - ); + + + + + + + + { + setOpenChangePass(true); + }} + > + + + + + {/* */} + + + ); }; export default ProfileActions; diff --git a/src/core/components/Profile/ProfileInfo.jsx b/src/core/components/Profile/ProfileInfo.jsx index ec84b2a..1b28171 100644 --- a/src/core/components/Profile/ProfileInfo.jsx +++ b/src/core/components/Profile/ProfileInfo.jsx @@ -5,45 +5,34 @@ import { Avatar, Box, Chip, Divider, Stack, Typography } from "@mui/material"; import moment from "jalali-moment"; const ProfileInfo = () => { - const { user } = useAuth(); + const { user } = useAuth(); - return ( - <> - - - - - {`${user.full_name}`} - - - شماره تماس داخلی : {user.telephone_id} - - - - - - آخرین ورود - - - - {moment(user.last_login).locale("fa").fromNow()} - - - - - - - - - ); + return ( + <> + + + + + {`${user.full_name}`} + + شماره تماس داخلی : {user.telephone_id} + + + + + آخرین ورود + + + + {moment(user.last_login).locale("fa").fromNow()} + + + + + + + + + ); }; export default ProfileInfo; diff --git a/src/core/components/Profile/index.jsx b/src/core/components/Profile/index.jsx index d538990..fd5cbf4 100644 --- a/src/core/components/Profile/index.jsx +++ b/src/core/components/Profile/index.jsx @@ -5,18 +5,18 @@ import ProfileInfo from "./ProfileInfo"; import ProfileActions from "./ProfileActions"; const Profile = () => { - return ( - - - - - ); + return ( + + + + + ); }; export default Profile; diff --git a/src/core/components/ScrollBox.jsx b/src/core/components/ScrollBox.jsx index c4a7391..e7bd5d7 100644 --- a/src/core/components/ScrollBox.jsx +++ b/src/core/components/ScrollBox.jsx @@ -1,20 +1,20 @@ import { Box, styled } from "@mui/material"; const ScrollBox = styled(Box)(({ theme }) => ({ - flexGrow: 1, - overflowY: "auto", - maxWidth: "450px", - "::-webkit-scrollbar": { - width: "5px", - }, - "::-webkit-scrollbar-track": { - boxShadow: "inset 0 0 5px #fff", - borderRadius: "5px", - }, - "::-webkit-scrollbar-thumb": { - background: theme.palette.primary.dark, - borderRadius: "0px", - }, + flexGrow: 1, + overflowY: "auto", + maxWidth: "450px", + "::-webkit-scrollbar": { + width: "5px", + }, + "::-webkit-scrollbar-track": { + boxShadow: "inset 0 0 5px #fff", + borderRadius: "5px", + }, + "::-webkit-scrollbar-thumb": { + background: theme.palette.primary.dark, + borderRadius: "0px", + }, })); export default ScrollBox; diff --git a/src/core/components/Toasts/error.jsx b/src/core/components/Toasts/error.jsx index ffd6381..dbc25e8 100644 --- a/src/core/components/Toasts/error.jsx +++ b/src/core/components/Toasts/error.jsx @@ -3,220 +3,214 @@ import { Box, Typography } from "@mui/material"; import { Dangerous } from "@mui/icons-material"; export const errorServerToast = (toastContainer) => - toast.error( - () => ( - - - - - - {"The request failed due to an internal error."} - - - - - ), - { - icon: false, - containerId: toastContainer, - autoClose: 5000, - hideProgressBar: true, - pauseOnHover: true, - closeOnClick: false, - draggable: true, - }, - ); + toast.error( + () => ( + + + + + {"The request failed due to an internal error."} + + + + ), + { + icon: false, + containerId: toastContainer, + autoClose: 5000, + hideProgressBar: true, + pauseOnHover: true, + closeOnClick: false, + draggable: true, + } + ); export const errorUnauthorizedToast = (toastContainer) => - toast.error( - () => ( - - - - - - {"The user is not authorized to make the request."} - - - - - ), - { - icon: false, - containerId: toastContainer, - autoClose: 3000, - hideProgressBar: true, - pauseOnHover: true, - closeOnClick: false, - draggable: true, - }, - ); + toast.error( + () => ( + + + + + {"The user is not authorized to make the request."} + + + + ), + { + icon: false, + containerId: toastContainer, + autoClose: 3000, + hideProgressBar: true, + pauseOnHover: true, + closeOnClick: false, + draggable: true, + } + ); export const errorAccessDeniedToast = (message, toastContainer) => - toast.error( - () => ( - - - - - - {message || "Access Denied"} - - - - - ), - { - icon: false, - containerId: toastContainer, - autoClose: 3000, - hideProgressBar: true, - pauseOnHover: true, - closeOnClick: false, - draggable: true, - }, - ); + toast.error( + () => ( + + + + + {message || "Access Denied"} + + + + ), + { + icon: false, + containerId: toastContainer, + autoClose: 3000, + hideProgressBar: true, + pauseOnHover: true, + closeOnClick: false, + draggable: true, + } + ); export const errorLogicToast = (message, toastContainer) => - toast.error( - () => ( - - - - - - {message || - "The request was well-formed but was unable to be followed due to semantic errors."} - - - - - ), - { - icon: false, - containerId: toastContainer, - autoClose: false, - closeOnClick: false, - draggable: false, - }, - ); + toast.error( + () => ( + + + + + + {message || + "The request was well-formed but was unable to be followed due to semantic errors."} + + + + + ), + { + icon: false, + containerId: toastContainer, + autoClose: false, + closeOnClick: false, + draggable: false, + } + ); export const errorValidationToast = (message, toastContainer) => - toast.error( - () => ( - - - - - - {message || - "The request was well-formed but was unable to be followed due to semantic errors."} - - - - - ), - { - icon: false, - containerId: toastContainer, - autoClose: false, - closeOnClick: false, - draggable: false, - }, - ); + toast.error( + () => ( + + + + + + {message || + "The request was well-formed but was unable to be followed due to semantic errors."} + + + + + ), + { + icon: false, + containerId: toastContainer, + autoClose: false, + closeOnClick: false, + draggable: false, + } + ); export const errorTooManyToast = (toastContainer) => - toast.error( - () => ( - - - - - - {"Too many requests have been sent within a given time span."} - - - - - ), - { - icon: false, - containerId: toastContainer, - autoClose: false, - closeOnClick: false, - draggable: false, - }, - ); + toast.error( + () => ( + + + + + + {"Too many requests have been sent within a given time span."} + + + + + ), + { + icon: false, + containerId: toastContainer, + autoClose: false, + closeOnClick: false, + draggable: false, + } + ); export const errorClientToast = (toastContainer) => - toast.error( - () => ( - - - - - - { - "The API request is invalid or improperly formed. Consequently, the API server could not understand the request." - } - - - - - ), - { - icon: false, - containerId: toastContainer, - autoClose: false, - closeOnClick: false, - draggable: false, - }, - ); + toast.error( + () => ( + + + + + + { + "The API request is invalid or improperly formed. Consequently, the API server could not understand the request." + } + + + + + ), + { + icon: false, + containerId: toastContainer, + autoClose: false, + closeOnClick: false, + draggable: false, + } + ); diff --git a/src/core/components/Toasts/success.jsx b/src/core/components/Toasts/success.jsx index 7cdea7f..fc11759 100644 --- a/src/core/components/Toasts/success.jsx +++ b/src/core/components/Toasts/success.jsx @@ -3,33 +3,31 @@ import { Box, Typography } from "@mui/material"; import { Beenhere } from "@mui/icons-material"; export const successToast = (toastContainer) => - toast.success( - () => ( - - - - - - {"عملیات با موفقیت انجام شد"} - - - - - ), - { - icon: false, - containerId: toastContainer, - autoClose: 3000, - hideProgressBar: true, - pauseOnHover: true, - closeOnClick: false, - draggable: true, - }, - ); + toast.success( + () => ( + + + + + {"عملیات با موفقیت انجام شد"} + + + + ), + { + icon: false, + containerId: toastContainer, + autoClose: 3000, + hideProgressBar: true, + pauseOnHover: true, + closeOnClick: false, + draggable: true, + } + ); diff --git a/src/core/components/svgs/SvgError.jsx b/src/core/components/svgs/SvgError.jsx index 756496e..580b803 100644 --- a/src/core/components/svgs/SvgError.jsx +++ b/src/core/components/svgs/SvgError.jsx @@ -2,99 +2,94 @@ import { useTheme } from "@mui/material"; const SvgError = ({ width, height, color = null }) => { - const theme = useTheme(); - const fillColor = color || theme.palette.primary.main; + const theme = useTheme(); + const fillColor = color || theme.palette.primary.main; - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; export default SvgError; diff --git a/src/core/components/svgs/SvgLoading.jsx b/src/core/components/svgs/SvgLoading.jsx index 661441e..750c57b 100644 --- a/src/core/components/svgs/SvgLoading.jsx +++ b/src/core/components/svgs/SvgLoading.jsx @@ -2,292 +2,292 @@ import { useTheme } from "@mui/material"; const SvgLoading = ({ width, height, color = null }) => { - const theme = useTheme(); - const fillColor = color || theme.palette.primary.main; + const theme = useTheme(); + const fillColor = color || theme.palette.primary.main; - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; export default SvgLoading; diff --git a/src/core/components/svgs/SvgNotFound.jsx b/src/core/components/svgs/SvgNotFound.jsx index 7c57e88..5d16909 100644 --- a/src/core/components/svgs/SvgNotFound.jsx +++ b/src/core/components/svgs/SvgNotFound.jsx @@ -1,162 +1,162 @@ import { useTheme } from "@mui/material"; const SvgNotFound = ({ width, height, color = null }) => { - const theme = useTheme(); - const fillColor = color || theme.palette.primary.main; + const theme = useTheme(); + const fillColor = color || theme.palette.primary.main; - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; export default SvgNotFound; diff --git a/src/core/middlewares/withAuth.js b/src/core/middlewares/withAuth.js index c9286e7..f2a40f7 100644 --- a/src/core/middlewares/withAuth.js +++ b/src/core/middlewares/withAuth.js @@ -6,39 +6,36 @@ import LoadingHardPage from "../components/LoadingHardPage"; import { Stack, Typography } from "@mui/material"; function WithAuthMiddleware({ children }) { - const router = useRouter(); - const pathName = usePathname(); - const { isAuth, initAuthState, errorState } = useAuth(); + const router = useRouter(); + const pathName = usePathname(); + const { isAuth, initAuthState, errorState } = useAuth(); - useEffect(() => { - if (!initAuthState) return; - if (!isAuth) { - router.replace(`/login?redirect=${encodeURIComponent(pathName)}`); - } - }, [isAuth, initAuthState]); - - if (!initAuthState || !isAuth) - return ( - - {errorState.message} - - {" "} - کد : {errorState.status} - -
- ) : ( - درحال احراز هویت... - ) + useEffect(() => { + if (!initAuthState) return; + if (!isAuth) { + router.replace(`/login?redirect=${encodeURIComponent(pathName)}`); } - loading={true} - /> - ); + }, [isAuth, initAuthState]); - return <>{children}; + if (!initAuthState || !isAuth) + return ( + + {errorState.message} + کد : {errorState.status} + + ) : ( + درحال احراز هویت... + ) + } + loading={true} + /> + ); + + return <>{children}; } export default WithAuthMiddleware; diff --git a/src/core/middlewares/withPermission.js b/src/core/middlewares/withPermission.js index f8b121a..7da7969 100644 --- a/src/core/middlewares/withPermission.js +++ b/src/core/middlewares/withPermission.js @@ -5,43 +5,39 @@ import { usePermissions } from "@/lib/hooks/usePermissions"; import { useEffect, useState } from "react"; function WithPermission({ children, permission_name }) { - const { data, isLoading } = usePermissions(); - const [cachedData, setCachedData] = useState(null); + const { data, isLoading } = usePermissions(); + const [cachedData, setCachedData] = useState(null); - useEffect(() => { - if (data) { - setCachedData(data); + useEffect(() => { + if (data) { + setCachedData(data); + } + }, [data]); + + if (isLoading || !cachedData || !permission_name) { + return null; } - }, [data]); - if (isLoading || !cachedData || !permission_name) { - return null; - } + const hasPermission = + permission_name.includes("all") || permission_name.some((permission) => cachedData.includes(permission)); - const hasPermission = - permission_name.includes("all") || - permission_name.some((permission) => cachedData.includes(permission)); - - if (!hasPermission) { - return ( - - - شما دسترسی لازم به این صفحه را ندارید - - - ); - } - return <>{children}; + if (!hasPermission) { + return ( + + + شما دسترسی لازم به این صفحه را ندارید + + + ); + } + return <>{children}; } export default WithPermission; diff --git a/src/core/middlewares/withWidget.js b/src/core/middlewares/withWidget.js index 95180ab..9413bdb 100644 --- a/src/core/middlewares/withWidget.js +++ b/src/core/middlewares/withWidget.js @@ -1,5 +1,5 @@ const WithWidgetMiddleware = ({ children, enable }) => { - return enable ? <>{children} : null; + return enable ? <>{children} : null; }; export default WithWidgetMiddleware; diff --git a/src/core/middlewares/withoutAuth.js b/src/core/middlewares/withoutAuth.js index 396b848..2600f93 100644 --- a/src/core/middlewares/withoutAuth.js +++ b/src/core/middlewares/withoutAuth.js @@ -6,40 +6,37 @@ import LoadingHardPage from "../components/LoadingHardPage"; import { Stack, Typography } from "@mui/material"; function WithoutAuthMiddleware({ children }) { - const router = useRouter(); - const { isAuth, initAuthState, errorState } = useAuth(); - const searchParams = useSearchParams(); + const router = useRouter(); + const { isAuth, initAuthState, errorState } = useAuth(); + const searchParams = useSearchParams(); - const redirect = searchParams.get("redirect"); + const redirect = searchParams.get("redirect"); - useEffect(() => { - if (!initAuthState) return; - if (isAuth) { - router.replace(redirect ? decodeURIComponent(redirect) : "/dashboard"); - } - }, [isAuth, initAuthState]); - - if (!initAuthState || isAuth) - return ( - - {errorState.message} - - {" "} - کد : {errorState.status} - - - ) : ( - درحال احراز هویت... - ) + useEffect(() => { + if (!initAuthState) return; + if (isAuth) { + router.replace(redirect ? decodeURIComponent(redirect) : "/dashboard"); } - loading={true} - /> - ); - return <>{children}; + }, [isAuth, initAuthState]); + + if (!initAuthState || isAuth) + return ( + + {errorState.message} + کد : {errorState.status} + + ) : ( + درحال احراز هویت... + ) + } + loading={true} + /> + ); + return <>{children}; } export default WithoutAuthMiddleware; diff --git a/src/core/utils/DataTableFilterDataStructure.js b/src/core/utils/DataTableFilterDataStructure.js index e8a5ddb..43f1144 100644 --- a/src/core/utils/DataTableFilterDataStructure.js +++ b/src/core/utils/DataTableFilterDataStructure.js @@ -1,10 +1,10 @@ export default function DataTableFilterDataStructure(filterData, isValueEmpty) { - return Object.values(filterData) - .filter((filter) => !isValueEmpty(filter.value)) - .map(({ filterMode, id, datatype, value }) => ({ - id: id.replace(/__/g, "."), - fn: filterMode, - datatype, - value, - })); + return Object.values(filterData) + .filter((filter) => !isValueEmpty(filter.value)) + .map(({ filterMode, id, datatype, value }) => ({ + id: id.replace(/__/g, "."), + fn: filterMode, + datatype, + value, + })); } diff --git a/src/core/utils/cacheRtl.js b/src/core/utils/cacheRtl.js index 5830941..120f7f8 100644 --- a/src/core/utils/cacheRtl.js +++ b/src/core/utils/cacheRtl.js @@ -6,10 +6,10 @@ import rtlPlugin from "stylis-plugin-rtl"; // Create rtl cache export const rtlCache = createCache({ - key: "mui-rtl", - stylisPlugins: [prefixer, rtlPlugin], + key: "mui-rtl", + stylisPlugins: [prefixer, rtlPlugin], }); export function Rtl(props) { - return {props.children}; + return {props.children}; } diff --git a/src/core/utils/errorResponse.js b/src/core/utils/errorResponse.js index 8d281ba..2a147ed 100644 --- a/src/core/utils/errorResponse.js +++ b/src/core/utils/errorResponse.js @@ -1,72 +1,65 @@ "use client"; import { toast } from "react-toastify"; import { - errorAccessDeniedToast, - errorClientToast, - errorLogicToast, - errorServerToast, - errorTooManyToast, - errorUnauthorizedToast, - errorValidationToast, + errorAccessDeniedToast, + errorClientToast, + errorLogicToast, + errorServerToast, + errorTooManyToast, + errorUnauthorizedToast, + errorValidationToast, } from "@/core/components/Toasts/error"; const isServerError = (status) => status >= 500 && status <= 599; const isClientError = (status) => status >= 400 && status <= 499; const errorServer = (response, notification, toastContainer) => { - if (notification) errorServerToast(toastContainer); + if (notification) errorServerToast(toastContainer); }; const errorClient = (response, notification, toastContainer, logout) => { - switch (response.status) { - case 401: - logout(); - if (notification) errorUnauthorizedToast(toastContainer); - break; - case 403: - if (notification) - errorAccessDeniedToast(response.data.message, toastContainer); - break; - case 422: - if ("type" in response.data) { - if (Array.isArray(response.data.message)) { - response.data.message.map((item) => { - if (notification) errorLogicToast(item, toastContainer); - }); - } else { - if (notification) - errorLogicToast(response.data.message, toastContainer); - } - break; - } - if (notification) { - const errorsMap = Object.keys(response.data.errors); - const errorsArray = response.data.errors; + switch (response.status) { + case 401: + logout(); + if (notification) errorUnauthorizedToast(toastContainer); + break; + case 403: + if (notification) errorAccessDeniedToast(response.data.message, toastContainer); + break; + case 422: + if ("type" in response.data) { + if (Array.isArray(response.data.message)) { + response.data.message.map((item) => { + if (notification) errorLogicToast(item, toastContainer); + }); + } else { + if (notification) errorLogicToast(response.data.message, toastContainer); + } + break; + } + if (notification) { + const errorsMap = Object.keys(response.data.errors); + const errorsArray = response.data.errors; - errorsMap.map((item, index) => { - errorValidationToast(errorsArray[item][0], toastContainer); - }); - } - break; - case 429: - if (notification) errorTooManyToast(toastContainer); - break; - default: - if (notification) errorClientToast(toastContainer); - break; - } + errorsMap.map((item, index) => { + errorValidationToast(errorsArray[item][0], toastContainer); + }); + } + break; + case 429: + if (notification) errorTooManyToast(toastContainer); + break; + default: + if (notification) errorClientToast(toastContainer); + break; + } }; -export const errorResponse = ( - response, - notification, - toastContainer, - logout, -) => { - if (notification) toast.dismiss({ containerId: toastContainer }); - if (isServerError(response.status)) { - errorServer(response, notification, toastContainer); - } else if (isClientError(response.status)) { - errorClient(response, notification, toastContainer, logout); - } +export const errorResponse = (response, notification, toastContainer, logout) => { + if (notification) toast.dismiss({ containerId: toastContainer }); + if (isServerError(response.status)) { + errorServer(response, notification, toastContainer); + } else if (isClientError(response.status)) { + errorClient(response, notification, toastContainer, logout); + } }; diff --git a/src/core/utils/filterMenuItems.js b/src/core/utils/filterMenuItems.js index ad10189..bd35a95 100644 --- a/src/core/utils/filterMenuItems.js +++ b/src/core/utils/filterMenuItems.js @@ -1,19 +1,17 @@ export function filterMenuItems(items, _permissions = []) { - return items.reduce((acc, item) => { - if (item.permissions) { - if ( - item.permissions.some((permission) => _permissions.includes(permission)) - ) { - acc.push(item); - } - } else if (item.hasSubitems) { - const filteredSubItems = filterMenuItems(item.Subitems, _permissions); - if (filteredSubItems.length > 0) { - acc.push({ ...item, Subitems: filteredSubItems }); - } - } else { - acc.push(item); - } - return acc; - }, []); + return items.reduce((acc, item) => { + if (item.permissions) { + if (item.permissions.some((permission) => _permissions.includes(permission))) { + acc.push(item); + } + } else if (item.hasSubitems) { + const filteredSubItems = filterMenuItems(item.Subitems, _permissions); + if (filteredSubItems.length > 0) { + acc.push({ ...item, Subitems: filteredSubItems }); + } + } else { + acc.push(item); + } + return acc; + }, []); } diff --git a/src/core/utils/flattenArrayOfObjects.js b/src/core/utils/flattenArrayOfObjects.js index d503e5b..e4d5051 100644 --- a/src/core/utils/flattenArrayOfObjects.js +++ b/src/core/utils/flattenArrayOfObjects.js @@ -1,9 +1,9 @@ export const flattenArrayOfObjects = (array, key) => { - return array.reduce((acc, obj) => { - acc.push(obj); - if (Array.isArray(obj[key])) { - acc.push(...flattenArrayOfObjects(obj[key], key)); - } - return acc; - }, []); + return array.reduce((acc, obj) => { + acc.push(obj); + if (Array.isArray(obj[key])) { + acc.push(...flattenArrayOfObjects(obj[key], key)); + } + return acc; + }, []); }; diff --git a/src/core/utils/flattenObjectOfObjects.js b/src/core/utils/flattenObjectOfObjects.js index 50458dd..fb03576 100644 --- a/src/core/utils/flattenObjectOfObjects.js +++ b/src/core/utils/flattenObjectOfObjects.js @@ -1,12 +1,12 @@ export const flattenObjectOfObjects = (obj, res = {}) => { - for (let key in obj) { - if (obj.hasOwnProperty(key)) { - if (typeof obj[key] === "object" && obj[key] !== null) { - flattenObjectOfObjects(obj[key], res); - } else { - res[key] = obj[key]; - } + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + if (typeof obj[key] === "object" && obj[key] !== null) { + flattenObjectOfObjects(obj[key], res); + } else { + res[key] = obj[key]; + } + } } - } - return res; + return res; }; diff --git a/src/core/utils/getValueByPath.js b/src/core/utils/getValueByPath.js index a03958a..a31f76f 100644 --- a/src/core/utils/getValueByPath.js +++ b/src/core/utils/getValueByPath.js @@ -1,14 +1,14 @@ export const getValueByPath = (obj, path) => { - const keys = path.split("."); + const keys = path.split("."); - let value = obj; + let value = obj; - for (const key of keys) { - if (value === undefined) { - return undefined; + for (const key of keys) { + if (value === undefined) { + return undefined; + } + value = value[key]; } - value = value[key]; - } - return value; + return value; }; diff --git a/src/core/utils/headerMenu.js b/src/core/utils/headerMenu.js index cd33e61..5b987bf 100644 --- a/src/core/utils/headerMenu.js +++ b/src/core/utils/headerMenu.js @@ -1,15 +1,15 @@ const api = process.env.NEXT_PUBLIC_API_URL; export const headerMenu = [ - // { - // title: "تصادفات", - // subMenu: [ - // [ - // { - // title: "تصادفات روزانه", - // href: api + "/v2/daily_accidents/create", - // }, - // ], - // ], - // }, + // { + // title: "تصادفات", + // subMenu: [ + // [ + // { + // title: "تصادفات روزانه", + // href: api + "/v2/daily_accidents/create", + // }, + // ], + // ], + // }, ]; diff --git a/src/core/utils/isArrayEmpty.js b/src/core/utils/isArrayEmpty.js index 61f7c8d..81624fb 100644 --- a/src/core/utils/isArrayEmpty.js +++ b/src/core/utils/isArrayEmpty.js @@ -1,6 +1,6 @@ export default function isArrayEmpty(value) { - if (Array.isArray(value)) { - return value.length === 0 || value.every((v) => v === ""); - } - return value === "" || value === null || value === undefined; + if (Array.isArray(value)) { + return value.length === 0 || value.every((v) => v === ""); + } + return value === "" || value === null || value === undefined; } diff --git a/src/core/utils/nationalCodeValidation.js b/src/core/utils/nationalCodeValidation.js index 2afec8c..747f4cd 100644 --- a/src/core/utils/nationalCodeValidation.js +++ b/src/core/utils/nationalCodeValidation.js @@ -1,30 +1,30 @@ function validateNationalCode(code) { - const invalidCodes = [ - "1111111111", - "2222222222", - "3333333333", - "4444444444", - "5555555555", - "6666666666", - "7777777777", - "8888888888", - "9999999999", - ]; - if (invalidCodes.includes(code)) return false; + const invalidCodes = [ + "1111111111", + "2222222222", + "3333333333", + "4444444444", + "5555555555", + "6666666666", + "7777777777", + "8888888888", + "9999999999", + ]; + if (invalidCodes.includes(code)) return false; - const L = code.length; - if (L < 8 || parseInt(code, 10) === 0) return false; + const L = code.length; + if (L < 8 || parseInt(code, 10) === 0) return false; - code = code.padStart(10, "0"); - if (parseInt(code.substr(3, 6), 10) === 0) return false; + code = code.padStart(10, "0"); + if (parseInt(code.substr(3, 6), 10) === 0) return false; - const c = parseInt(code.charAt(9), 10); - let s = 0; - for (let i = 0; i < 9; i++) { - s += parseInt(code.charAt(i), 10) * (10 - i); - } - s = s % 11; - return (s < 2 && c === s) || (s >= 2 && c === 11 - s); + const c = parseInt(code.charAt(9), 10); + let s = 0; + for (let i = 0; i < 9; i++) { + s += parseInt(code.charAt(i), 10) * (10 - i); + } + s = s % 11; + return (s < 2 && c === s) || (s >= 2 && c === 11 - s); } export default validateNationalCode; diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js index 8a4b62e..8aa30ff 100644 --- a/src/core/utils/pageMenu.js +++ b/src/core/utils/pageMenu.js @@ -2,28 +2,28 @@ import { Settings } from "@mui/icons-material"; import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard"; export const pageMenu = [ - { - id: "dashboard", - label: "پیشخوان", - type: "page", - route: "/dashboard", - icon: , - permissions: ["all"], - }, - { - id: "systemManagment", - label: "مدیریت سامانه", - type: "menu", - icon: , - hasSubitems: true, - Subitems: [ - { - id: "systemManagment-users", - label: "کاربران", + { + id: "dashboard", + label: "پیشخوان", type: "page", - route: "/dashboard/users", - permissions: ["manage_users"], - }, - ], - }, + route: "/dashboard", + icon: , + permissions: ["all"], + }, + { + id: "systemManagment", + label: "مدیریت سامانه", + type: "menu", + icon: , + hasSubitems: true, + Subitems: [ + { + id: "systemManagment-users", + label: "کاربران", + type: "page", + route: "/dashboard/users", + permissions: ["manage_users"], + }, + ], + }, ]; diff --git a/src/core/utils/successRequest.js b/src/core/utils/successRequest.js index daa2ab7..7fbde71 100644 --- a/src/core/utils/successRequest.js +++ b/src/core/utils/successRequest.js @@ -3,8 +3,8 @@ import { toast } from "react-toastify"; import { successToast } from "@/core/components/Toasts/success"; export const successRequest = (notification, toastContainer) => { - if (notification) { - toast.dismiss({ containerId: toastContainer }); - successToast(toastContainer); - } + if (notification) { + toast.dismiss({ containerId: toastContainer }); + successToast(toastContainer); + } }; diff --git a/src/core/utils/theme.js b/src/core/utils/theme.js index 9ec62c4..4405609 100644 --- a/src/core/utils/theme.js +++ b/src/core/utils/theme.js @@ -2,31 +2,31 @@ import { createTheme } from "@mui/material"; const theme = createTheme({ - direction: "rtl", - typography: { - fontFamily: `IRANSansFaNum, sans-serif`, - fontSize: 12, - }, - palette: { - primary: { - main: "#1b4332", - contrastText: "#FFFFFF", + direction: "rtl", + typography: { + fontFamily: `IRANSansFaNum, sans-serif`, + fontSize: 12, }, - secondary: { - main: "#1B4043", - contrastText: "#FFFFFF", - }, - }, - components: { - MuiBackdrop: { - styleOverrides: { - root: { - backdropFilter: "blur(3px)", - backgroundColor: "rgba(0, 0, 0, 0.3)", + palette: { + primary: { + main: "#1b4332", + contrastText: "#FFFFFF", + }, + secondary: { + main: "#1B4043", + contrastText: "#FFFFFF", + }, + }, + components: { + MuiBackdrop: { + styleOverrides: { + root: { + backdropFilter: "blur(3px)", + backgroundColor: "rgba(0, 0, 0, 0.3)", + }, + }, }, - }, }, - }, }); export default theme; diff --git a/src/core/utils/utils.js b/src/core/utils/utils.js index fb9a24a..a0a320d 100644 --- a/src/core/utils/utils.js +++ b/src/core/utils/utils.js @@ -2,148 +2,119 @@ import { alpha, darken } from "@mui/material"; export const parseCSSVarId = (id) => id.replace(/[^a-zA-Z0-9]/g, "_"); -export const parseFromValuesOrFunc = (fn, arg) => - fn instanceof Function ? fn(arg) : fn; +export const parseFromValuesOrFunc = (fn, arg) => (fn instanceof Function ? fn(arg) : fn); export const getCommonToolbarStyles = ({ table }) => ({ - alignItems: "flex-start", - backgroundColor: table.options.mrtTheme.baseBackgroundColor, - display: "grid", - flexWrap: "wrap-reverse", - minHeight: "3.5rem", - overflow: "hidden", - position: "relative", - transition: "all 150ms ease-in-out", - zIndex: 1, + alignItems: "flex-start", + backgroundColor: table.options.mrtTheme.baseBackgroundColor, + display: "grid", + flexWrap: "wrap-reverse", + minHeight: "3.5rem", + overflow: "hidden", + position: "relative", + transition: "all 150ms ease-in-out", + zIndex: 1, }); export const getCommonTooltipProps = (placement) => ({ - disableInteractive: true, - enterDelay: 500, - enterNextDelay: 500, - placement, + disableInteractive: true, + enterDelay: 500, + enterNextDelay: 500, + placement, }); export const flipIconStyles = (theme) => - theme.direction === "rtl" - ? { style: { transform: "scaleX(-1)" } } - : undefined; + theme.direction === "rtl" ? { style: { transform: "scaleX(-1)" } } : undefined; export const getCommonPinnedCellStyles = ({ column, table, theme }) => { - const { baseBackgroundColor } = table.options.mrtTheme; - const isPinned = column?.getIsPinned(); + const { baseBackgroundColor } = table.options.mrtTheme; + const isPinned = column?.getIsPinned(); - return { - '&[data-pinned="true"]': { - "&:before": { - backgroundColor: alpha( - darken( - baseBackgroundColor, - theme.palette.mode === "dark" ? 0.05 : 0.01, - ), - 0.97, - ), - boxShadow: column - ? isPinned === "left" && column.getIsLastColumn(isPinned) - ? `-4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset` - : isPinned === "right" && column.getIsFirstColumn(isPinned) - ? `4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset` - : undefined - : undefined, - ...commonCellBeforeAfterStyles, - }, - }, - }; + return { + '&[data-pinned="true"]': { + "&:before": { + backgroundColor: alpha(darken(baseBackgroundColor, theme.palette.mode === "dark" ? 0.05 : 0.01), 0.97), + boxShadow: column + ? isPinned === "left" && column.getIsLastColumn(isPinned) + ? `-4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset` + : isPinned === "right" && column.getIsFirstColumn(isPinned) + ? `4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset` + : undefined + : undefined, + ...commonCellBeforeAfterStyles, + }, + }, + }; }; -export const getCommonMRTCellStyles = ({ - column, - header, - table, - tableCellProps, - theme, -}) => { - const { - getState, - options: { enableColumnVirtualization, layoutMode }, - } = table; - const { draggingColumn } = getState(); - const { columnDef } = column; - const { columnDefType } = columnDef; +export const getCommonMRTCellStyles = ({ column, header, table, tableCellProps, theme }) => { + const { + getState, + options: { enableColumnVirtualization, layoutMode }, + } = table; + const { draggingColumn } = getState(); + const { columnDef } = column; + const { columnDefType } = columnDef; - const isColumnPinned = - columnDef.columnDefType !== "group" && column.getIsPinned(); + const isColumnPinned = columnDef.columnDefType !== "group" && column.getIsPinned(); - const widthStyles = { - minWidth: `max(calc(var(--${header ? "header" : "col"}-${parseCSSVarId( - header?.id ?? column.id, - )}-size) * 1px), ${columnDef.minSize ?? 30}px)`, - width: `calc(var(--${header ? "header" : "col"}-${parseCSSVarId(header?.id ?? column.id)}-size) * 1px)`, - }; + const widthStyles = { + minWidth: `max(calc(var(--${header ? "header" : "col"}-${parseCSSVarId( + header?.id ?? column.id + )}-size) * 1px), ${columnDef.minSize ?? 30}px)`, + width: `calc(var(--${header ? "header" : "col"}-${parseCSSVarId(header?.id ?? column.id)}-size) * 1px)`, + }; - if (layoutMode === "grid") { - widthStyles.flex = `${ - [0, false].includes(columnDef.grow) - ? 0 - : `var(--${header ? "header" : "col"}-${parseCSSVarId(header?.id ?? column.id)}-size)` - } 0 auto`; - } else if (layoutMode === "grid-no-grow") { - widthStyles.flex = `${+(columnDef.grow || 0)} 0 auto`; - } + if (layoutMode === "grid") { + widthStyles.flex = `${ + [0, false].includes(columnDef.grow) + ? 0 + : `var(--${header ? "header" : "col"}-${parseCSSVarId(header?.id ?? column.id)}-size)` + } 0 auto`; + } else if (layoutMode === "grid-no-grow") { + widthStyles.flex = `${+(columnDef.grow || 0)} 0 auto`; + } - const pinnedStyles = isColumnPinned - ? { - ...getCommonPinnedCellStyles({ column, table, theme }), - left: - isColumnPinned === "left" - ? `${column.getStart("left")}px` - : undefined, - opacity: 0.97, - position: "sticky", - right: - isColumnPinned === "right" - ? `${column.getAfter("right")}px` - : undefined, - } - : {}; + const pinnedStyles = isColumnPinned + ? { + ...getCommonPinnedCellStyles({ column, table, theme }), + left: isColumnPinned === "left" ? `${column.getStart("left")}px` : undefined, + opacity: 0.97, + position: "sticky", + right: isColumnPinned === "right" ? `${column.getAfter("right")}px` : undefined, + } + : {}; - return { - backgroundColor: "inherit", - backgroundImage: "inherit", - display: layoutMode?.startsWith("grid") ? "flex" : undefined, - justifyContent: - columnDefType === "group" - ? "center" - : layoutMode?.startsWith("grid") - ? tableCellProps.align - : undefined, - opacity: - table.getState().draggingColumn?.id === column.id || - table.getState().hoveredColumn?.id === column.id - ? 0.5 - : 1, - position: "relative", - transition: enableColumnVirtualization - ? "none" - : `padding 150ms ease-in-out`, - zIndex: - column.getIsResizing() || draggingColumn?.id === column.id - ? 2 - : columnDefType !== "group" && isColumnPinned - ? 1 - : 0, - ...pinnedStyles, - ...widthStyles, - ...parseFromValuesOrFunc(tableCellProps?.sx, theme), - }; + return { + backgroundColor: "inherit", + backgroundImage: "inherit", + display: layoutMode?.startsWith("grid") ? "flex" : undefined, + justifyContent: + columnDefType === "group" ? "center" : layoutMode?.startsWith("grid") ? tableCellProps.align : undefined, + opacity: + table.getState().draggingColumn?.id === column.id || table.getState().hoveredColumn?.id === column.id + ? 0.5 + : 1, + position: "relative", + transition: enableColumnVirtualization ? "none" : `padding 150ms ease-in-out`, + zIndex: + column.getIsResizing() || draggingColumn?.id === column.id + ? 2 + : columnDefType !== "group" && isColumnPinned + ? 1 + : 0, + ...pinnedStyles, + ...widthStyles, + ...parseFromValuesOrFunc(tableCellProps?.sx, theme), + }; }; export const commonCellBeforeAfterStyles = { - content: '""', - height: "100%", - left: 0, - position: "absolute", - top: 0, - width: "100%", - zIndex: -1, + content: '""', + height: "100%", + left: 0, + position: "absolute", + top: 0, + width: "100%", + zIndex: -1, }; diff --git a/src/lib/contexts/DataTable.js b/src/lib/contexts/DataTable.js index 28899d6..60ef071 100644 --- a/src/lib/contexts/DataTable.js +++ b/src/lib/contexts/DataTable.js @@ -7,205 +7,182 @@ import { LinearProgress } from "@mui/material"; export const DataTableContext = createContext(); -const DataTableProvider = ({ - children, - user_id, - page_name, - table_name, - columns, - initialSort = [], -}) => { - const { settingStore } = useTableSetting(); - const [isInitStates, setInitStates] = useState(false); - const flatColumns = flattenArrayOfObjects(columns, "columns"); - const [initFilter, setInitFilter] = useState({}); - const [filterData, setFilterData] = useState({}); - const [initSort, setInitSort] = useState(initialSort || []); - const [sortData, setSortData] = useState(initialSort || []); - const [initHide, setInitHide] = useState({}); - const [hideData, setHideData] = useState({}); - const [isDirty, setIsDirty] = useState(false); - const [isAnyDirty, setIsAnyDirty] = useState(false); +const DataTableProvider = ({ children, user_id, page_name, table_name, columns, initialSort = [] }) => { + const { settingStore } = useTableSetting(); + const [isInitStates, setInitStates] = useState(false); + const flatColumns = flattenArrayOfObjects(columns, "columns"); + const [initFilter, setInitFilter] = useState({}); + const [filterData, setFilterData] = useState({}); + const [initSort, setInitSort] = useState(initialSort || []); + const [sortData, setSortData] = useState(initialSort || []); + const [initHide, setInitHide] = useState({}); + const [hideData, setHideData] = useState({}); + const [isDirty, setIsDirty] = useState(false); + const [isAnyDirty, setIsAnyDirty] = useState(false); - useEffect(() => { - let hasAnyConflict = false; - const hasConflict = - JSON.stringify(hideData) !== JSON.stringify(initHide) || - JSON.stringify(sortData) !== JSON.stringify(initSort) || - JSON.stringify(filterData) !== JSON.stringify(initFilter); + useEffect(() => { + let hasAnyConflict = false; + const hasConflict = + JSON.stringify(hideData) !== JSON.stringify(initHide) || + JSON.stringify(sortData) !== JSON.stringify(initSort) || + JSON.stringify(filterData) !== JSON.stringify(initFilter); - const CheckFilterValues = Object.values(filterData).every((innerObject) => { - if ( - innerObject.datatype === "date" && - innerObject.filterMode === "between" - ) { - return ( - Array.isArray(innerObject.value) && - innerObject.value.length === 2 && - innerObject.value.every((v) => v === "") - ); - } else { - return innerObject.value === ""; - } - }); - const flattenObject = (obj) => { - let result = {}; - for (const key in obj) { - if (typeof obj[key] === "object" && obj[key] !== null) { - Object.assign(result, flattenObject(obj[key])); // باز کردن اشیای تودرتو - } else { - result[key] = obj[key]; - } - } - return result; - }; - - // تبدیل آبجکت به آبجکت فلت شده - const flatHideData = flattenObject(hideData); - - const CheckHideValues = Object.values(flatHideData).every( - (value) => value === true, - ); - hasAnyConflict = - !CheckHideValues || - JSON.stringify(sortData) !== JSON.stringify(initialSort) || - !CheckFilterValues; - - setIsDirty(hasConflict); - setIsAnyDirty(hasAnyConflict); - }, [hideData, sortData, filterData, initHide, initSort, initFilter]); - - useEffect(() => { - if (!settingStore) return; - const filterValues = flatColumns.reduce((acc, column) => { - if (!column.enableColumnFilter) return acc; - const storeFilter = settingStore?.[user_id]?.[page_name]?.[table_name]?.[ - "filters" - ]?.find((filter) => filter.id === column.id); - if (column.datatype === "array") { - acc[column.id] = { - id: column.id, - value: storeFilter?.value || [], - filterMode: storeFilter?.filterMode || column.filterMode, - datatype: column.datatype, - }; - } else if (column.filterMode === "between") { - acc[column.id] = { - id: column.id, - value: storeFilter?.value || ["", ""], - filterMode: storeFilter?.filterMode || column.filterMode, - datatype: column.datatype, - }; - } else { - acc[column.id] = { - id: column.id, - value: storeFilter?.value || "", - filterMode: storeFilter?.filterMode || column.filterMode, - datatype: column.datatype, - }; - } - return acc; - }, {}); - - const getHideValues = (columns) => { - return columns.reduce((acc, column) => { - const columnId = column.id; - const storeHide = - settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"]?.[ - columnId - ]; - if (column.columns && column.columns.length > 0) { - acc[columnId] = getHideValues(column.columns); - } else { - acc[columnId] = storeHide !== undefined ? storeHide : true; - } - - return acc; - }, {}); - }; - - const hideValues = getHideValues(columns); - setHideData(hideValues); - setInitHide(hideValues); - setFilterData(filterValues); - setInitFilter(filterValues); - setSortData( - settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || - initialSort, - ); - setInitSort( - settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || - initialSort, - ); - setInitStates(true); - }, [settingStore]); - - useEffect(() => { - if ( - JSON.stringify(initFilter) !== JSON.stringify(filterData) || - JSON.stringify(initSort) !== JSON.stringify(sortData) || - JSON.stringify(initHide) !== JSON.stringify(hideData) - ) { - if (!toast.isActive("keep_data", "filtering")) { - toast( - , - { - containerId: "filtering", - toastId: "keep_data", - className: "filter-toast", - position: "bottom-left", - draggable: true, - autoClose: false, - }, - ); - } else { - toast.update("keep_data", { - containerId: "filtering", - toastId: "keep_data", - render: ( - - ), + const CheckFilterValues = Object.values(filterData).every((innerObject) => { + if (innerObject.datatype === "date" && innerObject.filterMode === "between") { + return ( + Array.isArray(innerObject.value) && + innerObject.value.length === 2 && + innerObject.value.every((v) => v === "") + ); + } else { + return innerObject.value === ""; + } }); - } - } else { - toast.dismiss({ containerId: "datatable" }); - } - }, [filterData, sortData, hideData]); + const flattenObject = (obj) => { + let result = {}; + for (const key in obj) { + if (typeof obj[key] === "object" && obj[key] !== null) { + Object.assign(result, flattenObject(obj[key])); // باز کردن اشیای تودرتو + } else { + result[key] = obj[key]; + } + } + return result; + }; - if (!isInitStates) return ; + // تبدیل آبجکت به آبجکت فلت شده + const flatHideData = flattenObject(hideData); - return ( - - {children} - - ); + const CheckHideValues = Object.values(flatHideData).every((value) => value === true); + hasAnyConflict = + !CheckHideValues || JSON.stringify(sortData) !== JSON.stringify(initialSort) || !CheckFilterValues; + + setIsDirty(hasConflict); + setIsAnyDirty(hasAnyConflict); + }, [hideData, sortData, filterData, initHide, initSort, initFilter]); + + useEffect(() => { + if (!settingStore) return; + const filterValues = flatColumns.reduce((acc, column) => { + if (!column.enableColumnFilter) return acc; + const storeFilter = settingStore?.[user_id]?.[page_name]?.[table_name]?.["filters"]?.find( + (filter) => filter.id === column.id + ); + if (column.datatype === "array") { + acc[column.id] = { + id: column.id, + value: storeFilter?.value || [], + filterMode: storeFilter?.filterMode || column.filterMode, + datatype: column.datatype, + }; + } else if (column.filterMode === "between") { + acc[column.id] = { + id: column.id, + value: storeFilter?.value || ["", ""], + filterMode: storeFilter?.filterMode || column.filterMode, + datatype: column.datatype, + }; + } else { + acc[column.id] = { + id: column.id, + value: storeFilter?.value || "", + filterMode: storeFilter?.filterMode || column.filterMode, + datatype: column.datatype, + }; + } + return acc; + }, {}); + + const getHideValues = (columns) => { + return columns.reduce((acc, column) => { + const columnId = column.id; + const storeHide = settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"]?.[columnId]; + if (column.columns && column.columns.length > 0) { + acc[columnId] = getHideValues(column.columns); + } else { + acc[columnId] = storeHide !== undefined ? storeHide : true; + } + + return acc; + }, {}); + }; + + const hideValues = getHideValues(columns); + setHideData(hideValues); + setInitHide(hideValues); + setFilterData(filterValues); + setInitFilter(filterValues); + setSortData(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || initialSort); + setInitSort(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || initialSort); + setInitStates(true); + }, [settingStore]); + + useEffect(() => { + if ( + JSON.stringify(initFilter) !== JSON.stringify(filterData) || + JSON.stringify(initSort) !== JSON.stringify(sortData) || + JSON.stringify(initHide) !== JSON.stringify(hideData) + ) { + if (!toast.isActive("keep_data", "filtering")) { + toast( + , + { + containerId: "filtering", + toastId: "keep_data", + className: "filter-toast", + position: "bottom-left", + draggable: true, + autoClose: false, + } + ); + } else { + toast.update("keep_data", { + containerId: "filtering", + toastId: "keep_data", + render: ( + + ), + }); + } + } else { + toast.dismiss({ containerId: "datatable" }); + } + }, [filterData, sortData, hideData]); + + if (!isInitStates) return ; + + return ( + + {children} + + ); }; export default DataTableProvider; diff --git a/src/lib/contexts/auth.js b/src/lib/contexts/auth.js index e56dd22..a8d3784 100644 --- a/src/lib/contexts/auth.js +++ b/src/lib/contexts/auth.js @@ -1,109 +1,99 @@ "use client"; import { GET_USER_ROUTE } from "@/core/utils/routes"; import axios from "axios"; -import { - createContext, - useCallback, - useContext, - useEffect, - useReducer, - useState, -} from "react"; +import { createContext, useCallback, useContext, useEffect, useReducer, useState } from "react"; const initAuth = { - initAuthState: false, - isAuth: false, - user: {}, + initAuthState: false, + isAuth: false, + user: {}, }; const authReducer = (state, action) => { - switch (action.type) { - case "CLEAR_USER": - return { ...state, user: {} }; - case "CHANGE_USER": - return { ...state, user: action.user }; - case "CHANGE_AUTH_STATE": - return { ...state, isAuth: action.isAuth }; - case "CHANGE_INIT_AUTH": - return { ...state, initAuthState: action.initAuthState }; - default: - return state; - } + switch (action.type) { + case "CLEAR_USER": + return { ...state, user: {} }; + case "CHANGE_USER": + return { ...state, user: action.user }; + case "CHANGE_AUTH_STATE": + return { ...state, isAuth: action.isAuth }; + case "CHANGE_INIT_AUTH": + return { ...state, initAuthState: action.initAuthState }; + default: + return state; + } }; const AuthContext = createContext(); export const AuthProvider = ({ children }) => { - const [errorState, setErrorState] = useState({ status: null, message: "" }); - const [state, dispatch] = useReducer(authReducer, initAuth); + const [errorState, setErrorState] = useState({ status: null, message: "" }); + const [state, dispatch] = useReducer(authReducer, initAuth); - const clearUser = useCallback(() => { - dispatch({ type: "CLEAR_USER" }); - }, []); + const clearUser = useCallback(() => { + dispatch({ type: "CLEAR_USER" }); + }, []); - const changeUser = useCallback((user) => { - dispatch({ type: "CHANGE_USER", user }); - }, []); + const changeUser = useCallback((user) => { + dispatch({ type: "CHANGE_USER", user }); + }, []); - const changeAuthState = useCallback((isAuth) => { - dispatch({ type: "CHANGE_AUTH_STATE", isAuth }); - }, []); + const changeAuthState = useCallback((isAuth) => { + dispatch({ type: "CHANGE_AUTH_STATE", isAuth }); + }, []); - const changeInitAuth = useCallback((initAuthState) => { - dispatch({ type: "CHANGE_INIT_AUTH", initAuthState }); - }, []); + const changeInitAuth = useCallback((initAuthState) => { + dispatch({ type: "CHANGE_INIT_AUTH", initAuthState }); + }, []); - const logout = () => { - clearUser(); - changeAuthState(false); - changeInitAuth(true); - }; - - const getUser = useCallback(async () => { - try { - const { data } = await axios.get(GET_USER_ROUTE, { - withCredentials: true, - }); - changeUser(data.data); - changeAuthState(true); - changeInitAuth(true); - setErrorState(false); - } catch (error) { - if (error.response && error.response.status === 401) { + const logout = () => { clearUser(); changeAuthState(false); changeInitAuth(true); - return; - } - let status = - error.response && error.response.status - ? error.response.status - : "نامشخص"; - setErrorState({ - status, - message: " مشکلی در احراز هویت رخ داده است . دقایقی بعد امتحان کنید!!!", - }); - } - }, [clearUser, changeUser, changeAuthState, changeInitAuth]); + }; - useEffect(() => { - getUser(); - }, []); + const getUser = useCallback(async () => { + try { + const { data } = await axios.get(GET_USER_ROUTE, { + withCredentials: true, + }); + changeUser(data.data); + changeAuthState(true); + changeInitAuth(true); + setErrorState(false); + } catch (error) { + if (error.response && error.response.status === 401) { + clearUser(); + changeAuthState(false); + changeInitAuth(true); + return; + } + let status = error.response && error.response.status ? error.response.status : "نامشخص"; + setErrorState({ + status, + message: " مشکلی در احراز هویت رخ داده است . دقایقی بعد امتحان کنید!!!", + }); + } + }, [clearUser, changeUser, changeAuthState, changeInitAuth]); - return ( - - {children} - - ); + useEffect(() => { + getUser(); + }, []); + + return ( + + {children} + + ); }; export const useAuth = () => useContext(AuthContext); diff --git a/src/lib/contexts/call.js b/src/lib/contexts/call.js index df634b2..f42f7a1 100644 --- a/src/lib/contexts/call.js +++ b/src/lib/contexts/call.js @@ -1,106 +1,95 @@ "use client"; -import { - createContext, - useReducer, - useState, - useCallback, - useMemo, - useContext, -} from "react"; +import { createContext, useReducer, useState, useCallback, useMemo, useContext } from "react"; const reducer = (state, action) => { - switch (action.type) { - case "CHANGE_ACTIVE_TAB": - return state.map((call, index) => ({ - ...call, - active: index === action.index_call, - })); - case "CHANGE_LIST": - return [...action.new_list]; - case "CHANGE_ACTIVE_CATEGORY_ID": - return state.map((call) => - call.id === action.tab_id - ? { ...call, active_category_id: action.category_id } - : call, - ); - default: - return state; - } + switch (action.type) { + case "CHANGE_ACTIVE_TAB": + return state.map((call, index) => ({ + ...call, + active: index === action.index_call, + })); + case "CHANGE_LIST": + return [...action.new_list]; + case "CHANGE_ACTIVE_CATEGORY_ID": + return state.map((call) => + call.id === action.tab_id ? { ...call, active_category_id: action.category_id } : call + ); + default: + return state; + } }; export const CallContext = createContext(null); export const CallProvider = ({ children }) => { - const [openCallDialog, setOpenCallDialog] = useState(false); - const [activeCall, setActiveCall] = useState(0); - const [calls, dispatch] = useReducer(reducer, []); + const [openCallDialog, setOpenCallDialog] = useState(false); + const [activeCall, setActiveCall] = useState(0); + const [calls, dispatch] = useReducer(reducer, []); - const changeActiveTab = useCallback((index_call) => { - dispatch({ type: "CHANGE_ACTIVE_TAB", index_call }); - }, []); + const changeActiveTab = useCallback((index_call) => { + dispatch({ type: "CHANGE_ACTIVE_TAB", index_call }); + }, []); - const changeList = useCallback((new_list) => { - dispatch({ type: "CHANGE_LIST", new_list }); - }, []); + const changeList = useCallback((new_list) => { + dispatch({ type: "CHANGE_LIST", new_list }); + }, []); - const changeActiveCategoryId = useCallback((tab_id, category_id) => { - dispatch({ type: "CHANGE_ACTIVE_CATEGORY_ID", tab_id, category_id }); - }, []); + const changeActiveCategoryId = useCallback((tab_id, category_id) => { + dispatch({ type: "CHANGE_ACTIVE_CATEGORY_ID", tab_id, category_id }); + }, []); - const changeActiveTabCall = (newValue) => { - changeActiveTab(newValue); - setActiveCall(newValue); - }; + const changeActiveTabCall = (newValue) => { + changeActiveTab(newValue); + setActiveCall(newValue); + }; - const newCall = useCallback( - (data) => { - const newCall = { - id: data.id, - phone_number: data.phone_number, - date: new Date(), - active: true, - active_category_id: null, - }; - const newList = [...calls, newCall]; - changeList(newList); - changeActiveTabCall(newList.length - 1); - }, - [calls], - ); + const newCall = useCallback( + (data) => { + const newCall = { + id: data.id, + phone_number: data.phone_number, + date: new Date(), + active: true, + active_category_id: null, + }; + const newList = [...calls, newCall]; + changeList(newList); + changeActiveTabCall(newList.length - 1); + }, + [calls] + ); - const closeCall = useCallback( - (id) => { - const index = calls.findIndex((answer) => answer.id === id); - const newIndex = index === 0 ? 0 : index - 1; - const newList = [...calls]; - newList.splice(index, 1); - if (newList.length !== 0) { - newList[newIndex].active = true; - changeActiveTabCall(newIndex); - } - changeList(newList); - }, - [calls], - ); + const closeCall = useCallback( + (id) => { + const index = calls.findIndex((answer) => answer.id === id); + const newIndex = index === 0 ? 0 : index - 1; + const newList = [...calls]; + newList.splice(index, 1); + if (newList.length !== 0) { + newList[newIndex].active = true; + changeActiveTabCall(newIndex); + } + changeList(newList); + }, + [calls] + ); - const contextValue = useMemo( - () => ({ - openCallDialog, - setOpenCallDialog, - calls, - newCall, - closeCall, - activeCall, - setActiveCall, - changeActiveCategoryId, - changeActiveTabCall, - }), - [openCallDialog, calls, activeCall], - ); + const contextValue = useMemo( + () => ({ + openCallDialog, + setOpenCallDialog, + calls, + newCall, + closeCall, + activeCall, + setActiveCall, + changeActiveCategoryId, + changeActiveTabCall, + }), + [openCallDialog, calls, activeCall] + ); - return ( - {children} - ); + return {children}; }; export const useCall = () => useContext(CallContext); diff --git a/src/lib/contexts/category.js b/src/lib/contexts/category.js index 79e8360..4db143d 100644 --- a/src/lib/contexts/category.js +++ b/src/lib/contexts/category.js @@ -1,72 +1,57 @@ import { GET_CATEGORY } from "@/core/utils/routes"; -import { - createContext, - useCallback, - useContext, - useEffect, - useMemo, - useReducer, -} from "react"; +import { createContext, useCallback, useContext, useEffect, useMemo, useReducer } from "react"; import useRequest from "../hooks/useRequest"; const initialState = { - categoryLists: [], - subCategoryLists: [], - active_category_id: null, + categoryLists: [], + subCategoryLists: [], + active_category_id: null, }; const reducer = (state, action) => { - switch (action.type) { - case "SET_CATEGORIES": - return { ...state, categoryLists: action.payload }; - case "SET_SUBCATEGORIES": - return { ...state, subCategoryLists: action.payload }; - default: - return state; - } + switch (action.type) { + case "SET_CATEGORIES": + return { ...state, categoryLists: action.payload }; + case "SET_SUBCATEGORIES": + return { ...state, subCategoryLists: action.payload }; + default: + return state; + } }; export const CategoriesContext = createContext(null); export const CategoriesProvider = ({ children }) => { - const requestServer = useRequest({ notificationShow: false }); + const requestServer = useRequest({ notificationShow: false }); - const [state, dispatch] = useReducer(reducer, initialState); + const [state, dispatch] = useReducer(reducer, initialState); - useEffect(() => { - const fetchCategories = async () => { - try { - const { data } = await requestServer(GET_CATEGORY, "get"); - const subCategories = data.data; + useEffect(() => { + const fetchCategories = async () => { + try { + const { data } = await requestServer(GET_CATEGORY, "get"); + const subCategories = data.data; - const categories = Array.from( - new Map( - subCategories.map((item) => [item.category_id, item]), - ).values(), - ); + const categories = Array.from(new Map(subCategories.map((item) => [item.category_id, item])).values()); - dispatch({ type: "SET_CATEGORIES", payload: categories }); - dispatch({ type: "SET_SUBCATEGORIES", payload: subCategories }); - } catch (error) {} - }; + dispatch({ type: "SET_CATEGORIES", payload: categories }); + dispatch({ type: "SET_SUBCATEGORIES", payload: subCategories }); + } catch (error) {} + }; - fetchCategories(); - }, []); + fetchCategories(); + }, []); - const contextValue = useMemo( - () => ({ - categoryLists: state.categoryLists, - subCategoryLists: state.subCategoryLists, - active_category_id: state.active_category_id, - }), - [state], - ); + const contextValue = useMemo( + () => ({ + categoryLists: state.categoryLists, + subCategoryLists: state.subCategoryLists, + active_category_id: state.active_category_id, + }), + [state] + ); - return ( - - {children} - - ); + return {children}; }; export const useCategory = () => useContext(CategoriesContext); diff --git a/src/lib/contexts/socket.js b/src/lib/contexts/socket.js index a103a3a..f989e55 100644 --- a/src/lib/contexts/socket.js +++ b/src/lib/contexts/socket.js @@ -1,129 +1,111 @@ "use client"; import { Power, PowerOff } from "@mui/icons-material"; -import { - createContext, - useContext, - useEffect, - useMemo, - useRef, - useState, - useCallback, -} from "react"; +import { createContext, useContext, useEffect, useMemo, useRef, useState, useCallback } from "react"; import { toast } from "react-toastify"; import { io } from "socket.io-client"; import { useAuth } from "./auth"; const SocketContext = createContext({ - socket: null, - status: "", + socket: null, + status: "", }); export const useSocket = () => useContext(SocketContext); export const SocketProvider = ({ children }) => { - const { user } = useAuth(); - const socketToastId = useRef(null); - const [status, setStatus] = useState(""); - const [clientsOnline, setClientsOnline] = useState([]); + const { user } = useAuth(); + const socketToastId = useRef(null); + const [status, setStatus] = useState(""); + const [clientsOnline, setClientsOnline] = useState([]); - const socket = useMemo(() => { - return io(`${process.env.NEXT_PUBLIC_SERVER_SOCKET_URL}`, { - path: "/notification/socket.io", - autoConnect: false, - auth: { token: null }, - }); - }, []); - - useEffect(() => { - if (user?.telephone_id) { - socket.auth.token = { telephone_id: user.telephone_id, user_id: user.id }; - } - }, [user, socket]); - - const handleConnect = useCallback(() => setStatus("connected"), []); - const handleDisconnect = useCallback(() => setStatus("disconnected"), []); - const handleConnectError = useCallback(() => setStatus("error"), []); - - useEffect(() => { - socket.on("connect", handleConnect); - socket.on("disconnect", handleDisconnect); - socket.on("connect_error", handleConnectError); - - return () => { - socket.off("connect", handleConnect); - socket.off("disconnect", handleDisconnect); - socket.off("connect_error", handleConnectError); - }; - }, [socket, handleConnect, handleDisconnect, handleConnectError]); - - useEffect(() => { - if (status === "connected") { - toast.update(socketToastId.current, { - containerId: "socket_connection", - type: "success", - render: "ارتباط با سرور برقرار شد", - autoClose: 2000, - closeButton: true, - closeOnClick: true, - icon: ({ theme, type }) => , - }); - } else if (status === "error" || status === "disconnected") { - if (socketToastId.current) { - toast.update(socketToastId.current, { - containerId: "socket_connection", - type: "warning", - render: "ارتباط با سرور قطع شد. در حال تلاش برای بازیابی…", - autoClose: false, - closeButton: false, - draggable: false, - icon: ({ theme, type }) => , + const socket = useMemo(() => { + return io(`${process.env.NEXT_PUBLIC_SERVER_SOCKET_URL}`, { + path: "/notification/socket.io", + autoConnect: false, + auth: { token: null }, }); - } else { - socketToastId.current = toast.warn( - "ارتباط با سرور قطع شد. در حال تلاش برای بازیابی…", - { - containerId: "socket_connection", - autoClose: false, - closeButton: false, - draggable: false, - icon: ({ theme, type }) => , - }, - ); - } - } - }, [status]); + }, []); - useEffect(() => { - if (status == "connected") return; + useEffect(() => { + if (user?.telephone_id) { + socket.auth.token = { telephone_id: user.telephone_id, user_id: user.id }; + } + }, [user, socket]); - socket.connect(); + const handleConnect = useCallback(() => setStatus("connected"), []); + const handleDisconnect = useCallback(() => setStatus("disconnected"), []); + const handleConnectError = useCallback(() => setStatus("error"), []); - return () => { - socket.disconnect(); - }; - }, [socket]); + useEffect(() => { + socket.on("connect", handleConnect); + socket.on("disconnect", handleDisconnect); + socket.on("connect_error", handleConnectError); - useEffect(() => { - const handleNotification = (data) => { - setClientsOnline(data.clients); - }; - socket.on("onlineClientsUpdated", handleNotification); + return () => { + socket.off("connect", handleConnect); + socket.off("disconnect", handleDisconnect); + socket.off("connect_error", handleConnectError); + }; + }, [socket, handleConnect, handleDisconnect, handleConnectError]); - return () => { - socket.off("onlineClientsUpdated", handleNotification); - }; - }, [socket]); + useEffect(() => { + if (status === "connected") { + toast.update(socketToastId.current, { + containerId: "socket_connection", + type: "success", + render: "ارتباط با سرور برقرار شد", + autoClose: 2000, + closeButton: true, + closeOnClick: true, + icon: ({ theme, type }) => , + }); + } else if (status === "error" || status === "disconnected") { + if (socketToastId.current) { + toast.update(socketToastId.current, { + containerId: "socket_connection", + type: "warning", + render: "ارتباط با سرور قطع شد. در حال تلاش برای بازیابی…", + autoClose: false, + closeButton: false, + draggable: false, + icon: ({ theme, type }) => , + }); + } else { + socketToastId.current = toast.warn("ارتباط با سرور قطع شد. در حال تلاش برای بازیابی…", { + containerId: "socket_connection", + autoClose: false, + closeButton: false, + draggable: false, + icon: ({ theme, type }) => , + }); + } + } + }, [status]); - const contextValue = useMemo( - () => ({ socket, status, clientsOnline }), - [socket, status, clientsOnline], - ); + useEffect(() => { + if (status == "connected") return; - return ( - - {children} - - ); + socket.connect(); + + return () => { + socket.disconnect(); + }; + }, [socket]); + + useEffect(() => { + const handleNotification = (data) => { + setClientsOnline(data.clients); + }; + socket.on("onlineClientsUpdated", handleNotification); + + return () => { + socket.off("onlineClientsUpdated", handleNotification); + }; + }, [socket]); + + const contextValue = useMemo(() => ({ socket, status, clientsOnline }), [socket, status, clientsOnline]); + + return {children}; }; export default SocketContext; diff --git a/src/lib/contexts/tableSetting.js b/src/lib/contexts/tableSetting.js index 6009f88..bde0505 100644 --- a/src/lib/contexts/tableSetting.js +++ b/src/lib/contexts/tableSetting.js @@ -6,184 +6,137 @@ import LZString from "lz-string"; export const TableSettingContext = createContext(); const decompressData = (compressedData) => { - try { - const decompressed = LZString.decompressFromUTF16(compressedData); - if (decompressed === null) { - localStorage.removeItem("_setting-app"); - return null; - } else { - return JSON.parse(decompressed); + try { + const decompressed = LZString.decompressFromUTF16(compressedData); + if (decompressed === null) { + localStorage.removeItem("_setting-app"); + return null; + } else { + return JSON.parse(decompressed); + } + } catch (error) { + localStorage.removeItem("_setting-app"); + return null; } - } catch (error) { - localStorage.removeItem("_setting-app"); - return null; - } }; export const TableSettingProvider = ({ children }) => { - const [settingStore, setSettingStore] = useState({}); + const [settingStore, setSettingStore] = useState({}); - useEffect(() => { - const compressedData = localStorage.getItem("_setting-app"); + useEffect(() => { + const compressedData = localStorage.getItem("_setting-app"); - const data = compressedData ? decompressData(compressedData) : null; - if (data) { - setSettingStore(data); - } - }, []); + const data = compressedData ? decompressData(compressedData) : null; + if (data) { + setSettingStore(data); + } + }, []); - const hideAction = useCallback( - (user_id, page_name, table_name, settingValue) => { - clearAction(user_id, page_name, table_name, "hides"); - updateSettingStorage( - user_id, - page_name, - table_name, - "hides", - settingValue, - ); - }, - [], - ); + const hideAction = useCallback((user_id, page_name, table_name, settingValue) => { + clearAction(user_id, page_name, table_name, "hides"); + updateSettingStorage(user_id, page_name, table_name, "hides", settingValue); + }, []); - const sortAction = useCallback( - (user_id, page_name, table_name, settingValue) => { - updateSettingStorage( - user_id, - page_name, - table_name, - "sorts", - settingValue, - ); - }, - [], - ); + const sortAction = useCallback((user_id, page_name, table_name, settingValue) => { + updateSettingStorage(user_id, page_name, table_name, "sorts", settingValue); + }, []); - const filterAction = (user_id, page_name, table_name, settingValue) => { - updateSettingStorage( - user_id, - page_name, - table_name, - "filters", - settingValue, - ); - }; - - const resetAction = (user_id, page_name, table_name) => { - const compressedData = localStorage.getItem("_setting-app"); - const prevLocalStorage = compressedData - ? decompressData(compressedData) - : {}; - - const userSettings = prevLocalStorage[user_id] || {}; - const pageSettings = userSettings[page_name] || {}; - delete pageSettings[table_name]; - - const resetData = { - ...prevLocalStorage, - [user_id]: { - ...userSettings, - [page_name]: { - ...pageSettings, - }, - }, + const filterAction = (user_id, page_name, table_name, settingValue) => { + updateSettingStorage(user_id, page_name, table_name, "filters", settingValue); }; - localStorage.setItem( - "_setting-app", - LZString.compressToUTF16(JSON.stringify(resetData)), - ); - setSettingStore(resetData); - }; + const resetAction = (user_id, page_name, table_name) => { + const compressedData = localStorage.getItem("_setting-app"); + const prevLocalStorage = compressedData ? decompressData(compressedData) : {}; - const updateSettingStorage = ( - user_id, - page_name, - table_name, - settingType, - settingValue, - ) => { - const compressedData = localStorage.getItem("_setting-app"); - const prevLocalStorage = compressedData - ? decompressData(compressedData) - : {}; + const userSettings = prevLocalStorage[user_id] || {}; + const pageSettings = userSettings[page_name] || {}; + delete pageSettings[table_name]; - const userSettings = prevLocalStorage[user_id] || {}; - const pageSettings = userSettings[page_name] || {}; - const tableSettings = pageSettings[table_name] || {}; + const resetData = { + ...prevLocalStorage, + [user_id]: { + ...userSettings, + [page_name]: { + ...pageSettings, + }, + }, + }; - let newSettings; - if (settingType === "sorts" || settingType === "filters") { - newSettings = [...settingValue]; - } else { - newSettings = { ...(tableSettings[settingType] || {}), ...settingValue }; - } - - const updatedLocalStorage = { - ...prevLocalStorage, - [user_id]: { - ...userSettings, - [page_name]: { - ...pageSettings, - [table_name]: { - ...tableSettings, - [settingType]: Array.isArray(settingValue) - ? [...newSettings] - : { ...newSettings }, - }, - }, - }, + localStorage.setItem("_setting-app", LZString.compressToUTF16(JSON.stringify(resetData))); + setSettingStore(resetData); }; - localStorage.setItem( - "_setting-app", - LZString.compressToUTF16(JSON.stringify(updatedLocalStorage)), - ); - setSettingStore(updatedLocalStorage); - }; + const updateSettingStorage = (user_id, page_name, table_name, settingType, settingValue) => { + const compressedData = localStorage.getItem("_setting-app"); + const prevLocalStorage = compressedData ? decompressData(compressedData) : {}; - const clearAction = (user_id, page_name, table_name, key) => { - const compressedData = localStorage.getItem("_setting-app"); - const prevLocalStorage = compressedData - ? decompressData(compressedData) - : {}; + const userSettings = prevLocalStorage[user_id] || {}; + const pageSettings = userSettings[page_name] || {}; + const tableSettings = pageSettings[table_name] || {}; - const userSettings = prevLocalStorage[user_id] || {}; - const pageSettings = userSettings[page_name] || {}; - const tableSettings = pageSettings[table_name] || {}; + let newSettings; + if (settingType === "sorts" || settingType === "filters") { + newSettings = [...settingValue]; + } else { + newSettings = { ...(tableSettings[settingType] || {}), ...settingValue }; + } - const updatedSettings = { - ...prevLocalStorage, - [user_id]: { - ...userSettings, - [page_name]: { - ...pageSettings, - [table_name]: { - ...tableSettings, - [key]: Array.isArray(tableSettings[key]) ? [] : {}, - }, - }, - }, + const updatedLocalStorage = { + ...prevLocalStorage, + [user_id]: { + ...userSettings, + [page_name]: { + ...pageSettings, + [table_name]: { + ...tableSettings, + [settingType]: Array.isArray(settingValue) ? [...newSettings] : { ...newSettings }, + }, + }, + }, + }; + + localStorage.setItem("_setting-app", LZString.compressToUTF16(JSON.stringify(updatedLocalStorage))); + setSettingStore(updatedLocalStorage); }; - localStorage.setItem( - "_setting-app", - LZString.compressToUTF16(JSON.stringify(updatedSettings)), - ); - setSettingStore(updatedSettings); - }; + const clearAction = (user_id, page_name, table_name, key) => { + const compressedData = localStorage.getItem("_setting-app"); + const prevLocalStorage = compressedData ? decompressData(compressedData) : {}; - return ( - - {children} - - ); + const userSettings = prevLocalStorage[user_id] || {}; + const pageSettings = userSettings[page_name] || {}; + const tableSettings = pageSettings[table_name] || {}; + + const updatedSettings = { + ...prevLocalStorage, + [user_id]: { + ...userSettings, + [page_name]: { + ...pageSettings, + [table_name]: { + ...tableSettings, + [key]: Array.isArray(tableSettings[key]) ? [] : {}, + }, + }, + }, + }; + + localStorage.setItem("_setting-app", LZString.compressToUTF16(JSON.stringify(updatedSettings))); + setSettingStore(updatedSettings); + }; + + return ( + + {children} + + ); }; diff --git a/src/lib/hooks/useCallerHistory.js b/src/lib/hooks/useCallerHistory.js index 21cee61..10da59f 100644 --- a/src/lib/hooks/useCallerHistory.js +++ b/src/lib/hooks/useCallerHistory.js @@ -3,47 +3,45 @@ import useRequest from "./useRequest"; import { GET_CALLER_HISTORY } from "@/core/utils/routes"; const useCallerHistory = (callId, phoneNumber, maxSize) => { - const requestServer = useRequest(); + const requestServer = useRequest(); - const [historyData, setHistoryData] = useState([]); - const [isLoading, setIsLoading] = useState(false); - const [hasError, setHasError] = useState(false); + const [historyData, setHistoryData] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [hasError, setHasError] = useState(false); - useEffect(() => { - const fetchHistory = async () => { - if (!phoneNumber || !maxSize) return; + useEffect(() => { + const fetchHistory = async () => { + if (!phoneNumber || !maxSize) return; - setIsLoading(true); - setHasError(false); + setIsLoading(true); + setHasError(false); - try { - const url = `${GET_CALLER_HISTORY}?phone_number=${phoneNumber}&size=${maxSize}`; - const { data } = await requestServer(url, "get"); - const items = data?.data || []; + try { + const url = `${GET_CALLER_HISTORY}?phone_number=${phoneNumber}&size=${maxSize}`; + const { data } = await requestServer(url, "get"); + const items = data?.data || []; - const filtered = items.filter((item) => item.id !== callId); - const unique = Array.from( - new Map(filtered.map((item) => [item.id, item])).values(), - ); + const filtered = items.filter((item) => item.id !== callId); + const unique = Array.from(new Map(filtered.map((item) => [item.id, item])).values()); - setHistoryData(unique); - } catch (error) { - setHasError(true); - setHistoryData([]); - } finally { - setIsLoading(false); - } + setHistoryData(unique); + } catch (error) { + setHasError(true); + setHistoryData([]); + } finally { + setIsLoading(false); + } + }; + + fetchHistory(); + }, [callId, phoneNumber, maxSize]); + + return { + firstItemOfHistory: historyData[0] || false, + historyList: historyData.length > 1 ? historyData.slice(1) : false, + isLoadingHistoryList: isLoading, + errorHistoryList: hasError, }; - - fetchHistory(); - }, [callId, phoneNumber, maxSize]); - - return { - firstItemOfHistory: historyData[0] || false, - historyList: historyData.length > 1 ? historyData.slice(1) : false, - isLoadingHistoryList: isLoading, - errorHistoryList: hasError, - }; }; export default useCallerHistory; diff --git a/src/lib/hooks/useDataTable.js b/src/lib/hooks/useDataTable.js index f0cdc03..c940d91 100644 --- a/src/lib/hooks/useDataTable.js +++ b/src/lib/hooks/useDataTable.js @@ -2,26 +2,18 @@ import { useContext } from "react"; import { DataTableContext } from "@/lib/contexts/DataTable"; const useTableSetting = () => { - const { - filterData, - setFilterData, - sortData, - setSortData, - hideData, - setHideData, - isDirty, - isAnyDirty, - } = useContext(DataTableContext); - return { - filterData, - setFilterData, - sortData, - setSortData, - hideData, - setHideData, - isDirty, - isAnyDirty, - }; + const { filterData, setFilterData, sortData, setSortData, hideData, setHideData, isDirty, isAnyDirty } = + useContext(DataTableContext); + return { + filterData, + setFilterData, + sortData, + setSortData, + hideData, + setHideData, + isDirty, + isAnyDirty, + }; }; export default useTableSetting; diff --git a/src/lib/hooks/usePermissions.js b/src/lib/hooks/usePermissions.js index b1f2856..c50c0e6 100644 --- a/src/lib/hooks/usePermissions.js +++ b/src/lib/hooks/usePermissions.js @@ -3,19 +3,19 @@ import useSWR from "swr"; import useRequest from "./useRequest"; export const usePermissions = () => { - const request = useRequest(); + const request = useRequest(); - const fetcher = async (url) => { - try { - const response = await request(url); - return response.data.data; - } catch (error) { - throw new Error(); - } - }; + const fetcher = async (url) => { + try { + const response = await request(url); + return response.data.data; + } catch (error) { + throw new Error(); + } + }; - return useSWR(GET_PERMISSIONS_ROUTE, fetcher, { - keepPreviousData: true, - dedupingInterval: 30000, - }); + return useSWR(GET_PERMISSIONS_ROUTE, fetcher, { + keepPreviousData: true, + dedupingInterval: 30000, + }); }; diff --git a/src/lib/hooks/useProvince.js b/src/lib/hooks/useProvince.js index d73cfdc..a670efd 100644 --- a/src/lib/hooks/useProvince.js +++ b/src/lib/hooks/useProvince.js @@ -3,27 +3,27 @@ import { GET_PROVINCE_LISTS } from "@/core/utils/routes"; import useRequest from "@/lib/hooks/useRequest"; const useProvinces = () => { - const requestServer = useRequest(); - const [provinces, setProvinces] = useState([]); - const [loadingProvinces, setLoadingProvinces] = useState(true); - const [errorProvinces, setErrorProvinces] = useState(null); + const requestServer = useRequest(); + const [provinces, setProvinces] = useState([]); + const [loadingProvinces, setLoadingProvinces] = useState(true); + const [errorProvinces, setErrorProvinces] = useState(null); - useEffect(() => { - const fetchProvinces = async () => { - try { - const response = await requestServer(`${GET_PROVINCE_LISTS}`); - setProvinces(response.data.data); - setLoadingProvinces(false); - } catch (e) { - setErrorProvinces(e); - setLoadingProvinces(false); - } - }; + useEffect(() => { + const fetchProvinces = async () => { + try { + const response = await requestServer(`${GET_PROVINCE_LISTS}`); + setProvinces(response.data.data); + setLoadingProvinces(false); + } catch (e) { + setErrorProvinces(e); + setLoadingProvinces(false); + } + }; - fetchProvinces(); - }, []); + fetchProvinces(); + }, []); - return { provinces, loadingProvinces, errorProvinces }; + return { provinces, loadingProvinces, errorProvinces }; }; export default useProvinces; diff --git a/src/lib/hooks/useRequest.js b/src/lib/hooks/useRequest.js index 9f4f2ff..547161e 100644 --- a/src/lib/hooks/useRequest.js +++ b/src/lib/hooks/useRequest.js @@ -5,62 +5,58 @@ import { useAuth } from "../contexts/auth"; import { useSidebarBadge } from "./useSidebarBadge"; const defaultOptions = { - data: {}, - requestOptions: { - headers: {}, - }, - notificationShow: true, - notificationSuccess: false, - notificationFailed: true, - hasSidebarUpdate: false, + data: {}, + requestOptions: { + headers: {}, + }, + notificationShow: true, + notificationSuccess: false, + notificationFailed: true, + hasSidebarUpdate: false, }; const useRequest = (initOptions) => { - const _options = Object.assign({}, defaultOptions, initOptions); + const _options = Object.assign({}, defaultOptions, initOptions); - const { mutate: sidebarUpdate } = useSidebarBadge({ - enable: _options.hasSidebarUpdate, - }); - const { logout } = useAuth(); + const { mutate: sidebarUpdate } = useSidebarBadge({ + enable: _options.hasSidebarUpdate, + }); + const { logout } = useAuth(); - /** - * Performs an HTTP request. - * @param {string} url - The URL to send the request to. - * @param {'get' | 'post' | 'put' | 'delete'} [method='get'] - HTTP method. - * @param {object} [options] - Additional request options. - * @returns {Promise} - Axios response. - */ - return async (url = "", method = "get", options) => { - const mergedOptions = Object.assign({}, _options, options); - try { - const response = await axios({ - url, - method, - data: method === "get" ? null : mergedOptions.data, - withCredentials: true, - ...mergedOptions.requestOptions, - }); - if (mergedOptions.hasSidebarUpdate) { - if (method === "post" || method === "put" || method === "delete") - sidebarUpdate(); - } - successRequest( - mergedOptions.notificationShow && mergedOptions.notificationSuccess, - "request_data", - ); - return response; - } catch (error) { - if (error.response) { - errorResponse( - error.response, - mergedOptions.notificationShow && mergedOptions.notificationFailed, - "request_data", - logout, - ); - } - throw error; - } - }; + /** + * Performs an HTTP request. + * @param {string} url - The URL to send the request to. + * @param {'get' | 'post' | 'put' | 'delete'} [method='get'] - HTTP method. + * @param {object} [options] - Additional request options. + * @returns {Promise} - Axios response. + */ + return async (url = "", method = "get", options) => { + const mergedOptions = Object.assign({}, _options, options); + try { + const response = await axios({ + url, + method, + data: method === "get" ? null : mergedOptions.data, + withCredentials: true, + ...mergedOptions.requestOptions, + }); + if (mergedOptions.hasSidebarUpdate) { + if (method === "post" || method === "put" || method === "delete") sidebarUpdate(); + } + successRequest(mergedOptions.notificationShow && mergedOptions.notificationSuccess, "request_data"); + return response; + } catch (error) { + if (error.response) { + errorResponse( + error.response, + mergedOptions.notificationShow && mergedOptions.notificationFailed, + "request_data", + logout + ); + } + throw error; + } + }; }; export default useRequest; diff --git a/src/lib/hooks/useRoles.js b/src/lib/hooks/useRoles.js index 822cbef..098f3e4 100644 --- a/src/lib/hooks/useRoles.js +++ b/src/lib/hooks/useRoles.js @@ -3,27 +3,27 @@ import { GET_ROLE_LISTS } from "@/core/utils/routes"; import useRequest from "@/lib/hooks/useRequest"; const useRoles = () => { - const requestServer = useRequest(); - const [roles, setRoles] = useState([]); - const [loadingRoles, setLoadingRoles] = useState(true); - const [errorRoles, setErrorRoles] = useState(null); + const requestServer = useRequest(); + const [roles, setRoles] = useState([]); + const [loadingRoles, setLoadingRoles] = useState(true); + const [errorRoles, setErrorRoles] = useState(null); - useEffect(() => { - const fetchRoles = async () => { - try { - const response = await requestServer(`${GET_ROLE_LISTS}`); - setRoles(response.data.data); - setLoadingRoles(false); - } catch (e) { - setErrorRoles(e); - setLoadingRoles(false); - } - }; + useEffect(() => { + const fetchRoles = async () => { + try { + const response = await requestServer(`${GET_ROLE_LISTS}`); + setRoles(response.data.data); + setLoadingRoles(false); + } catch (e) { + setErrorRoles(e); + setLoadingRoles(false); + } + }; - fetchRoles(); - }, []); + fetchRoles(); + }, []); - return { roles, loadingRoles, errorRoles }; + return { roles, loadingRoles, errorRoles }; }; export default useRoles; diff --git a/src/lib/hooks/useSidebarBadge.js b/src/lib/hooks/useSidebarBadge.js index 10e7461..7f83a07 100644 --- a/src/lib/hooks/useSidebarBadge.js +++ b/src/lib/hooks/useSidebarBadge.js @@ -3,21 +3,21 @@ import axios from "axios"; import useSWR from "swr"; export const useSidebarBadge = ({ enable = true }) => { - const fetcher = async (url) => { - try { - const response = await axios({ - url, - method: "get", - withCredentials: true, - }); - return response.data.data; - } catch (error) { - throw new Error(); - } - }; + const fetcher = async (url) => { + try { + const response = await axios({ + url, + method: "get", + withCredentials: true, + }); + return response.data.data; + } catch (error) { + throw new Error(); + } + }; - return useSWR(enable ? GET_SIDEBAR_BADGE_ROUTE : "", fetcher, { - keepPreviousData: true, - dedupingInterval: 30000, - }); + return useSWR(enable ? GET_SIDEBAR_BADGE_ROUTE : "", fetcher, { + keepPreviousData: true, + dedupingInterval: 30000, + }); }; diff --git a/src/lib/hooks/useTableSetting.js b/src/lib/hooks/useTableSetting.js index 35860f0..c841ffc 100644 --- a/src/lib/hooks/useTableSetting.js +++ b/src/lib/hooks/useTableSetting.js @@ -2,9 +2,8 @@ import { useContext } from "react"; import { TableSettingContext } from "../contexts/tableSetting"; const useTableSetting = () => { - const { settingStore, hideAction, sortAction, filterAction, resetAction } = - useContext(TableSettingContext); - return { settingStore, hideAction, sortAction, filterAction, resetAction }; + const { settingStore, hideAction, sortAction, filterAction, resetAction } = useContext(TableSettingContext); + return { settingStore, hideAction, sortAction, filterAction, resetAction }; }; export default useTableSetting; From 8d3b5b6e1e067d7113f22ac21f109dc342a70a16 Mon Sep 17 00:00:00 2001 From: mhmjalali Date: Mon, 28 Jul 2025 14:28:39 +0330 Subject: [PATCH 4/8] start working on role page and add it page --- .idea/inspectionProfiles/Project_Default.xml | 1 + .../(dashboardLayout)/dashboard/roles/page.js | 16 +++++++ src/components/dashboard/Roles/index.jsx | 14 ++++++ .../Users/RowActions/Edit/Form/index.jsx | 43 +++++++++++++----- .../Users/Toolbar/Create/Form/index.jsx | 44 ++++++++++++++----- src/core/utils/pageMenu.js | 7 +++ 6 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js create mode 100644 src/components/dashboard/Roles/index.jsx diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 03d9549..0a8a18b 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,6 @@ \ No newline at end of file diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js new file mode 100644 index 0000000..631cd14 --- /dev/null +++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js @@ -0,0 +1,16 @@ +import RolesPage from "@/components/dashboard/Roles"; +import WithPermission from "@/core/middlewares/withPermission"; + +export const metadata = { + title: "نقش ها", +}; + +const Page = () => { + return ( + + + + ); +}; + +export default Page; diff --git a/src/components/dashboard/Roles/index.jsx b/src/components/dashboard/Roles/index.jsx new file mode 100644 index 0000000..dc33690 --- /dev/null +++ b/src/components/dashboard/Roles/index.jsx @@ -0,0 +1,14 @@ +import PageTitle from "@/core/components/PageTitle"; +import { Stack } from "@mui/material"; +import DataTable from "./DataTable"; + +const RolesPage = () => { + return ( + + + + + ); +}; + +export default RolesPage; diff --git a/src/components/dashboard/Users/RowActions/Edit/Form/index.jsx b/src/components/dashboard/Users/RowActions/Edit/Form/index.jsx index 2686f27..cd61490 100644 --- a/src/components/dashboard/Users/RowActions/Edit/Form/index.jsx +++ b/src/components/dashboard/Users/RowActions/Edit/Form/index.jsx @@ -27,19 +27,20 @@ import { Controller, useForm } from "react-hook-form"; import { object, string } from "yup"; const validationSchema = object().shape({ - full_name: string().required("نام و نام خانوادگی خود را وارد کنید"), - username: string().required("نام کاربری خود را وارد کنید"), + full_name: string().required("نام و نام خانوادگی را وارد کنید"), + username: string().required("نام کاربری را وارد کنید"), phone_number: string() .matches(/^09\d{9}$/, "شماره همراه باید با 09 شروع شود و 11 رقم باشد.") - .required("شماره همراه خود را وارد کنید"), - gender: string().required("جنسیت خود را وارد کنید"), + .required("شماره همراه را وارد کنید"), + gender: string().required("جنسیت را وارد کنید"), national_id: string() .test("max", "کد ملی باید شامل 10 رقم باشد", (value) => value.toString().length === 10) .test("validation", "کد ملی صحیح نمی باشد", (value) => validateNationalCode(value)) - .required("کد ملی خود را وارد کنید"), - position: string().required("سمت خود را وارد کنید"), - province_id: string().required("استان خود را وارد کنید"), - role_id: string().required("نقش خود را وارد کنید"), + .required("کد ملی را وارد کنید"), + position: string().required("سمت را وارد کنید"), + province_id: string().required("استان را وارد کنید"), + role_id: string().required("نقش را وارد کنید"), + telephone_id: string().required("شماره تماس داخلی را وارد کنید") }); const UpdateUserForm = ({ values, setOpen, mutate }) => { @@ -56,6 +57,7 @@ const UpdateUserForm = ({ values, setOpen, mutate }) => { phone_number: values.phone_number, province_id: values.province_id, role_id: values.roles[0].id, + telephone_id: values.telephone_id }; const provinceSelectOptions = useMemo(() => { @@ -212,12 +214,12 @@ const UpdateUserForm = ({ values, setOpen, mutate }) => { render={({ field, fieldState: { error } }) => { return ( - + جنسیت } @@ -372,6 +373,25 @@ const CreateUserForm = ({ setOpen, mutate }) => { name={"role_id"} /> + + { + return ( + + ); + }} + name={"telephone_id"} + /> + diff --git a/src/core/utils/pageMenu.js b/src/core/utils/pageMenu.js index 8aa30ff..24d22de 100644 --- a/src/core/utils/pageMenu.js +++ b/src/core/utils/pageMenu.js @@ -24,6 +24,13 @@ export const pageMenu = [ route: "/dashboard/users", permissions: ["manage_users"], }, + { + id: "systemManagment-roles", + label: "نقش ها", + type: "page", + route: "/dashboard/roles", + permissions: ["manage_roles"], + } ], }, ]; From 74dddb170522213bf57c07078aa30087a056e054 Mon Sep 17 00:00:00 2001 From: mhmjalali Date: Tue, 29 Jul 2025 09:33:55 +0330 Subject: [PATCH 5/8] middle of role page --- .../(dashboardLayout)/dashboard/roles/page.js | 2 +- src/components/dashboard/Roles/DataTable.jsx | 91 +++++++++++ .../dashboard/Roles/RowAcctions/index.jsx | 0 .../Roles/Toolbar/Create/Form/index.jsx | 150 ++++++++++++++++++ .../dashboard/Roles/Toolbar/Create/index.jsx | 39 +++++ .../dashboard/Roles/Toolbar/index.jsx | 10 ++ src/components/dashboard/Roles/index.jsx | 2 +- src/core/utils/routes.js | 6 + src/lib/hooks/usePermissionsList.js | 21 +++ 9 files changed, 319 insertions(+), 2 deletions(-) create mode 100644 src/components/dashboard/Roles/DataTable.jsx create mode 100644 src/components/dashboard/Roles/RowAcctions/index.jsx create mode 100644 src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx create mode 100644 src/components/dashboard/Roles/Toolbar/Create/index.jsx create mode 100644 src/components/dashboard/Roles/Toolbar/index.jsx create mode 100644 src/lib/hooks/usePermissionsList.js diff --git a/src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js b/src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js index 631cd14..8e37670 100644 --- a/src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js +++ b/src/app/(withAuth)/(dashboardLayout)/dashboard/roles/page.js @@ -7,7 +7,7 @@ export const metadata = { const Page = () => { return ( - + ); diff --git a/src/components/dashboard/Roles/DataTable.jsx b/src/components/dashboard/Roles/DataTable.jsx new file mode 100644 index 0000000..7dc50f6 --- /dev/null +++ b/src/components/dashboard/Roles/DataTable.jsx @@ -0,0 +1,91 @@ +"use client"; +import DataTableWithAuth from "@/core/components/DataTableWithAuth"; +import { GET_ROLE_LIST } from "@/core/utils/routes"; +import { Box, Stack, Typography } from "@mui/material"; +import { useMemo } from "react"; +// import RowActions from "./RowActions"; +import Toolbar from "./Toolbar"; +import moment from "jalali-moment"; +import RowActions from "@/components/dashboard/Users/RowActions"; + +const DataTable = () => { + const columns = useMemo( + () => [ + { + accessorKey: "id", + header: "کد یکتا", + id: "id", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "name_fa", + header: "نام", + id: "name_fa", + enableColumnFilter: true, + datatype: "text", + filterMode: "equals", + sortDescFirst: false, + columnFilterModeOptions: ["equals", "contains"], + grow: false, + size: 100, + }, + { + accessorKey: "created_at", + header: "تاریخ ساخت", + id: "created_at", + enableColumnFilter: false, + datatype: "date", + filterMode: "equals", + grow: false, + size: 100, + Cell: ({ renderedCellValue }) => ( + + {renderedCellValue ? moment(renderedCellValue).locale("fa").format("HH:mm | YYYY/MM/DD") : "-"} + + ), + }, + { + accessorKey: "updated_at", + header: "تاریخ آخرین بروزرسانی", + id: "updated_at", + enableColumnFilter: false, + datatype: "date", + filterMode: "equals", + grow: false, + size: 100, + Cell: ({ renderedCellValue }) => ( + + {renderedCellValue ? moment(renderedCellValue).locale("fa").format("HH:mm | YYYY/MM/DD") : "-"} + + ), + }, + ], + [] + ); + + return ( + <> + + + + + ); +}; +export default DataTable; diff --git a/src/components/dashboard/Roles/RowAcctions/index.jsx b/src/components/dashboard/Roles/RowAcctions/index.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx b/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx new file mode 100644 index 0000000..01fc9f0 --- /dev/null +++ b/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx @@ -0,0 +1,150 @@ +import LtrTextField from "@/core/components/LtrTextField"; +import StyledForm from "@/core/components/StyledForm"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { Button, Checkbox, Chip, DialogActions, DialogContent, Divider, Grid, Stack } from "@mui/material"; +import { Controller, useForm } from "react-hook-form"; +import { object, string } from "yup"; +import useRequest from "@/lib/hooks/useRequest"; +import { CREATE_ROLE } from "@/core/utils/routes"; +import { useState } from "react"; +import { usePermissionsList } from "@/lib/hooks/usePermissionsList"; + +const defaultValues = { + name: "", + name_fa: "", +}; + +const validationSchema = object().shape({ + name: string().required("نام فارسی نقش را وارد کنید"), + name_fa: string().required("نام انگلیسی نقش را وارد کنید"), +}); + +const CreateRoleForm = ({ setOpen, mutate }) => { + const [permissionChecked, setPermissionChecked] = useState({}); + const requestServer = useRequest({ notificationSuccess: true }); + const { data } = usePermissionsList(); + + console.log("data", data); + + const handleCheckboxChange = (index) => { + setPermissionChecked((prev) => ({ + ...prev, + [index]: !prev[index], + })); + }; + + const { + control, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); + + const onSubmit = async (data) => { + const formData = new FormData(); + Object.keys(data).forEach((key) => { + formData.append(key, data[key]); + }); + try { + await requestServer(CREATE_ROLE, "post", { + data: formData, + }); + setOpen(false); + mutate(); + } catch (error) {} + }; + + return ( + <> + + + + + + + + + { + return ( + + ); + }} + name={"name"} + /> + + + { + return ( + + ); + }} + name={"name_fa"} + /> + + + + + + + {permissions.map((permission, index) => ( + + handleCheckboxChange(index)} + /> + {permission.label} + + ))} + + + + + + + + + + + + ); +}; + +export default CreateRoleForm; diff --git a/src/components/dashboard/Roles/Toolbar/Create/index.jsx b/src/components/dashboard/Roles/Toolbar/Create/index.jsx new file mode 100644 index 0000000..db5df6f --- /dev/null +++ b/src/components/dashboard/Roles/Toolbar/Create/index.jsx @@ -0,0 +1,39 @@ +"use client"; +import { AddCircle } from "@mui/icons-material"; +import { Button, Dialog, IconButton, useMediaQuery, useTheme } from "@mui/material"; +import CreateRoleForm from "./Form"; +import { useState } from "react"; + +const CreateRole = ({ mutate }) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + return ( + <> + {isMobile ? ( + + + + ) : ( + + )} + + + + + ); +}; +export default CreateRole; diff --git a/src/components/dashboard/Roles/Toolbar/index.jsx b/src/components/dashboard/Roles/Toolbar/index.jsx new file mode 100644 index 0000000..413eefc --- /dev/null +++ b/src/components/dashboard/Roles/Toolbar/index.jsx @@ -0,0 +1,10 @@ +import CreateRole from "./Create"; + +const Toolbar = ({ mutate }) => { + return ( + <> + + + ); +}; +export default Toolbar; diff --git a/src/components/dashboard/Roles/index.jsx b/src/components/dashboard/Roles/index.jsx index dc33690..6f3cadd 100644 --- a/src/components/dashboard/Roles/index.jsx +++ b/src/components/dashboard/Roles/index.jsx @@ -5,7 +5,7 @@ import DataTable from "./DataTable"; const RolesPage = () => { return ( - + ); diff --git a/src/core/utils/routes.js b/src/core/utils/routes.js index b803eff..bac15b9 100644 --- a/src/core/utils/routes.js +++ b/src/core/utils/routes.js @@ -8,6 +8,7 @@ export const GET_PERMISSIONS_ROUTE = api + "/profile/permissions"; export const GET_SIDEBAR_BADGE_ROUTE = ""; export const GET_PROVINCE_LISTS = api + "/provinces/list"; export const GET_ROLE_LISTS = api + "/roles/list"; +export const GET_PERMISSIONS_LIST = api + "/permissions/list"; export const GET_CATEGORY = api + "/categories/list"; export const GET_CALLER_HISTORY = api + "/calls/list"; @@ -17,3 +18,8 @@ export const GET_USER_LIST = api + "/users"; export const CREATE_USER = api + "/users"; export const DELETE_USER = api + "/users"; export const UPDATE_USER = api + "/users"; + +export const GET_ROLE_LIST = api + "/roles"; +export const CREATE_ROLE = api + "/roles"; +export const DELETE_ROLE = api + "/roles"; +export const UPDATE_ROLE = api + "/roles"; diff --git a/src/lib/hooks/usePermissionsList.js b/src/lib/hooks/usePermissionsList.js new file mode 100644 index 0000000..1ceff74 --- /dev/null +++ b/src/lib/hooks/usePermissionsList.js @@ -0,0 +1,21 @@ +import { GET_PERMISSIONS_LIST } from "@/core/utils/routes"; +import useSWR from "swr"; +import useRequest from "./useRequest"; + +export const usePermissionsList = () => { + const request = useRequest(); + + const fetcher = async (url) => { + try { + const response = await request(url); + return response.data.data; + } catch (error) { + throw new Error(); + } + }; + + return useSWR(GET_PERMISSIONS_LIST, fetcher, { + keepPreviousData: true, + dedupingInterval: 30000, + }); +}; From 3569d10ecccda65fe9461994a3a804234212b22f Mon Sep 17 00:00:00 2001 From: mhmjalali Date: Tue, 29 Jul 2025 14:39:39 +0330 Subject: [PATCH 6/8] complete store part of role and start delete and edit --- .../Roles/Toolbar/Create/Form/index.jsx | 103 ++++++++++++------ src/lib/hooks/usePermissionsList.js | 40 ++++--- 2 files changed, 93 insertions(+), 50 deletions(-) diff --git a/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx b/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx index 01fc9f0..dbc11e9 100644 --- a/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx +++ b/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx @@ -1,52 +1,55 @@ import LtrTextField from "@/core/components/LtrTextField"; import StyledForm from "@/core/components/StyledForm"; import { yupResolver } from "@hookform/resolvers/yup"; -import { Button, Checkbox, Chip, DialogActions, DialogContent, Divider, Grid, Stack } from "@mui/material"; +import { + Box, + Button, + Checkbox, + Chip, + DialogActions, + DialogContent, + Divider, + FormControlLabel, FormHelperText, + Grid, Skeleton, + Stack, +} from "@mui/material"; import { Controller, useForm } from "react-hook-form"; -import { object, string } from "yup"; +import { array, object, string } from "yup"; import useRequest from "@/lib/hooks/useRequest"; import { CREATE_ROLE } from "@/core/utils/routes"; -import { useState } from "react"; -import { usePermissionsList } from "@/lib/hooks/usePermissionsList"; +import usePermissionsList from "@/lib/hooks/usePermissionsList"; const defaultValues = { name: "", name_fa: "", + permissions: [] }; const validationSchema = object().shape({ name: string().required("نام فارسی نقش را وارد کنید"), name_fa: string().required("نام انگلیسی نقش را وارد کنید"), + permissions: array().min(1, "حداقل یک دسترسی را انتخاب نمایید") }); const CreateRoleForm = ({ setOpen, mutate }) => { - const [permissionChecked, setPermissionChecked] = useState({}); const requestServer = useRequest({ notificationSuccess: true }); - const { data } = usePermissionsList(); - - console.log("data", data); - - const handleCheckboxChange = (index) => { - setPermissionChecked((prev) => ({ - ...prev, - [index]: !prev[index], - })); - }; + const { permissions, loadingPermissions } = usePermissionsList(); const { control, handleSubmit, formState: { isSubmitting, errors }, + watch, } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); const onSubmit = async (data) => { - const formData = new FormData(); - Object.keys(data).forEach((key) => { - formData.append(key, data[key]); - }); try { await requestServer(CREATE_ROLE, "post", { - data: formData, + data: { + permissions: data.permissions, + name: data.name, + name_fa: data.name_fa, + }, }); setOpen(false); mutate(); @@ -60,7 +63,7 @@ const CreateRoleForm = ({ setOpen, mutate }) => { @@ -102,21 +105,53 @@ const CreateRoleForm = ({ setOpen, mutate }) => { name={"name_fa"} /> - + - + - - {permissions.map((permission, index) => ( - - handleCheckboxChange(index)} - /> - {permission.label} - - ))} - + + + {!loadingPermissions ? ( + ( + <> + {permissions.map((permission) => ( + + { + const value = parseInt(e.target.value, 10); + if (e.target.checked) { + field.onChange([...field.value, value]); + } else { + field.onChange(field.value.filter((id) => id !== value)); + } + }} + /> + } + label={permission.name_fa} + /> + + ))} + {!!error && error.message} + + )} + /> + ) : ( + + + + + + + + + )} diff --git a/src/lib/hooks/usePermissionsList.js b/src/lib/hooks/usePermissionsList.js index 1ceff74..84cd1cc 100644 --- a/src/lib/hooks/usePermissionsList.js +++ b/src/lib/hooks/usePermissionsList.js @@ -1,21 +1,29 @@ +import { useEffect, useState } from "react"; import { GET_PERMISSIONS_LIST } from "@/core/utils/routes"; -import useSWR from "swr"; -import useRequest from "./useRequest"; +import useRequest from "@/lib/hooks/useRequest"; -export const usePermissionsList = () => { - const request = useRequest(); +const usePermissionsList = () => { + const requestServer = useRequest(); + const [permissions, setPermissions] = useState([]); + const [loadingPermissions, setLoadingPermissions] = useState(true); + const [errorPermissions, setErrorPermissions] = useState(null); - const fetcher = async (url) => { - try { - const response = await request(url); - return response.data.data; - } catch (error) { - throw new Error(); - } - }; + useEffect(() => { + const fetchPermissions = async () => { + try { + const response = await requestServer(`${GET_PERMISSIONS_LIST}`); + setPermissions(response.data.data); + setLoadingPermissions(false); + } catch (e) { + setErrorPermissions(e); + setLoadingPermissions(false); + } + }; - return useSWR(GET_PERMISSIONS_LIST, fetcher, { - keepPreviousData: true, - dedupingInterval: 30000, - }); + fetchPermissions(); + }, []); + + return { permissions, loadingPermissions, errorPermissions }; }; + +export default usePermissionsList; From f4539de72a9be34c413000d00d96d55fce5973ee Mon Sep 17 00:00:00 2001 From: mhmjalali Date: Tue, 29 Jul 2025 14:43:35 +0330 Subject: [PATCH 7/8] complete delete role action --- src/components/dashboard/Roles/DataTable.jsx | 2 +- .../RowAcctions/Delete/DeleteContent.jsx | 39 +++++++++++++++++++ .../Roles/RowAcctions/Delete/index.jsx | 32 +++++++++++++++ .../dashboard/Roles/RowAcctions/index.jsx | 12 ++++++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/components/dashboard/Roles/RowAcctions/Delete/DeleteContent.jsx create mode 100644 src/components/dashboard/Roles/RowAcctions/Delete/index.jsx diff --git a/src/components/dashboard/Roles/DataTable.jsx b/src/components/dashboard/Roles/DataTable.jsx index 7dc50f6..7a1e3c6 100644 --- a/src/components/dashboard/Roles/DataTable.jsx +++ b/src/components/dashboard/Roles/DataTable.jsx @@ -6,7 +6,7 @@ import { useMemo } from "react"; // import RowActions from "./RowActions"; import Toolbar from "./Toolbar"; import moment from "jalali-moment"; -import RowActions from "@/components/dashboard/Users/RowActions"; +import RowActions from "@/components/dashboard/Roles/RowAcctions"; const DataTable = () => { const columns = useMemo( diff --git a/src/components/dashboard/Roles/RowAcctions/Delete/DeleteContent.jsx b/src/components/dashboard/Roles/RowAcctions/Delete/DeleteContent.jsx new file mode 100644 index 0000000..1225fed --- /dev/null +++ b/src/components/dashboard/Roles/RowAcctions/Delete/DeleteContent.jsx @@ -0,0 +1,39 @@ +import { DELETE_ROLE } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; +import { Button, DialogActions, DialogContent, Stack, Typography } from "@mui/material"; +import { useState } from "react"; + +const DeleteContent = ({ rowId, mutate, setOpenDeleteDialog }) => { + const [submitting, setSubmitting] = useState(false); + const requestServer = useRequest({ notificationSuccess: true }); + const handleClick = async () => { + setSubmitting(true); + try { + await requestServer(`${DELETE_ROLE}/${rowId}`, "delete"); + mutate(); + setOpenDeleteDialog(false); + } catch (error) { + } finally { + setSubmitting(false); + } + }; + return ( + <> + + + آیا از حذف کاربر اطمینان دارید؟ + + + + + + + + ); +}; + +export default DeleteContent; diff --git a/src/components/dashboard/Roles/RowAcctions/Delete/index.jsx b/src/components/dashboard/Roles/RowAcctions/Delete/index.jsx new file mode 100644 index 0000000..7d045bf --- /dev/null +++ b/src/components/dashboard/Roles/RowAcctions/Delete/index.jsx @@ -0,0 +1,32 @@ +import DeleteIcon from "@mui/icons-material/Delete"; +import { Dialog, DialogTitle, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import DeleteContent from "./DeleteContent"; +const Delete = ({ rowId, mutate }) => { + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + + return ( + <> + + setOpenDeleteDialog(true)}> + + + + setOpenDeleteDialog(false)} + PaperProps={{ + sx: { + boxShadow: "rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px", + }, + }} + dir="rtl" + maxWidth={"md"} + > + حذف + + + + ); +}; +export default Delete; diff --git a/src/components/dashboard/Roles/RowAcctions/index.jsx b/src/components/dashboard/Roles/RowAcctions/index.jsx index e69de29..e192a81 100644 --- a/src/components/dashboard/Roles/RowAcctions/index.jsx +++ b/src/components/dashboard/Roles/RowAcctions/index.jsx @@ -0,0 +1,12 @@ +import { Box } from "@mui/material"; +import Delete from "./Delete"; +// import UpdateUser from "./Edit"; +const RowActions = ({ row, mutate }) => { + return ( + + + {/**/} + + ); +}; +export default RowActions; From e38a1dfb57e8b0967e42bfb16dda4ba60504470f Mon Sep 17 00:00:00 2001 From: mhmjalali Date: Tue, 29 Jul 2025 15:39:43 +0330 Subject: [PATCH 8/8] complete role page with store update and delete action --- src/components/dashboard/Roles/DataTable.jsx | 5 +- .../Roles/RowAcctions/Edit/Form/index.jsx | 186 ++++++++++++++++++ .../Roles/RowAcctions/Edit/index.jsx | 27 +++ .../dashboard/Roles/RowAcctions/index.jsx | 4 +- .../Roles/Toolbar/Create/Form/index.jsx | 1 - 5 files changed, 217 insertions(+), 6 deletions(-) create mode 100644 src/components/dashboard/Roles/RowAcctions/Edit/Form/index.jsx create mode 100644 src/components/dashboard/Roles/RowAcctions/Edit/index.jsx diff --git a/src/components/dashboard/Roles/DataTable.jsx b/src/components/dashboard/Roles/DataTable.jsx index 7a1e3c6..d7147ae 100644 --- a/src/components/dashboard/Roles/DataTable.jsx +++ b/src/components/dashboard/Roles/DataTable.jsx @@ -1,12 +1,11 @@ "use client"; import DataTableWithAuth from "@/core/components/DataTableWithAuth"; import { GET_ROLE_LIST } from "@/core/utils/routes"; -import { Box, Stack, Typography } from "@mui/material"; +import { Box, Typography } from "@mui/material"; import { useMemo } from "react"; -// import RowActions from "./RowActions"; import Toolbar from "./Toolbar"; import moment from "jalali-moment"; -import RowActions from "@/components/dashboard/Roles/RowAcctions"; +import RowActions from "./RowAcctions"; const DataTable = () => { const columns = useMemo( diff --git a/src/components/dashboard/Roles/RowAcctions/Edit/Form/index.jsx b/src/components/dashboard/Roles/RowAcctions/Edit/Form/index.jsx new file mode 100644 index 0000000..d95a357 --- /dev/null +++ b/src/components/dashboard/Roles/RowAcctions/Edit/Form/index.jsx @@ -0,0 +1,186 @@ +import LtrTextField from "@/core/components/LtrTextField"; +import StyledForm from "@/core/components/StyledForm"; +import { CREATE_ROLE } from "@/core/utils/routes"; +import useRequest from "@/lib/hooks/useRequest"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { + Box, + Button, + Checkbox, + Chip, + DialogActions, + DialogContent, + Divider, + FormControlLabel, + FormHelperText, + Grid, + Skeleton, + Stack, +} from "@mui/material"; +import { Controller, useForm } from "react-hook-form"; +import { array, object, string } from "yup"; +import usePermissionsList from "@/lib/hooks/usePermissionsList"; + +const validationSchema = object().shape({ + name: string().required("نام فارسی نقش را وارد کنید"), + name_fa: string().required("نام انگلیسی نقش را وارد کنید"), + permissions: array().min(1, "حداقل یک دسترسی را انتخاب نمایید") +}); + +const UpdateRoleForm = ({ values, setOpen, mutate }) => { + const requestServer = useRequest({ notificationSuccess: true }); + const { permissions, loadingPermissions } = usePermissionsList(); + + const defaultValues = { + name: values.name, + name_fa: values.name_fa, + permissions: values.permissions?.map(p => p.id) || [] + }; + + const { + control, + handleSubmit, + formState: { isSubmitting, errors }, + } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); + + const onSubmit = async (data) => { + try { + await requestServer(`${CREATE_ROLE}/${values.id}`, "post", { + data: { + permissions: data.permissions, + name: data.name, + name_fa: data.name_fa, + }, + }); + setOpen(false); + mutate(); + } catch (error) {} + }; + + return ( + <> + + + + + + + + + { + return ( + + ); + }} + name={"name"} + /> + + + { + return ( + + ); + }} + name={"name_fa"} + /> + + + + + + + + {!loadingPermissions ? ( + ( + <> + {permissions.map((permission) => ( + + { + const value = parseInt(e.target.value, 10); + if (e.target.checked) { + field.onChange([...field.value, value]); + } else { + field.onChange(field.value.filter((id) => id !== value)); + } + }} + /> + } + label={permission.name_fa} + /> + + ))} + {!!error && error.message} + + )} + /> + ) : ( + + + + + + + + + )} + + + + + + + + + + + ); +}; + +export default UpdateRoleForm; diff --git a/src/components/dashboard/Roles/RowAcctions/Edit/index.jsx b/src/components/dashboard/Roles/RowAcctions/Edit/index.jsx new file mode 100644 index 0000000..1aa42c4 --- /dev/null +++ b/src/components/dashboard/Roles/RowAcctions/Edit/index.jsx @@ -0,0 +1,27 @@ +"use client"; +import { Edit } from "@mui/icons-material"; +import { Dialog, IconButton, Tooltip } from "@mui/material"; +import { useState } from "react"; +import UpdateUserForm from "./Form"; + +const UpdateUser = ({ values, mutate }) => { + const [open, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + return ( + <> + + + + + + + + + + ); +}; +export default UpdateUser; diff --git a/src/components/dashboard/Roles/RowAcctions/index.jsx b/src/components/dashboard/Roles/RowAcctions/index.jsx index e192a81..b551a15 100644 --- a/src/components/dashboard/Roles/RowAcctions/index.jsx +++ b/src/components/dashboard/Roles/RowAcctions/index.jsx @@ -1,11 +1,11 @@ import { Box } from "@mui/material"; import Delete from "./Delete"; -// import UpdateUser from "./Edit"; +import UpdateUser from "./Edit"; const RowActions = ({ row, mutate }) => { return ( - {/**/} + ); }; diff --git a/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx b/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx index dbc11e9..e573312 100644 --- a/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx +++ b/src/components/dashboard/Roles/Toolbar/Create/Form/index.jsx @@ -39,7 +39,6 @@ const CreateRoleForm = ({ setOpen, mutate }) => { control, handleSubmit, formState: { isSubmitting, errors }, - watch, } = useForm({ defaultValues, resolver: yupResolver(validationSchema) }); const onSubmit = async (data) => {