diff --git a/package.json b/package.json
index 4a1bf6b..7bec569 100644
--- a/package.json
+++ b/package.json
@@ -41,4 +41,4 @@
"eslint-config-prettier": "^9.1.0",
"prettier": "^3.3.2"
}
-}
\ No newline at end of file
+}
diff --git a/public/global.scss b/public/global.scss
index 1af3ae3..d1d10e3 100644
--- a/public/global.scss
+++ b/public/global.scss
@@ -5,5 +5,4 @@
box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px,
rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
background-color: #d0dfe8;
- border: 1px dashed #095b8c;
}
diff --git a/src/app/(withAuth)/dashboard/layout.js b/src/app/(withAuth)/dashboard/layout.js
index cb48375..f00cb95 100644
--- a/src/app/(withAuth)/dashboard/layout.js
+++ b/src/app/(withAuth)/dashboard/layout.js
@@ -11,5 +11,5 @@ const Layout = ({ children }) => {
);
-}
+};
export default Layout;
\ No newline at end of file
diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js
index db8aebd..3ea2e65 100644
--- a/src/core/components/DataTable/Main.js
+++ b/src/core/components/DataTable/Main.js
@@ -76,65 +76,43 @@ const data = [
];
const DataTable_Main = (props) => {
- const { filterData } = useDataTable();
+ const { filterData, sortData, setSortData } = useDataTable();
const { table_url, user_id, page_name, table_name, columns, initialStateProps } = props;
const flatColumns = flattenArrayOfObjects(columns, "columns");
- const { settingStore, hideAction, sortAction } = useTableSetting();
+ const { settingStore, hideAction } = useTableSetting();
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
- const filters = 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);
- const storedFilters = settingStore?.[user_id]?.[page_name]?.[table_name]?.filters;
- const finalFilters = storedFilters || filters;
-
- const fetchUrl = useMemo(() => {
- const params = new URLSearchParams();
- params.set("start", `${pagination.pageIndex * pagination.pageSize}`);
- params.set("size", pagination.pageSize);
- params.set("filters", JSON.stringify(finalFilters ?? []));
- params.set("sorting", JSON.stringify(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] ?? []));
- return `${table_url}?${params}`;
- }, [table_url, finalFilters, pagination, columns]);
const onColumnVisibilityChange = (event) => {
const settingValue = event();
hideAction(user_id, page_name, table_name, settingValue, flatColumns);
};
+
const onSortingChange = (event) => {
- const settingValue = event(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []);
- sortAction(user_id, page_name, table_name, settingValue, flatColumns);
+ setSortData(event);
};
+ const fetchUrl = useMemo(() => {
+ const params = new URLSearchParams();
+ params.set("start", `${pagination.pageIndex * pagination.pageSize}`);
+ params.set("size", pagination.pageSize);
+ params.set("filters", JSON.stringify(filterData ?? []));
+ params.set("sorting", JSON.stringify(sortData));
+ return `${table_url}?${params}`;
+ }, [table_url, filterData, pagination, columns]);
+
const table = useMaterialReactTable({
localization: FA_DATATABLE_LOCALIZATION,
columns,
data: data,
- // manualSorting: true,
- renderTopToolbarCustomActions: ({ table }) => (
- <>
-
- >
- ),
initialState: {
density: "compact",
columnVisibility: settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"],
- sorting: settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || [],
+ sorting: sortData,
...initialStateProps,
},
state: {
columnVisibility: settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"],
- sorting: settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || [],
+ sorting: sortData,
pagination,
},
muiTableHeadProps: {
@@ -162,10 +140,15 @@ const DataTable_Main = (props) => {
},
manualFiltering: true,
manualPagination: true,
- onPaginationChange: setPagination,
manualSorting: true,
+ onPaginationChange: setPagination,
onColumnVisibilityChange: onColumnVisibilityChange,
onSortingChange: onSortingChange,
+ renderTopToolbarCustomActions: ({ table }) => (
+ <>
+
+ >
+ ),
...props,
});
diff --git a/src/core/components/DataTable/filter/FilterBody.jsx b/src/core/components/DataTable/filter/FilterBody.jsx
index 9dafb03..1f8513c 100644
--- a/src/core/components/DataTable/filter/FilterBody.jsx
+++ b/src/core/components/DataTable/filter/FilterBody.jsx
@@ -3,12 +3,10 @@
import { Box, Button, Drawer, styled } from "@mui/material";
import { Form, Formik } from "formik";
import useTableSetting from "@/lib/hooks/useTableSetting";
-import { useEffect, useRef, useState } from "react";
+import { useEffect, useState } from "react";
import FilterHeader from "@/core/components/DataTable/filter/FilterHeader";
import * as Yup from "yup";
import FilterBodyField from "@/core/components/DataTable/filter/FilterBodyField";
-import { toast } from "react-toastify";
-import AskForKeep from "@/core/components/NotificationDesign/AskForKeep";
import useDataTable from "@/lib/hooks/useDataTable";
const ScrollBox = styled(Box)({
@@ -29,46 +27,13 @@ const ScrollBox = styled(Box)({
});
function FilterBody({ columns, drawerState, setDrawerState, user_id, page_name, table_name }) {
- const { settingStore, filterAction } = useTableSetting();
+ const { settingStore } = useTableSetting();
const [initialValues, setInitialValues] = useState({});
const [validationSchema, setValidationSchema] = useState({});
const { filterData, setFilterData } = useDataTable();
- const filterDataRef = useRef(filterData);
- useEffect(() => {
- filterDataRef.current = filterData;
- }, [filterData]);
useEffect(() => {
- const values = columns.reduce((acc, column) => {
- if (!column.enableColumnFilter) return acc;
- const filter = 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?.fn || column._filterFn,
- datatype: column.datatype,
- };
- } else if (column._filterFn === "between") {
- acc[column.id] = {
- id: column.id,
- value: filter?.value || ["", ""],
- filterFn: filter?.fn || column._filterFn,
- datatype: column.datatype,
- };
- } else {
- acc[column.id] = {
- id: column.id,
- value: filter?.value || "",
- filterFn: filter?.fn || column._filterFn,
- datatype: column.datatype,
- };
- }
- return acc;
- }, {});
- setInitialValues(Object.keys(filterData).length !== 0 ? filterData : values);
+ setInitialValues(filterData);
}, [columns, settingStore, user_id, page_name, table_name, filterData]);
useEffect(() => {
@@ -107,49 +72,16 @@ function FilterBody({ columns, drawerState, setDrawerState, user_id, page_name,
}, [initialValues]);
const handleSubmit = (values, { setSubmitting }) => {
- toast.dismiss({ containerId: "filtering" });
setDrawerState(false);
setFilterData(values);
- toast(, {
- containerId: "filtering",
- className: "filter-toast",
- position: "bottom-left",
- draggable: true,
- autoClose: false,
- });
setSubmitting(false);
};
- const onSaveFilter = () => {
- const currentFilterData = filterDataRef.current;
- const arrayOfObjects = Object.keys(currentFilterData)
- .map((key) => {
- const value = currentFilterData[key].value;
- if (
- value !== "" &&
- !(
- Array.isArray(value) &&
- (value.length === 0 || (value.length === 2 && value[0] === "" && value[1] === ""))
- )
- ) {
- return currentFilterData[key];
- }
- })
- .filter(Boolean);
- filterAction(user_id, page_name, table_name, arrayOfObjects, columns);
- toast.dismiss({ containerId: "filtering" });
- };
-
return (
setDrawerState(false)}
- sx={{
- overflowY: "hidden",
- display: "flex",
- flexDirection: "column",
- height: "100%",
- }}
+ sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%" }}
>
{Object.keys(initialValues).length > 0 && (
diff --git a/src/core/components/DataTable/filter/FilterOptionList.jsx b/src/core/components/DataTable/filter/FilterOptionList.jsx
index e088832..86a4745 100644
--- a/src/core/components/DataTable/filter/FilterOptionList.jsx
+++ b/src/core/components/DataTable/filter/FilterOptionList.jsx
@@ -32,12 +32,7 @@ function FilterOptionList({
key={index}
onClick={(event) => handleChangeItem(event, index)}
selected={option === selectedFilter}
- sx={{
- cursor: "pointer",
- width: "100px",
- display: "flex",
- justifyContent: "center",
- }}
+ sx={{ cursor: "pointer", width: "100px", display: "flex", justifyContent: "center" }}
>
{columnFilterModeOptionFa[option]}
diff --git a/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx b/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx
index b4da7f5..22eb5f9 100644
--- a/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx
+++ b/src/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker.jsx
@@ -7,7 +7,6 @@ import ClearIcon from "@mui/icons-material/Clear";
import moment from "jalali-moment";
function MuiDatePicker({ value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error }) {
-
return (
{
return (
-
+
);
diff --git a/src/core/components/NotificationDesign/AskForKeep.jsx b/src/core/components/NotificationDesign/AskForKeep.jsx
index d4721bb..e69de29 100644
--- a/src/core/components/NotificationDesign/AskForKeep.jsx
+++ b/src/core/components/NotificationDesign/AskForKeep.jsx
@@ -1,61 +0,0 @@
-"use client";
-
-import SaveIcon from "@mui/icons-material/Save";
-import { Box, Button, Typography } from "@mui/material";
-import DownloadIcon from "@mui/icons-material/Download";
-import { toast } from "react-toastify";
-
-function AskForKeep({ onSaveFilter }) {
- const handleDismiss = () => {
- toast.dismiss({ containerId: "filtering" });
- };
-
- return (
-
-
-
- ذخیره سازی اطلاعات
-
-
-
-
- آیا مایل به ذخیره فیلتر های اعمال شده برای دفعات بعد هستید؟
-
-
-
- }
- 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",
- }}
- >
- ذخیره فیلتر
-
-
-
- );
-}
-
-export default AskForKeep;
diff --git a/src/core/components/NotificationDesign/AskForKeepData.jsx b/src/core/components/NotificationDesign/AskForKeepData.jsx
new file mode 100644
index 0000000..552aee1
--- /dev/null
+++ b/src/core/components/NotificationDesign/AskForKeepData.jsx
@@ -0,0 +1,78 @@
+"use client";
+
+import SaveIcon from "@mui/icons-material/Save";
+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";
+
+function AskForKeepData({ filterData, sortData, user_id, page_name, table_name, columns }) {
+ const { filterAction, sortAction } = useTableSetting();
+
+ 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);
+ toast.dismiss({ containerId: "datatable" });
+ };
+
+ const handleDismiss = () => {
+ toast.dismiss({ containerId: "datatable" });
+ };
+
+ return (
+
+
+
+ ذخیره سازی تغییرات
+
+
+
+
+ آیا مایل به ذخیره تغییر های اعمال شده برای دفعات بعد هستید؟
+
+
+
+ }
+ 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",
+ }}
+ >
+ ذخیره
+
+
+
+ );
+}
+
+export default AskForKeepData;
\ No newline at end of file
diff --git a/src/lib/contexts/DataTable.jsx b/src/lib/contexts/DataTable.jsx
new file mode 100644
index 0000000..32b2a7c
--- /dev/null
+++ b/src/lib/contexts/DataTable.jsx
@@ -0,0 +1,110 @@
+import { createContext, useEffect, useState } from "react";
+import { toast } from "react-toastify";
+import AskForKeepData from "@/core/components/NotificationDesign/AskForKeepData";
+import useTableSetting from "@/lib/hooks/useTableSetting";
+import { flattenArrayOfObjects } from "@/core/utils/flattenArrayOfObjects";
+
+export const DataTableContext = createContext();
+
+const DataTableProvider = ({ children, user_id, page_name, table_name, columns }) => {
+ const { settingStore } = useTableSetting();
+ const [isInitStates, setInitStates] = useState(false);
+ const flatColumns = flattenArrayOfObjects(columns, "columns");
+ const [initFilter, setInitFilter] = useState({});
+ const [initSort, setInitSort] = useState([]);
+ const [filterData, setFilterData] = useState({});
+ const [sortData, setSortData] = useState([]);
+
+ useEffect(() => {
+ if (!settingStore) return;
+ const values = 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
+ );
+ if (column.datatype === "array") {
+ acc[column.id] = {
+ id: column.id,
+ value: filter?.value || [],
+ filterFn: filter?.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,
+ datatype: column.datatype,
+ };
+ } else {
+ acc[column.id] = {
+ id: column.id,
+ value: filter?.value || "",
+ filterFn: filter?.filterFn || column._filterFn,
+ datatype: column.datatype,
+ };
+ }
+ return acc;
+ }, {});
+ setFilterData(values);
+ setSortData(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []);
+ setInitFilter(values);
+ setInitSort(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []);
+ setInitStates(true);
+ }, [settingStore, isInitStates]);
+
+ useEffect(() => {
+ if (
+ JSON.stringify(initFilter) !== JSON.stringify(filterData) ||
+ JSON.stringify(initSort) !== JSON.stringify(sortData)
+ ) {
+ if (!toast.isActive("keep_data", "datatable")) {
+ toast(
+ ,
+ {
+ containerId: "datatable",
+ toastId: "keep_data",
+ className: "filter-toast",
+ position: "bottom-left",
+ draggable: true,
+ autoClose: false,
+ }
+ );
+ } else {
+ toast.update("keep_data", {
+ containerId: "datatable",
+ toastId: "keep_data",
+ render: (
+
+ ),
+ });
+ }
+ } else {
+ toast.dismiss({ containerId: "datatable" });
+ }
+ }, [filterData, sortData]);
+
+ if (!isInitStates) return null;
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default DataTableProvider;
diff --git a/src/lib/contexts/tableSetting.js b/src/lib/contexts/tableSetting.js
index 3611df9..8b05828 100644
--- a/src/lib/contexts/tableSetting.js
+++ b/src/lib/contexts/tableSetting.js
@@ -96,10 +96,7 @@ export const TableSettingProvider = ({ children }) => {
}
if (values.hides) {
- const hidesArray = Object.entries(values.hides).map((e) => ({
- id: e[0],
- value: e[1],
- }));
+ const hidesArray = Object.entries(values.hides).map((e) => ({ id: e[0], value: e[1] }));
if (hidesArray.length > 0) {
const _list = [];
for (const hide of hidesArray) {
@@ -136,15 +133,7 @@ export const TableSettingProvider = ({ children }) => {
};
return (
-
+
{children}
);
diff --git a/src/lib/hooks/useDataTable.jsx b/src/lib/hooks/useDataTable.jsx
new file mode 100644
index 0000000..e2feecb
--- /dev/null
+++ b/src/lib/hooks/useDataTable.jsx
@@ -0,0 +1,9 @@
+import { useContext } from "react";
+import { DataTableContext } from "@/lib/contexts/DataTable";
+
+const useTableSetting = () => {
+ const { filterData, setFilterData, sortData, setSortData } = useContext(DataTableContext);
+ return { filterData, setFilterData, sortData, setSortData };
+};
+
+export default useTableSetting;
diff --git a/src/lib/hooks/useTableSetting.jsx b/src/lib/hooks/useTableSetting.jsx
new file mode 100644
index 0000000..6588446
--- /dev/null
+++ b/src/lib/hooks/useTableSetting.jsx
@@ -0,0 +1,9 @@
+import { useContext } from "react";
+import { TableSettingContext } from "../contexts/tableSetting";
+
+const useTableSetting = () => {
+ const { settingStore, hideAction, sortAction, filterAction, refactorAction } = useContext(TableSettingContext);
+ return { settingStore, hideAction, sortAction, filterAction, refactorAction };
+};
+
+export default useTableSetting;