Merge branch 'release/v0.4.1'

This commit is contained in:
Amirhossein Mahmoodi
2024-07-31 10:19:19 +03:30
31 changed files with 801 additions and 810 deletions

View File

@@ -1,3 +1,3 @@
NEXT_PUBLIC_VERSION="0.3.8"
NEXT_PUBLIC_VERSION="0.4.0"
NEXT_PUBLIC_API_URL="https://rms.witel.ir"
NEXT_PUBLIC_MAPTILE_ENDPOINT="https://rmsmap.rmto.ir/141map"

View File

@@ -18,6 +18,7 @@
"@mui/material": "^5.15.6",
"@mui/material-nextjs": "^5.15.6",
"@mui/x-date-pickers": "^6.19.5",
"@mui/x-tree-view": "^7.11.0",
"axios": "^1.7.2",
"date-fns": "^3.3.1",
"date-fns-jalali": "^2.13.0-0",

View File

@@ -1,12 +1,15 @@
"use client";
import DialogTransition from "@/core/components/DialogTransition";
import { AddCircle, Close } from "@mui/icons-material";
import { Button, Dialog, DialogTitle, IconButton } from "@mui/material";
import { Button, Dialog, DialogTitle, IconButton, useMediaQuery } from "@mui/material";
import CreateOrUpdateForm from "../../Forms/CreateOrUpdate";
import { SET_INQUIRE_PRIVACY_FENCING } from "@/core/utils/routes";
import { useState } from "react";
import { useTheme } from "@emotion/react";
const InquiryPrivacyFencingCreate = ({ mutate }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const [open, setOpen] = useState(false);
const handleOpen = () => {
@@ -19,11 +22,22 @@ const InquiryPrivacyFencingCreate = ({ mutate }) => {
return (
<>
<Button variant="contained" color="primary2" startIcon={<AddCircle />} onClick={handleOpen}>
ایجاد پاسخ به استعلام
</Button>
{isMobile ? (
<IconButton aria-label="ایجاد پاسخ به استعلام" color="primary" onClick={handleOpen}>
<AddCircle sx={{ fontSize: "25px" }} />
</IconButton>
) : (
<Button
variant="contained"
color="primary"
startIcon={<AddCircle />}
onClick={handleOpen}
>
ایجاد پاسخ به استعلام
</Button>
)}
<Dialog open={open} fullScreen TransitionComponent={DialogTransition}>
<DialogTitle sx={{ m: 0, p: 2, borderBottom: 1, borderColor: 'divider' }} id="create-dialog">
<DialogTitle sx={{ m: 0, p: 2, borderBottom: 1, borderColor: "divider" }} id="create-dialog">
ایجاد پاسخ به استعلام
</DialogTitle>
<IconButton

View File

@@ -93,7 +93,7 @@ const CreateOrUpdateForm = ({ handleClose, mutate, defaultValues, url }) => {
formData.append('rah_type_id', data.rah_type_id)
formData.append('rah_type', data.rah_type_id)
formData.append('name_mehvar_id', 1)
formData.append('name_mehvar_fa', data.name_mehvar_id)
formData.append('name_mehvar_fa', data.name_mehvar_fa)
formData.append('mizan_harim', data.mizan_harim)
formData.append('arze_navar', data.arze_navar)
formData.append('samt_id', data.samt_id)

View File

@@ -1,351 +1,15 @@
"use client";
import { useMemo } from "react";
import Toolbar from "@/components/dashboard/inquiryPrivacyFencing/Toolbar";
import DataTable from "@/core/components/DataTable";
import { Box } from "@mui/material";
import { GET_INQUIRY_PRIVACY_FENCING_ROUTE } from "@/core/utils/routes";
import PageTitle from "@/core/components/PageTitle";
import InquiryPrivacyFencingList from "./inquiryPrivacyFencingList";
import { Stack } from "@mui/material";
const InquiryPrivacyFencingPage = () => {
const columns = useMemo(
() => [
{
accessorKey: "dabirkhaneh_number",
header: "شماره دبیرخانه درخواست",
id: "dabirkhaneh_number",
enableColumnFilter: false,
datatype: "text",
filterFn: "notEquals",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "marjae_pasokh",
header: "مرجع درخواست کننده پاسخ به استعلام",
id: "marjae_pasokh",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
columnFilterModeOptions: ["equals", "notEquals", "contains", "lessThan", "greaterThan", "fuzzy"],
},
{
accessorKey: "motaghazi_is_legal",
header: "متقاضی",
id: "motaghazi_is_legal",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "nameh_date",
header: "تاریخ نامه درخواست",
id: "nameh_date",
enableColumnFilter: false,
datatype: "date",
filterFn: "equals",
},
{
accessorKey: "motaghazi_type",
header: "نوع متقاضی",
id: "motaghazi_type",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "motaghazi_firstname",
header: "نام متقاضی",
id: "motaghazi_firstname",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "motaghazi_lastname",
header: "نام خانوادگی متقاضی",
id: "motaghazi_lastname",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "national_id",
header: "کد ملی/شناسه ملی",
id: "national_id",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "tel_number",
header: "تلفن",
id: "tel_number",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "mobile_number",
header: "تلفن همراه",
id: "mobile_number",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "address",
header: "آدرس",
id: "address",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "edare_kol",
header: "اداره كل راهداری",
id: "edare_kol",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "edare_shahri",
header: "اداره شهرستان",
id: "edare_shahri",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "rah_type",
header: "نوع راه",
id: "rah_type",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "name_mehvar_fa",
header: "نام محور",
id: "name_mehvar_fa",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "mizan_harim",
header: "میزان حریم",
id: "mizan_harim",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "arze_navar",
header: "عرض نوار تاسیساتی زیربنایی",
id: "arze_navar",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "samt",
header: "سمت",
id: "samt",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "kilometr",
header: "كيلومتر",
id: "kilometr",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "zone",
header: "zone",
id: "zone",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "karbari_type",
header: "نوع کاربری",
id: "karbari_type",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "tarh_title",
header: "عنوان طرح",
id: "tarh_title",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "masahat_zirbana",
header: "مساحت زیربنا",
id: "masahat_zirbana",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "ehdasat_type",
header: "نوع احداثات",
id: "ehdasat_type",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "divarkeshi_distance",
header: "فاصله دیوارکشی از آکس محور",
id: "divarkeshi_distance",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "mahale_ejra",
header: "محل اجرا",
id: "mahale_ejra",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "traffic",
header: "میزان ترافیک",
id: "traffic",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "vaziat_eghtesadi",
header: "وضعیت اقتصادی",
id: "vaziat_eghtesadi",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "has_access",
header: "آیا راه دسترسی از قبل وجود دارد؟",
id: "has_access",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "shomare_estelam_harim",
header: "شماره استعلام دفتر ایمنی و حریم",
id: "shomare_estelam_harim",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "max_month",
header: "ماه",
id: "max_month",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "max_day",
header: "روز",
id: "max_day",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "shomare_tahaodname",
header: "شماره تعهدنامه",
id: "shomare_tahaodname",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "shomare_daftarkhaneh",
header: "شماره دفترخانه",
id: "shomare_daftarkhaneh",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "description",
header: "توضیحات",
id: "description",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
{
accessorKey: "ronevesht",
header: "رونوشت",
id: "ronevesht",
enableColumnFilter: false,
datatype: "text",
filterFn: "contains",
columnFilterModeOptions: ["equals", "notEquals", "contains"],
},
],
[]
);
return (
<DataTable
need_filter={false}
columns={columns}
table_url={GET_INQUIRY_PRIVACY_FENCING_ROUTE}
user_id={0}
page_name={"inquiryPrivacyFencing"}
table_name={"inquiryPrivacyFencingList"}
TableToolbar={Toolbar}
/>
<Stack spacing={2}>
<PageTitle title={"احداث و بهره برداری دیوارکشی و مستحدثات"} />
<InquiryPrivacyFencingList />
</Stack>
);
};
export default InquiryPrivacyFencingPage;

View File

@@ -0,0 +1,255 @@
"use client";
import { useMemo } from "react";
import Toolbar from "@/components/dashboard/inquiryPrivacyFencing/Toolbar";
import DataTable from "@/core/components/DataTable";
import { GET_INQUIRY_PRIVACY_FENCING_ROUTE } from "@/core/utils/routes";
import { Box } from "@mui/material";
import PageTitle from "@/core/components/PageTitle";
const InquiryPrivacyFencingList = () => {
const columns = useMemo(
() => [
{
accessorKey: "dabirkhaneh_number",
header: "شماره دبیرخانه درخواست",
id: "dabirkhaneh_number",
enableColumnFilter: false,
datatype: "text",
filterFn: "notEquals",
},
{
accessorKey: "marjae_pasokh",
header: "مرجع درخواست کننده پاسخ به استعلام",
id: "marjae_pasokh",
enableColumnFilter: false,
datatype: "text",
filterFn: "equals",
},
{
accessorKey: "motaghazi_is_legal",
header: "متقاضی",
id: "motaghazi_is_legal",
enableColumnFilter: false,
},
{
accessorKey: "nameh_date",
header: "تاریخ نامه درخواست",
id: "nameh_date",
enableColumnFilter: false,
},
{
accessorKey: "motaghazi_type",
header: "نوع متقاضی",
id: "motaghazi_type",
enableColumnFilter: false,
},
{
accessorKey: "motaghazi_firstname",
header: "نام متقاضی",
id: "motaghazi_firstname",
enableColumnFilter: false,
},
{
accessorKey: "motaghazi_lastname",
header: "نام خانوادگی متقاضی",
id: "motaghazi_lastname",
enableColumnFilter: false,
},
{
accessorKey: "national_id",
header: "کد ملی/شناسه ملی",
id: "national_id",
enableColumnFilter: false,
},
{
accessorKey: "tel_number",
header: "تلفن",
id: "tel_number",
enableColumnFilter: false,
},
{
accessorKey: "mobile_number",
header: "تلفن همراه",
id: "mobile_number",
enableColumnFilter: false,
},
{
accessorKey: "address",
header: "آدرس",
id: "address",
enableColumnFilter: false,
},
{
accessorKey: "edare_kol",
header: "اداره كل راهداری",
id: "edare_kol",
enableColumnFilter: false,
},
{
accessorKey: "edare_shahri",
header: "اداره شهرستان",
id: "edare_shahri",
enableColumnFilter: false,
},
{
accessorKey: "rah_type",
header: "نوع راه",
id: "rah_type",
enableColumnFilter: false,
},
{
accessorKey: "name_mehvar_fa",
header: "نام محور",
id: "name_mehvar_fa",
enableColumnFilter: false,
},
{
accessorKey: "mizan_harim",
header: "میزان حریم",
id: "mizan_harim",
enableColumnFilter: false,
},
{
accessorKey: "arze_navar",
header: "عرض نوار تاسیساتی زیربنایی",
id: "arze_navar",
enableColumnFilter: false,
},
{
accessorKey: "samt",
header: "سمت",
id: "samt",
enableColumnFilter: false,
},
{
accessorKey: "kilometr",
header: "كيلومتر",
id: "kilometr",
enableColumnFilter: false,
},
{
accessorKey: "zone",
header: "zone",
id: "zone",
enableColumnFilter: false,
},
{
accessorKey: "karbari_type",
header: "نوع کاربری",
id: "karbari_type",
enableColumnFilter: false,
},
{
accessorKey: "tarh_title",
header: "عنوان طرح",
id: "tarh_title",
enableColumnFilter: false,
},
{
accessorKey: "masahat_zirbana",
header: "مساحت زیربنا",
id: "masahat_zirbana",
enableColumnFilter: false,
},
{
accessorKey: "ehdasat_type",
header: "نوع احداثات",
id: "ehdasat_type",
enableColumnFilter: false,
},
{
accessorKey: "divarkeshi_distance",
header: "فاصله دیوارکشی از آکس محور",
id: "divarkeshi_distance",
enableColumnFilter: false,
},
{
accessorKey: "mahale_ejra",
header: "محل اجرا",
id: "mahale_ejra",
enableColumnFilter: false,
},
{
accessorKey: "traffic",
header: "میزان ترافیک",
id: "traffic",
enableColumnFilter: false,
},
{
accessorKey: "vaziat_eghtesadi",
header: "وضعیت اقتصادی",
id: "vaziat_eghtesadi",
enableColumnFilter: false,
},
{
accessorKey: "has_access",
header: "آیا راه دسترسی از قبل وجود دارد؟",
id: "has_access",
enableColumnFilter: false,
},
{
accessorKey: "shomare_estelam_harim",
header: "شماره استعلام دفتر ایمنی و حریم",
id: "shomare_estelam_harim",
enableColumnFilter: false,
},
{
accessorKey: "max_month",
header: "ماه",
id: "max_month",
enableColumnFilter: false,
},
{
accessorKey: "max_day",
header: "روز",
id: "max_day",
enableColumnFilter: false,
},
{
accessorKey: "shomare_tahaodname",
header: "شماره تعهدنامه",
id: "shomare_tahaodname",
enableColumnFilter: false,
},
{
accessorKey: "shomare_daftarkhaneh",
header: "شماره دفترخانه",
id: "shomare_daftarkhaneh",
enableColumnFilter: false,
},
{
accessorKey: "description",
header: "توضیحات",
id: "description",
enableColumnFilter: false,
},
{
accessorKey: "ronevesht",
header: "رونوشت",
id: "ronevesht",
enableColumnFilter: false,
},
],
[],
);
return (
<>
<Box sx={{ p: 2, border: 1, borderColor: 'divider', borderRadius: 1 }}>
<DataTable
table_title={"لیست استعلام ها"}
need_filter={false}
columns={columns}
table_url={GET_INQUIRY_PRIVACY_FENCING_ROUTE}
user_id={0}
page_name={"inquiryPrivacyFencing"}
table_name={"inquiryPrivacyFencingList"}
TableToolbar={Toolbar}
/>
</Box>
</>
);
};
export default InquiryPrivacyFencingList;

View File

@@ -1,35 +1,49 @@
import DataTable_Paper from "./table/Paper";
import { useMaterialReactTable } from "material-react-table";
import { FA_DATATABLE_LOCALIZATION } from "./localization/fa/datatable";
import useTableSetting from "@/lib/hooks/useTableSetting";
import { flattenArrayOfObjects } from "@/core/utils/flattenArrayOfObjects";
import useDataTable from "@/lib/hooks/useDataTable";
import { useMemo, useState } from "react";
import useRequest from "@/lib/hooks/useRequest";
import useSWR from "swr";
import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects";
const DataTable_Main = (props) => {
const request = useRequest();
const isEmptyObject = (obj) => obj && Object.keys(obj).length === 0 && obj.constructor === Object;
const { filterData, sortData, setSortData, hideData, setHideData } = useDataTable();
const { need_filter, table_url, user_id, page_name, table_name, columns, initialStateProps, TableToolbar } = props;
const { filterData, sortData, setSortData, hideData } = useDataTable();
const {
need_filter,
table_url,
user_id,
page_name,
table_name,
columns,
initialStateProps,
TableToolbar,
table_title,
} = props;
const flatColumns = flattenArrayOfObjects(columns, "columns");
const { settingStore, hideAction } = useTableSetting();
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
const onColumnVisibilityChange = (event) => {
setHideData(event);
};
const flattenHideData = flattenObjectOfObjects(hideData);
const onSortingChange = (event) => {
setSortData(event);
};
const fetchUrl = useMemo(() => {
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),
);
const params = new URLSearchParams();
params.set("start", `${pagination.pageIndex * pagination.pageSize}`);
params.set("size", pagination.pageSize);
params.set("filters", JSON.stringify(isEmptyObject(filterData) ? [] : [filterData]));
params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData));
params.set("sorting", JSON.stringify(sortData));
return `${table_url}?${params}`;
}, [table_url, filterData, pagination, columns, sortData]);
@@ -56,13 +70,13 @@ const DataTable_Main = (props) => {
data: data?.data ?? [],
initialState: {
density: "compact",
columnVisibility: hideData,
columnVisibility: flattenHideData,
sorting: sortData,
...initialStateProps,
},
state: {
showProgressBars: isValidating,
columnVisibility: hideData,
columnVisibility: flattenHideData,
sorting: sortData,
pagination,
},
@@ -93,7 +107,6 @@ const DataTable_Main = (props) => {
manualPagination: true,
manualSorting: true,
onPaginationChange: setPagination,
onColumnVisibilityChange: onColumnVisibilityChange,
onSortingChange: onSortingChange,
renderTopToolbarCustomActions: ({ table }) => (
<>
@@ -106,6 +119,7 @@ const DataTable_Main = (props) => {
return (
<DataTable_Paper
table={table}
table_title={table_title}
need_filter={need_filter}
mutate={mutate}
table_url={table_url}

View File

@@ -1,30 +0,0 @@
import { IconButton, Tooltip } from "@mui/material";
import { useState } from "react";
import DataTable_ShowHideColumnsMenu from "../menus/ShowHideColumnsMenu";
const DataTable_ShowHideColumnsButton = ({ table, ...rest }) => {
const {
options: {
icons: { ViewColumnIcon },
localization,
},
} = table;
const [anchorEl, setAnchorEl] = useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
return (
<>
<Tooltip title={rest?.title ?? localization.showHideColumns}>
<IconButton aria-label={localization.showHideColumns} onClick={handleClick} {...rest} title={undefined}>
<ViewColumnIcon />
</IconButton>
</Tooltip>
{anchorEl && <DataTable_ShowHideColumnsMenu anchorEl={anchorEl} setAnchorEl={setAnchorEl} table={table} />}
</>
);
};
export default DataTable_ShowHideColumnsButton;

View File

@@ -18,15 +18,15 @@ const columnFilterModeOptionFa = {
};
function FilterBodyField({
column,
filterParameters,
handleChange,
handleBlur,
setFieldValue,
errors,
touched,
resetForm,
}) {
column,
filterParameters,
handleChange,
handleBlur,
setFieldValue,
errors,
touched,
resetForm,
}) {
const [anchorEl, setAnchorEl] = useState(null);
const defaultFilterTranslation = columnFilterModeOptionFa[filterParameters.filterFn] || filterParameters.filterFn;
@@ -48,8 +48,8 @@ function FilterBodyField({
touched={touched}
/>
) : filterParameters.datatype === "numeric" &&
filterParameters.filterFn === "equals" &&
Array.isArray(column.columnSelectOption) ? (
filterParameters.filterFn === "equals" &&
Array.isArray(column.columnSelectOption) ? (
<CustomSelect
column={column}
filterParameters={filterParameters}

View File

@@ -19,7 +19,7 @@ function FilterHeader({ setDrawerState }) {
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<FilterAltIcon sx={{ color: "#fff" }} />
<FilterAltIcon sx={{ color: "#fff", mr: 1 }} />
<Typography variant="h6" sx={{ color: "#fff" }}>
فیلتر
</Typography>

View File

@@ -4,14 +4,15 @@ import { ListItem, Menu } from "@mui/material";
import { useState } from "react";
function FilterOptionList({
column,
filterType,
filterOption,
anchorEl,
columnFilterModeOptionFa,
setAnchorEl,
setFieldValue,
}) {
column,
filterType,
filterOption,
anchorEl,
columnFilterModeOptionFa,
setAnchorEl,
setFieldValue,
}) {
const [selectedFilter, setSelectedFilter] = useState(filterType);
const handleChangeItem = (event, index) => {

View File

@@ -0,0 +1,53 @@
"use client";
import { Box, Drawer, styled } from "@mui/material";
import HideBodyField from "@/core/components/DataTable/hide/HideBodyField";
import HideHeader from "@/core/components/DataTable/hide/HideHeader";
import useDataTable from "@/lib/hooks/useDataTable";
import HideOrShowAll from "@/core/components/DataTable/hide/HideOrShowAll";
const ScrollBox = styled(Box)({
flexGrow: 1,
overflowY: "scroll",
maxWidth: "450px",
"::-webkit-scrollbar": {
width: "5px",
},
"::-webkit-scrollbar-track": {
boxShadow: "inset 0 0 5px #fff",
borderRadius: "5px",
},
"::-webkit-scrollbar-thumb": {
background: "#155175",
borderRadius: "0px",
},
});
function HideBody({ columns, drawerState, setDrawerState }) {
const { hideData, setHideData } = useDataTable();
return (
<Drawer
open={drawerState}
onClose={() => setDrawerState(false)}
sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%" }}
>
<HideHeader setDrawerState={setDrawerState} />
<HideOrShowAll hideData={hideData} setHideData={setHideData} />
<ScrollBox>
<Box sx={{ px: 1, py: 2, display: "flex", flexDirection: "column" }}>
{columns.map((column) => (
<HideBodyField
key={column.id}
column={column}
hideData={hideData}
setHideData={setHideData}
/>
))}
</Box>
</ScrollBox>
</Drawer>
);
}
export default HideBody;

View File

@@ -0,0 +1,80 @@
import { alpha, Box, Checkbox, styled, Typography } from "@mui/material";
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.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 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 (
<Box sx={{ display: "flex", alignItems: "center" }}>
<Checkbox
checked={hideData[column.id]}
onChange={handleCheckboxChange}
name={column.id}
/>
<Typography variant="subtitle1">{column.header}</Typography>
</Box>
);
} else {
return (
<Box sx={{ display: "flex", alignItems: "center", p: 1 }}>
<Typography variant="subtitle1">{column.header}</Typography>
</Box>
);
}
})();
return (
<SimpleTreeView disableSelection>
<CustomTreeItem itemId={column.id} label={labelContent}>
{column.columns?.map((subColumn) => (
<HideBodyField
key={subColumn.id}
column={subColumn}
hideData={hideData[column.id]}
setHideData={setHideData}
/>
))}
</CustomTreeItem>
</SimpleTreeView>
);
}
export default HideBodyField;

View File

@@ -0,0 +1,21 @@
"use client";
import ViewColumnIcon from "@mui/icons-material/ViewColumn";
import { IconButton, Tooltip } from "@mui/material";
function HideButton({ drawerState, setDrawerState }) {
return (
<Tooltip title="نمایش/مخفی کردن ستون ها">
<IconButton
onClick={() => {
setDrawerState(!drawerState);
}}
aria-label="hide table column"
>
<ViewColumnIcon />
</IconButton>
</Tooltip>
);
}
export default HideButton;

View File

@@ -0,0 +1,34 @@
"use client";
import { Box, IconButton, Typography } from "@mui/material";
import CancelIcon from "@mui/icons-material/Cancel";
import ViewColumnIcon from "@mui/icons-material/ViewColumn";
function FilterHeader({ setDrawerState }) {
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
px: 2,
py: 1,
backgroundColor: "#155175",
boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
maxWidth: "450px",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<ViewColumnIcon sx={{ color: "#fff", mr: 1 }} />
<Typography variant="h6" sx={{ color: "#fff" }}>
نمایش/مخفی کردن ستون ها
</Typography>
</Box>
<IconButton sx={{ color: "#fff" }} onClick={() => setDrawerState(false)}>
<CancelIcon sx={{ fontSize: "1em" }} />
</IconButton>
</Box>
);
}
export default FilterHeader;

View File

@@ -0,0 +1,70 @@
"use client";
import { Box, Button } from "@mui/material";
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;
}
}
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;
}
}
return true;
};
function HideOrShowAll({ hideData, setHideData }) {
const handleShowAll = () => {
const newHideData = setAllValues(hideData, true);
setHideData(newHideData);
};
const handleHideAll = () => {
const newHideData = setAllValues(hideData, false);
setHideData(newHideData);
};
const allHidden = allValuesAre(hideData, false);
const allVisible = allValuesAre(hideData, true);
return (
<Box sx={{ mx: 2, my: 1, display: "flex", justifyContent: "space-between" }}>
<Button
color="info"
disabled={allVisible}
variant="contained"
startIcon={<VisibilityIcon />}
onClick={handleShowAll}
>
نمایش همه
</Button>
<Button
color="error"
disabled={allHidden}
variant="contained"
startIcon={<VisibilityOffIcon />}
onClick={handleHideAll}
>
مخفی کردن همه
</Button>
</Box>
);
}
export default HideOrShowAll;

View File

@@ -0,0 +1,24 @@
"use client";
import { useState } from "react";
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 (
<>
<HideButton drawerState={open} setDrawerState={setOpen} />
<HideBody
columns={columns}
drawerState={open}
setDrawerState={setOpen}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
</>
);
}
export default HideColumn;

View File

@@ -1,116 +0,0 @@
import { Box, Button, Divider, Menu } from "@mui/material";
import { useMemo, useState } from "react";
import DataTable_ShowHideColumnsMenuItems from "./ShowHideColumnsMenuItems";
const DataTable_ShowHideColumnsMenu = ({ anchorEl, setAnchorEl, table, ...rest }) => {
const {
getAllColumns,
getAllLeafColumns,
getCenterLeafColumns,
getIsAllColumnsVisible,
getIsSomeColumnsPinned,
getIsSomeColumnsVisible,
getLeftLeafColumns,
getRightLeafColumns,
getState,
options: {
enableColumnOrdering,
enableColumnPinning,
enableHiding,
localization,
mrtTheme: { menuBackgroundColor },
},
} = table;
const { columnOrder, columnPinning, density } = getState();
const handleToggleAllColumns = (value) => {
getAllLeafColumns()
.filter((col) => col.columnDef.enableHiding !== false)
.forEach((col) => col.toggleVisibility(value));
};
const allColumns = useMemo(() => {
const columns = getAllColumns();
if (columnOrder.length > 0 && !columns.some((col) => col.columnDef.columnDefType === "group")) {
return [
...getLeftLeafColumns(),
...Array.from(new Set(columnOrder)).map((colId) =>
getCenterLeafColumns().find((col) => col?.id === colId)
),
...getRightLeafColumns(),
].filter(Boolean);
}
return columns;
}, [
columnOrder,
columnPinning,
getAllColumns(),
getCenterLeafColumns(),
getLeftLeafColumns(),
getRightLeafColumns(),
]);
const isNestedColumns = allColumns.some((col) => col.columnDef.columnDefType === "group");
const [hoveredColumn, setHoveredColumn] = useState(null);
return (
<Menu
MenuListProps={{
dense: density === "compact",
sx: {
backgroundColor: menuBackgroundColor,
},
}}
anchorEl={anchorEl}
disableScrollLock
onClose={() => setAnchorEl(null)}
open={!!anchorEl}
{...rest}
>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
p: "0.5rem",
pt: 0,
}}
>
{enableHiding && (
<Button disabled={!getIsSomeColumnsVisible()} onClick={() => handleToggleAllColumns(false)}>
{localization.hideAll}
</Button>
)}
{enableColumnOrdering && (
<Button onClick={() => table.setColumnOrder(getDefaultColumnOrderIds(table.options, true))}>
{localization.resetOrder}
</Button>
)}
{enableColumnPinning && (
<Button disabled={!getIsSomeColumnsPinned()} onClick={() => table.resetColumnPinning(true)}>
{localization.unpinAll}
</Button>
)}
{enableHiding && (
<Button disabled={getIsAllColumnsVisible()} onClick={() => handleToggleAllColumns(true)}>
{localization.showAll}
</Button>
)}
</Box>
<Divider />
{allColumns.map((column, index) => (
<DataTable_ShowHideColumnsMenuItems
allColumns={allColumns}
column={column}
hoveredColumn={hoveredColumn}
isNestedColumns={isNestedColumns}
key={`${index}-${column.id}`}
setHoveredColumn={setHoveredColumn}
table={table}
/>
))}
</Menu>
);
};
export default DataTable_ShowHideColumnsMenu;

View File

@@ -1,154 +0,0 @@
import { getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils";
import { Box, FormControlLabel, MenuItem, Switch, Tooltip, Typography } from "@mui/material";
import { useRef, useState } from "react";
import DataTable_GrabHandleButton from "../buttons/GrabHandleButton";
const DataTable_ShowHideColumnsMenuItems = ({
allColumns,
column,
hoveredColumn,
isNestedColumns,
setHoveredColumn,
table,
...rest
}) => {
const {
getState,
options: {
enableColumnOrdering,
enableHiding,
localization,
mrtTheme: { draggingBorderColor },
},
setColumnOrder,
} = table;
const { columnOrder } = getState();
const { columnDef } = column;
const { columnDefType } = columnDef;
const switchChecked = column.getIsVisible();
const handleToggleColumnHidden = (column) => {
if (columnDefType === "group") {
column?.columns?.forEach?.((childColumn) => {
childColumn.toggleVisibility(!switchChecked);
});
} else {
column.toggleVisibility();
}
};
const menuItemRef = useRef(null);
const [isDragging, setIsDragging] = useState(false);
const handleDragStart = (e) => {
setIsDragging(true);
try {
e.dataTransfer.setDragImage(menuItemRef.current, 0, 0);
} catch (e) {
console.error(e);
}
};
const handleDragEnd = (_e) => {
setIsDragging(false);
setHoveredColumn(null);
if (hoveredColumn) {
setColumnOrder(reorderColumn(column, hoveredColumn, columnOrder));
}
};
const handleDragEnter = (_e) => {
if (!isDragging && columnDef.enableColumnOrdering !== false) {
setHoveredColumn(column);
}
};
if (!columnDef.header || columnDef.visibleInShowHideMenu === false) {
return null;
}
return (
<>
<MenuItem
disableRipple
onDragEnter={handleDragEnter}
ref={menuItemRef}
{...rest}
sx={(theme) => ({
alignItems: "center",
justifyContent: "flex-start",
my: 0,
opacity: isDragging ? 0.5 : 1,
outline: isDragging
? `2px dashed ${theme.palette.grey[500]}`
: hoveredColumn?.id === column.id
? `2px dashed ${draggingBorderColor}`
: "none",
outlineOffset: "-2px",
pl: `${(column.depth + 0.5) * 2}rem`,
py: "6px",
...parseFromValuesOrFunc(rest?.sx, theme),
})}
>
<Box
sx={{
display: "flex",
flexWrap: "nowrap",
gap: "8px",
}}
>
{columnDefType !== "group" &&
enableColumnOrdering &&
!isNestedColumns &&
(columnDef.enableColumnOrdering !== false ? (
<DataTable_GrabHandleButton
onDragEnd={handleDragEnd}
onDragStart={handleDragStart}
table={table}
/>
) : (
<Box sx={{ width: "28px" }} />
))}
{enableHiding ? (
<FormControlLabel
checked={switchChecked}
componentsProps={{
typography: {
sx: {
mb: 0,
opacity: columnDefType !== "display" ? 1 : 0.5,
},
},
}}
control={
<Tooltip {...getCommonTooltipProps()} title={localization.toggleVisibility}>
<Switch />
</Tooltip>
}
disabled={!column.getCanHide()}
label={columnDef.header}
onChange={() => handleToggleColumnHidden(column)}
/>
) : (
<Typography sx={{ alignSelf: "center" }}>{columnDef.header}</Typography>
)}
</Box>
</MenuItem>
{column.columns?.map((c, i) => (
<DataTable_ShowHideColumnsMenuItems
allColumns={allColumns}
column={c}
hoveredColumn={hoveredColumn}
isNestedColumns={isNestedColumns}
key={`${i}-${c.id}`}
setHoveredColumn={setHoveredColumn}
table={table}
/>
))}
</>
);
};
export default DataTable_ShowHideColumnsMenuItems;

View File

@@ -0,0 +1,22 @@
"use client";
import { IconButton, Tooltip } from "@mui/material";
import AutorenewIcon from "@mui/icons-material/Autorenew";
import useTableSetting from "@/lib/hooks/useTableSetting";
function ResetStorage({ user_id, page_name, table_name }) {
const { resetAction } = useTableSetting();
const reset = () => {
resetAction(user_id, page_name, table_name);
};
return (
<Tooltip title="بازنشانی اطلاعات">
<IconButton onClick={reset} aria-label="reset table data">
<AutorenewIcon />
</IconButton>
</Tooltip>
);
}
export default ResetStorage;

View File

@@ -5,16 +5,17 @@ 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,
...rest
}) => {
table,
table_name,
columns,
user_id,
page_name,
mutate,
need_filter,
table_url,
table_title,
...rest
}) => {
const {
getState,
options: {
@@ -49,19 +50,19 @@ const DataTable_Paper = ({
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,
}
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,
}}
@@ -84,6 +85,7 @@ const DataTable_Paper = ({
user_id={user_id}
page_name={page_name}
table_name={table_name}
table_title={table_title}
/>
))}
<DataTable_TableContainer table={table} />

View File

@@ -1,44 +0,0 @@
import { parseFromValuesOrFunc } from "@/core/utils/utils";
import { Box } from "@mui/material";
import DataTable_ShowHideColumnsButton from "../buttons/ShowHideColumnsButton";
import DataTable_ToggleFiltersButton from "../buttons/ToggleFiltersButton";
const DataTable_ToolbarInternalButtons = ({ table, ...rest }) => {
const {
options: {
columnFilterDisplayMode,
enableColumnFilters,
enableColumnOrdering,
enableColumnPinning,
enableFilters,
enableHiding,
renderToolbarInternalActions,
},
} = table;
return (
<Box
{...rest}
sx={(theme) => ({
alignItems: "center",
display: "flex",
zIndex: 3,
...parseFromValuesOrFunc(rest?.sx, theme),
})}
>
{renderToolbarInternalActions?.({
table,
}) ?? (
<>
{enableFilters && enableColumnFilters && columnFilterDisplayMode !== "popover" && (
<DataTable_ToggleFiltersButton table={table} />
)}
{(enableHiding || enableColumnOrdering || enableColumnPinning) && (
<DataTable_ShowHideColumnsButton table={table} />
)}
</>
)}
</Box>
);
};
export default DataTable_ToolbarInternalButtons;

View File

@@ -1,12 +1,23 @@
import { getCommonToolbarStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
import { Box, useMediaQuery } from "@mui/material";
import { Box, Typography, useMediaQuery } from "@mui/material";
import DataTable_LinearProgressBar from "./LinearProgressBar";
import DataTable_TablePagination from "./TablePagination";
import DataTable_ToolbarInternalButtons from "./ToolbarInternalButtons";
import FilterColumn from "@/core/components/DataTable/filter";
import RefactorTable from "@/core/components/DataTable/refactor/RefactorTable";
import UpdateTable from "@/core/components/DataTable/update/UpdateTable";
import ResetStorage from "@/core/components/DataTable/reset/ResetStorage";
import HideColumn from "@/core/components/DataTable/hide";
const DataTable_TopToolbar = ({ mutate, need_filter, table, columns, table_url, user_id, page_name, table_name }) => {
const DataTable_TopToolbar = ({
mutate,
need_filter,
table,
columns,
table_url,
user_id,
page_name,
table_name,
table_title,
}) => {
const {
getState,
options: {
@@ -46,11 +57,12 @@ const DataTable_TopToolbar = ({ mutate, need_filter, table, columns, table_url,
>
<Box
sx={{
alignItems: "flex-start",
flexWrap: { xs: "wrap", sm: "no-wrap" },
boxSizing: "border-box",
display: "flex",
gap: "0.5rem",
justifyContent: "space-between",
alignItems: "center",
py: "0.5rem",
position: stackAlertBanner ? "relative" : "absolute",
right: 0,
@@ -58,18 +70,33 @@ const DataTable_TopToolbar = ({ mutate, need_filter, table, columns, table_url,
width: "100%",
}}
>
{renderTopToolbarCustomActions?.({ table }) ?? <span />}
<Box sx={{
display: "flex",
alignItems: "center",
order: { xs: 2, sm: 1 },
}}>{renderTopToolbarCustomActions?.({ table })}</Box>
<Typography sx={{ textAlign: "center", order: { xs: 1, sm: 2 }, width: { xs: "100%", sm: "unset" } }}
fontWeight={600}>{table_title || ""}</Typography>
{enableToolbarInternalActions && (
<Box
sx={{
alignItems: "center",
display: "flex",
flexWrap: "wrap-reverse",
gap: "0.5rem",
flexWrap: "wrap-reverse",
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
order: 3,
}}
>
<RefactorTable mutate={mutate} />
<ResetStorage user_id={user_id}
page_name={page_name}
table_name={table_name} />
<UpdateTable mutate={mutate} />
<HideColumn
columns={table.options.columns}
user_id={user_id}
page_name={page_name}
table_name={table_name} />
{need_filter && (
<FilterColumn
columns={columns}
@@ -79,7 +106,6 @@ const DataTable_TopToolbar = ({ mutate, need_filter, table, columns, table_url,
table_name={table_name}
/>
)}
<DataTable_ToolbarInternalButtons table={table} />
</Box>
)}
</Box>

View File

@@ -2,18 +2,18 @@
import { IconButton, Tooltip } from "@mui/material";
import RestartAltIcon from "@mui/icons-material/RestartAlt";
function RefactorTable({ mutate }) {
const refactor = () => {
function UpdateTable({ mutate }) {
const update = () => {
mutate();
};
return (
<Tooltip title=ازنشانی اطلاعات">
<IconButton onClick={refactor} aria-label="refactor table">
<Tooltip title=روزرسانی اطلاعات">
<IconButton onClick={update} aria-label="refactor table">
<RestartAltIcon />
</IconButton>
</Tooltip>
);
}
export default RefactorTable;
export default UpdateTable;

View File

@@ -5,9 +5,11 @@ import { Box, Button, Typography } from "@mui/material";
import DownloadIcon from "@mui/icons-material/Download";
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();
const flattenHideData = flattenObjectOfObjects(hideData);
const onSaveFilter = () => {
const filteredItems = Object.keys(filterData)
@@ -26,7 +28,7 @@ function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, ta
.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, hideData, columns);
hideAction(user_id, page_name, table_name, flattenHideData, columns);
toast.dismiss({ containerId: "datatable" });
};
@@ -37,42 +39,33 @@ function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, ta
return (
<Box sx={{ width: "100%" }}>
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", mb: 1 }}>
<Typography color="#155175" variant="subtitle1" sx={{ fontWeight: "500" }}>
<Typography color="primary.main" variant="subtitle1" sx={{ fontWeight: "500" }}>
ذخیره سازی تغییرات
</Typography>
<SaveIcon sx={{ color: "#155175" }} />
<SaveIcon sx={{ color: "primary.main" }} />
</Box>
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">آیا مایل به ذخیره تغییر های اعمال شده برای دفعات بعد هستید؟</Typography>
</Box>
<Box sx={{ display: "flex", gap: 1, mt: 1 }}>
<Box sx={{ display: "flex", gap: 1, mt: 2 }}>
<Button
variant="contained"
onClick={handleDismiss}
sx={{
backgroundColor: "#792626",
":hover": { backgroundColor: "#792626" },
boxShadow: "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
}}
>
رد کردن
</Button>
<Button
variant="contained"
component="label"
size="small"
endIcon={<DownloadIcon />}
onClick={onSaveFilter}
sx={{
backgroundColor: "#155175",
":hover": { backgroundColor: "#155175" },
boxShadow: "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
}}
>
ذخیره
</Button>
<Button
variant="outlined"
size="small"
onClick={handleDismiss}
>
رد کردن
</Button>
</Box>
</Box>
);
}
export default AskForKeepData;
export default AskForKeepData;

View File

@@ -0,0 +1,12 @@
"use client";
import { Chip, Divider, Typography } from "@mui/material";
const PageTitle = ({ title }) => {
return (
<Divider><Chip
label={<Typography fontSize={14} fontWeight={500}>{title}</Typography>} /></Divider>
);
};
export default PageTitle;

View File

@@ -1,10 +1,10 @@
export const flattenArrayOfObjects = (array, key) => {
return array.reduce((acc, obj) => {
acc.push(obj);
if (Array.isArray(obj[key])) {
acc.push(...flattenArrayOfObjects(obj[key]));
} else {
acc.push(obj);
acc.push(...flattenArrayOfObjects(obj[key], key));
}
return acc;
}, []);
};

View File

@@ -0,0 +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];
}
}
}
return res;
};

View File

@@ -19,44 +19,64 @@ const DataTableProvider = ({ children, user_id, page_name, table_name, columns }
useEffect(() => {
if (!settingStore) return;
const values = flatColumns.reduce((acc, column) => {
const filterValues = flatColumns.reduce((acc, column) => {
if (!column.enableColumnFilter) return acc;
const filter = settingStore?.[user_id]?.[page_name]?.[table_name]?.["filters"]?.find(
(filter) => filter.id === column.id
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: filter?.value || [],
filterFn: filter?.filterFn || column._filterFn,
value: storeFilter?.value || [],
filterFn: storeFilter?.filterFn || column._filterFn,
datatype: column.datatype,
};
} else if (column._filterFn === "between") {
acc[column.id] = {
id: column.id,
value: filter?.value || ["", ""],
filterFn: filter?.filterFn || column._filterFn,
value: storeFilter?.value || ["", ""],
filterFn: storeFilter?.filterFn || column._filterFn,
datatype: column.datatype,
};
} else {
acc[column.id] = {
id: column.id,
value: filter?.value || "",
filterFn: filter?.filterFn || column._filterFn,
value: storeFilter?.value || "",
filterFn: storeFilter?.filterFn || column._filterFn,
datatype: column.datatype,
};
}
return acc;
}, {});
setFilterData(values);
setInitFilter(values);
setFilterData(filterValues);
setInitFilter(filterValues);
setSortData(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []);
setInitSort(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []);
setHideData(settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"] || {});
setInitHide(settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"] || {});
setInitStates(true);
}, [settingStore, isInitStates]);
useEffect(() => {
const getHideValues = (columns) => {
return columns.reduce((acc, column) => {
const columnId = column.id;
const storeHide = settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"]?.[columnId];
// If the column has nested columns, process them recursively
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);
}, [settingStore, isInitStates]);
useEffect(() => {
if (
JSON.stringify(initFilter) !== JSON.stringify(filterData) ||
@@ -81,7 +101,7 @@ const DataTableProvider = ({ children, user_id, page_name, table_name, columns }
position: "bottom-left",
draggable: true,
autoClose: false,
}
},
);
} else {
toast.update("keep_data", {

View File

@@ -21,6 +21,23 @@ export const TableSettingProvider = ({ children }) => {
const filterAction = (user_id, page_name, table_name, settingValue, columns) => {
updateSettingStorage(user_id, page_name, table_name, "filters", settingValue, columns);
};
const resetAction = (user_id, page_name, table_name) => {
const prevLocalStorage = JSON.parse(localStorage.getItem("_setting-app")) || {};
const userSettings = prevLocalStorage[user_id] || {};
const pageSettings = userSettings[page_name] || {};
delete pageSettings[table_name];
const resetData = {
...prevLocalStorage,
[user_id]: {
...userSettings,
[page_name]: {
...pageSettings,
},
},
};
localStorage.setItem("_setting-app", JSON.stringify(resetData));
setSettingStore(resetData);
};
const updateSettingStorage = (user_id, page_name, table_name, settingType, settingValue, columns) => {
const prevLocalStorage = JSON.parse(localStorage.getItem("_setting-app")) || {};
const userSettings = prevLocalStorage[user_id] || {};
@@ -46,7 +63,7 @@ export const TableSettingProvider = ({ children }) => {
...tableSettings,
[settingType]: Array.isArray(settingValue) ? [...newSettings] : { ...newSettings },
},
columns
columns,
),
},
},
@@ -117,7 +134,7 @@ export const TableSettingProvider = ({ children }) => {
};
return (
<TableSettingContext.Provider value={{ settingStore, hideAction, sortAction, filterAction }}>
<TableSettingContext.Provider value={{ settingStore, hideAction, sortAction, filterAction, resetAction }}>
{children}
</TableSettingContext.Provider>
);

View File

@@ -2,8 +2,8 @@ import { useContext } from "react";
import { TableSettingContext } from "../contexts/tableSetting";
const useTableSetting = () => {
const { settingStore, hideAction, sortAction, filterAction } = useContext(TableSettingContext);
return { settingStore, hideAction, sortAction, filterAction };
const { settingStore, hideAction, sortAction, filterAction, resetAction } = useContext(TableSettingContext);
return { settingStore, hideAction, sortAction, filterAction, resetAction };
};
export default useTableSetting;