add prettier for formatting to project

This commit is contained in:
2025-07-28 12:18:27 +03:30
parent 1a6cb32528
commit 3a36561ab0
180 changed files with 15437 additions and 14748 deletions

View File

@@ -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(
<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}
/>
),
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 <LinearProgress sx={{ borderRadius: 2 }} />;
// تبدیل آبجکت به آبجکت فلت شده
const flatHideData = flattenObject(hideData);
return (
<DataTableContext.Provider
value={{
filterData,
setFilterData,
sortData,
setSortData,
hideData,
setHideData,
isDirty,
isAnyDirty,
}}
>
{children}
</DataTableContext.Provider>
);
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;

View File

@@ -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 (
<AuthContext.Provider
value={{
user: state.user,
isAuth: state.isAuth,
initAuthState: state.initAuthState,
getUser,
logout,
errorState,
}}
>
{children}
</AuthContext.Provider>
);
useEffect(() => {
getUser();
}, []);
return (
<AuthContext.Provider
value={{
user: state.user,
isAuth: state.isAuth,
initAuthState: state.initAuthState,
getUser,
logout,
errorState,
}}
>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);

View File

@@ -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 (
<CallContext.Provider value={contextValue}>{children}</CallContext.Provider>
);
return <CallContext.Provider value={contextValue}>{children}</CallContext.Provider>;
};
export const useCall = () => useContext(CallContext);

View File

@@ -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 (
<CategoriesContext.Provider value={contextValue}>
{children}
</CategoriesContext.Provider>
);
return <CategoriesContext.Provider value={contextValue}>{children}</CategoriesContext.Provider>;
};
export const useCategory = () => useContext(CategoriesContext);

View File

@@ -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 }) => <Power />,
});
} 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 }) => <PowerOff />,
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 }) => <PowerOff />,
},
);
}
}
}, [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 }) => <Power />,
});
} 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 }) => <PowerOff />,
});
} else {
socketToastId.current = toast.warn("ارتباط با سرور قطع شد. در حال تلاش برای بازیابی…", {
containerId: "socket_connection",
autoClose: false,
closeButton: false,
draggable: false,
icon: ({ theme, type }) => <PowerOff />,
});
}
}
}, [status]);
const contextValue = useMemo(
() => ({ socket, status, clientsOnline }),
[socket, status, clientsOnline],
);
useEffect(() => {
if (status == "connected") return;
return (
<SocketContext.Provider value={contextValue}>
{children}
</SocketContext.Provider>
);
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 <SocketContext.Provider value={contextValue}>{children}</SocketContext.Provider>;
};
export default SocketContext;

View File

@@ -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 (
<TableSettingContext.Provider
value={{
settingStore,
hideAction,
sortAction,
filterAction,
resetAction,
}}
>
{children}
</TableSettingContext.Provider>
);
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 (
<TableSettingContext.Provider
value={{
settingStore,
hideAction,
sortAction,
filterAction,
resetAction,
}}
>
{children}
</TableSettingContext.Provider>
);
};

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,
});
};

View File

@@ -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;

View File

@@ -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<AxiosResponse>} - 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<AxiosResponse>} - 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;

View File

@@ -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;

View File

@@ -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,
});
};

View File

@@ -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;