Feature/user management
This commit is contained in:
211
src/lib/contexts/DataTable.js
Normal file
211
src/lib/contexts/DataTable.js
Normal file
@@ -0,0 +1,211 @@
|
||||
import { createContext, useEffect, useState } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
import useTableSetting from "@/lib/hooks/useTableSetting";
|
||||
import { flattenArrayOfObjects } from "@/core/utils/flattenArrayOfObjects";
|
||||
import AskForKeepData from "@/core/components/NotificationDesign/AskForKeepData";
|
||||
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);
|
||||
|
||||
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(
|
||||
<AskForKeepData
|
||||
filterData={filterData}
|
||||
sortData={sortData}
|
||||
hideData={hideData}
|
||||
user_id={user_id}
|
||||
page_name={page_name}
|
||||
table_name={table_name}
|
||||
columns={flatColumns}
|
||||
/>,
|
||||
{
|
||||
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: (
|
||||
<AskForKeepData
|
||||
filterData={filterData}
|
||||
sortData={sortData}
|
||||
hideData={hideData}
|
||||
user_id={user_id}
|
||||
page_name={page_name}
|
||||
table_name={table_name}
|
||||
columns={flatColumns}
|
||||
/>
|
||||
),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
toast.dismiss({ containerId: "datatable" });
|
||||
}
|
||||
}, [filterData, sortData, hideData]);
|
||||
|
||||
if (!isInitStates) return <LinearProgress sx={{ borderRadius: 2 }} />;
|
||||
|
||||
return (
|
||||
<DataTableContext.Provider
|
||||
value={{
|
||||
filterData,
|
||||
setFilterData,
|
||||
sortData,
|
||||
setSortData,
|
||||
hideData,
|
||||
setHideData,
|
||||
isDirty,
|
||||
isAnyDirty,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</DataTableContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default DataTableProvider;
|
||||
@@ -24,6 +24,7 @@ export const SocketProvider = ({ children }) => {
|
||||
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}`, {
|
||||
@@ -35,7 +36,7 @@ export const SocketProvider = ({ children }) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (user?.telephone_id) {
|
||||
socket.auth.token = user.telephone_id;
|
||||
socket.auth.token = { telephone_id: user.telephone_id, user_id: user.id };
|
||||
}
|
||||
}, [user, socket]);
|
||||
|
||||
@@ -102,7 +103,21 @@ export const SocketProvider = ({ children }) => {
|
||||
};
|
||||
}, [socket]);
|
||||
|
||||
const contextValue = useMemo(() => ({ socket, status }), [socket, status]);
|
||||
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 (
|
||||
<SocketContext.Provider value={contextValue}>
|
||||
|
||||
27
src/lib/hooks/useDataTable.js
Normal file
27
src/lib/hooks/useDataTable.js
Normal file
@@ -0,0 +1,27 @@
|
||||
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,
|
||||
};
|
||||
};
|
||||
|
||||
export default useTableSetting;
|
||||
29
src/lib/hooks/useProvince.js
Normal file
29
src/lib/hooks/useProvince.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { useEffect, useState } from "react";
|
||||
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);
|
||||
|
||||
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();
|
||||
}, []);
|
||||
|
||||
return { provinces, loadingProvinces, errorProvinces };
|
||||
};
|
||||
|
||||
export default useProvinces;
|
||||
29
src/lib/hooks/useRoles.js
Normal file
29
src/lib/hooks/useRoles.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { useEffect, useState } from "react";
|
||||
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);
|
||||
|
||||
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();
|
||||
}, []);
|
||||
|
||||
return { roles, loadingRoles, errorRoles };
|
||||
};
|
||||
|
||||
export default useRoles;
|
||||
10
src/lib/hooks/useTableSetting.js
Normal file
10
src/lib/hooks/useTableSetting.js
Normal file
@@ -0,0 +1,10 @@
|
||||
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 };
|
||||
};
|
||||
|
||||
export default useTableSetting;
|
||||
Reference in New Issue
Block a user