diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json
index 3613a1c..e6d60eb 100644
--- a/public/locales/fa/app.json
+++ b/public/locales/fa/app.json
@@ -15,6 +15,8 @@
"between": "میان",
"online_message": "شما به اینترنت وصل هستید",
"offline_message": "اتصال شما به اینترنت قطع شده است",
+ "socket_is_connect_message": "شما به سوکت وصل هستید",
+ "socket_is_not_connect_message": "اتصال شما به سوکت قطع شده است",
"header": {
"open_profile": "پروفایل",
"edit_profile": " پروفایل",
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetButton.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetButton.jsx
index 416e5c8..76af95c 100644
--- a/src/components/layouts/Dashboard/CallWidget/CallWidgetButton.jsx
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetButton.jsx
@@ -1,10 +1,12 @@
import PermPhoneMsgIcon from '@mui/icons-material/PermPhoneMsg';
import StyledFab from "@/core/components/StyledFab";
+import useCallDialog from "@/lib/callWidget/hooks/useCallDialog";
-const CallWidgetButton = ({setOpen}) => {
+const CallWidgetButton = () => {
+ const {setOpenCallDialog} = useCallDialog()
return (
setOpen(true)}>
+ onClick={() => setOpenCallDialog(true)}>
)
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallActions/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallActions/index.jsx
new file mode 100644
index 0000000..5b9326f
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallActions/index.jsx
@@ -0,0 +1,7 @@
+const CallActions = ({tab}) => {
+ return (
+ <>CallActions - {tab.id}>
+ )
+}
+
+export default CallActions
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/index.jsx
new file mode 100644
index 0000000..292c640
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory/index.jsx
@@ -0,0 +1,7 @@
+const CallHistory = ({tab}) => {
+ return (
+ <>CallHistory - {tab.id}>
+ )
+}
+
+export default CallHistory
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/index.jsx
new file mode 100644
index 0000000..79dc736
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/index.jsx
@@ -0,0 +1,19 @@
+import {Grid} from "@mui/material";
+import CallActions from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallActions";
+import CallHistory from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel/CallHistory";
+
+const CallTabPanel = ({tab}) => {
+ return (
+
+
+
+
+
+
+
+
+ )
+}
+
+export default CallTabPanel
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/CallTabLabel.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/CallTabLabel.jsx
new file mode 100644
index 0000000..7a9b703
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/CallTabLabel.jsx
@@ -0,0 +1,23 @@
+import {IconButton, Stack, Typography, Zoom} from "@mui/material";
+import CloseIcon from '@mui/icons-material/Close';
+import useAnswers from "@/lib/callWidget/hooks/useAnswers";
+
+const CallTabLabel = ({tab}) => {
+ const {closeAnswerTab} = useAnswers()
+ const handleCloseClick = (id) => {
+ closeAnswerTab(id)
+ };
+
+ return (
+
+ {tab.phone_number} - {tab.id}
+
+ handleCloseClick(tab.id)}>
+
+
+
+
+ )
+}
+
+export default CallTabLabel
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/index.jsx
new file mode 100644
index 0000000..70fccd9
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/index.jsx
@@ -0,0 +1,27 @@
+import {Box, Tab, Tabs} from "@mui/material";
+import CallTabLabel
+ from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList/CallTabLabel";
+import useAnswers from "@/lib/callWidget/hooks/useAnswers";
+
+const CallTabsList = () => {
+ const {answersList, changeActiveTabAnswers, activeTab} = useAnswers()
+ const handleChange = (event, newValue) => {
+ changeActiveTabAnswers(newValue)
+ };
+
+ return (
+
+
+ {answersList.map((answer) => (
+ } key={answer.id}/>
+ ))}
+
+
+ )
+}
+
+export default CallTabsList
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/index.jsx
new file mode 100644
index 0000000..4e1d2f1
--- /dev/null
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/index.jsx
@@ -0,0 +1,17 @@
+import CallTabsList from "src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabsList";
+import CallTabPanel from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs/CallTabPanel";
+import useAnswers from "@/lib/callWidget/hooks/useAnswers";
+
+const CallTabs = () => {
+ const {answersList} = useAnswers()
+
+ return (
+ <>
+
+ {answersList.map((answer) => (
+
+ ))}
+ >
+ )
+}
+export default CallTabs
\ No newline at end of file
diff --git a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/index.jsx b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/index.jsx
index 77ed57d..5afb0a1 100644
--- a/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/index.jsx
+++ b/src/components/layouts/Dashboard/CallWidget/CallWidgetDialog/index.jsx
@@ -1,23 +1,47 @@
import {Dialog} from "@mui/material";
import {DialogTransition} from "@/core/components/DialogTransition";
+import {useEffect} from "react";
+import useCallDialog from "@/lib/callWidget/hooks/useCallDialog";
+import CallTabs from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog/CallTabs";
+import useAnswers from "@/lib/callWidget/hooks/useAnswers";
+import useSocket from "@/lib/app/hooks/useSocket";
-const CallWidgetDialog = ({open, setOpen}) => {
+const CallWidgetDialog = () => {
+ const {openCallDialog, setOpenCallDialog} = useCallDialog()
+ const {answersList, newAnswerTab} = useAnswers()
+ const socket = useSocket()
- const handleClose = () => {
- setOpen(false);
- };
+ useEffect(() => {
+ const answerCall = (data, act) => {
+ newAnswerTab({
+ id: data.id,
+ phone_number: data.phone_number
+ })
+ act()
+ }
+ socket.on('answer', answerCall)
+
+ return () => {
+ socket.off('answer', answerCall)
+ }
+ }, []);
+
+ useEffect(() => {
+ if (answersList.length === 0) {
+ setOpenCallDialog(false)
+ return
+ }
+ setOpenCallDialog(true)
+ }, [answersList.length]);
return (
- <>
-
- >
+
)
}
diff --git a/src/components/layouts/Dashboard/CallWidget/index.jsx b/src/components/layouts/Dashboard/CallWidget/index.jsx
index 4d871b2..d6fe5a0 100644
--- a/src/components/layouts/Dashboard/CallWidget/index.jsx
+++ b/src/components/layouts/Dashboard/CallWidget/index.jsx
@@ -1,14 +1,27 @@
import CallWidgetButton from "@/components/layouts/Dashboard/CallWidget/CallWidgetButton";
import CallWidgetDialog from "@/components/layouts/Dashboard/CallWidget/CallWidgetDialog";
-import {useState} from "react";
+import {AnswersProvider} from "@/lib/callWidget/contexts/answers";
+import useSocket from "@/lib/app/hooks/useSocket";
+import {useEffect} from "react";
const CallWidget = () => {
- const [open, setOpen] = useState(false)
+ const socket = useSocket()
+
+ useEffect(() => {
+ if (socket.connected) return
+
+ socket.connect()
+
+ return () => {
+ socket.disconnect()
+ }
+ }, []);
+
return (
- <>
-
-
- >
+
+
+
+
)
}
diff --git a/src/core/components/NetworkComponent.jsx b/src/core/components/NetworkComponent.jsx
index 8ebbb68..22d4620 100644
--- a/src/core/components/NetworkComponent.jsx
+++ b/src/core/components/NetworkComponent.jsx
@@ -6,13 +6,13 @@ import WifiOffIcon from '@mui/icons-material/WifiOff';
import {useTranslations} from "next-intl";
const NetworkComponent = () => {
- const toastId = useRef(null);
+ const networkToastId = useRef(null);
const network = useNetwork()
const t = useTranslations()
useEffect(() => {
if (network.online) {
- toast.update(toastId.current, {
+ toast.update(networkToastId.current, {
type: toast.TYPE.SUCCESS,
render: t('online_message'),
autoClose: 2000,
@@ -22,8 +22,7 @@ const NetworkComponent = () => {
});
return
}
- toast.dismiss()
- toastId.current = toast.warn(t('offline_message'), {
+ networkToastId.current = toast.warn(t('offline_message'), {
autoClose: false, closeButton: false, closeOnClick: false, icon:
})
}, [network.online]);
diff --git a/src/core/components/StyledFab.jsx b/src/core/components/StyledFab.jsx
index dd935cc..95c5ff7 100644
--- a/src/core/components/StyledFab.jsx
+++ b/src/core/components/StyledFab.jsx
@@ -5,7 +5,6 @@ const StyledFab = styled(Fab)`
bottom: 16px;
/* @noflip */
left: 16px;
- z-index: 1500;
`;
export default StyledFab;
diff --git a/src/layouts/MuiLayout.jsx b/src/layouts/MuiLayout.jsx
index 6dcd3ed..eba3449 100644
--- a/src/layouts/MuiLayout.jsx
+++ b/src/layouts/MuiLayout.jsx
@@ -22,26 +22,23 @@ const MuiLayout = ({children, isBot}) => {
{
+ const {user, isAuth} = useUser()
+ const [connectionError, setConnectionError] = useState(false)
+ const socketToastId = useRef(null);
+ const t = useTranslations()
const socket = useMemo(() => io(process.env.NEXT_PUBLIC_SERVER_SOCKET_URL, {
autoConnect: false,
auth: {
@@ -11,5 +20,48 @@ export const SocketProvider = ({children}) => {
}
}), [])
+ useEffect(() => {
+ if (isAuth) {
+ socket.auth.token = user.telephone_id
+ return
+ }
+ socket.auth.token = ''
+ }, [isAuth]);
+
+ useEffect(() => {
+ const connectErrorHandler = () => {
+ setConnectionError(true)
+ }
+ const connectHandler = () => {
+ setConnectionError(false)
+ }
+ socket.on("connect_error", connectErrorHandler);
+ socket.on("connect", connectHandler);
+
+ return () => {
+ socket.off("connect_error", connectErrorHandler);
+ socket.off("connect", connectHandler);
+ }
+ }, []);
+
+ useEffect(() => {
+ if (!connectionError) {
+ toast.update(socketToastId.current, {
+ type: toast.TYPE.SUCCESS,
+ render: t('socket_is_connect_message'),
+ autoClose: 2000,
+ closeButton: true,
+ closeOnClick: true,
+ icon:
+ });
+ return
+ }
+ socketToastId.current = toast.warn(t('socket_is_not_connect_message'), {
+ draggable: false,
+ autoClose: false, closeButton: false, closeOnClick: false, icon:
+ })
+
+ }, [connectionError]);
+
return {children}
}
\ No newline at end of file
diff --git a/src/lib/app/contexts/user.jsx b/src/lib/app/contexts/user.jsx
index 0d7adeb..899ac1b 100644
--- a/src/lib/app/contexts/user.jsx
+++ b/src/lib/app/contexts/user.jsx
@@ -2,7 +2,6 @@ import {GET_USER_ROUTE} from "@/core/data/apiRoutes";
import axios from "axios";
import {createContext, useCallback, useEffect, useReducer} from "react";
import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler";
-import useSocket from "@/lib/app/hooks/useSocket";
const initialUser = {
isAuth: false,
@@ -40,7 +39,6 @@ const reducer = (state, action) => {
export const UserContext = createContext();
export const UserProvider = ({children}) => {
- const socket = useSocket()
const [state, dispatch] = useReducer(reducer, initialUser);
const clearUser = useCallback(() => {
@@ -102,16 +100,12 @@ export const UserProvider = ({children}) => {
clearUser();
changeAuthState(false);
changeLanguageState(false);
-
- socket.auth.token = ""
return;
}
getUser((data) => {
changeUser(data);
changeAuthState(true);
changeLanguageState(true);
-
- socket.auth.token = data.telephone_id
});
}, [state.token]);
diff --git a/src/lib/app/hooks/useNetwork.jsx b/src/lib/app/hooks/useNetwork.jsx
index 84e2950..9c436a5 100644
--- a/src/lib/app/hooks/useNetwork.jsx
+++ b/src/lib/app/hooks/useNetwork.jsx
@@ -1,29 +1,5 @@
import {useEffect, useState} from "react";
-function getNetworkConnection() {
- return (
- navigator.connection ||
- navigator.mozConnection ||
- navigator.webkitConnection ||
- null
- );
-}
-
-function getNetworkConnectionInfo() {
- const connection = getNetworkConnection();
- if (!connection) {
- return {};
- }
- return {
- rtt: connection.rtt,
- type: connection.type,
- saveData: connection.saveData,
- downLink: connection.downLink,
- downLinkMax: connection.downLinkMax,
- effectiveType: connection.effectiveType,
- };
-}
-
function useNetwork() {
const [state, setState] = useState(() => {
return {
@@ -51,7 +27,7 @@ function useNetwork() {
window.removeEventListener("offline", handleOffline);
};
}, []);
-
+
return state;
}
diff --git a/src/lib/callWidget/contexts/answers.jsx b/src/lib/callWidget/contexts/answers.jsx
new file mode 100644
index 0000000..a9f7ae2
--- /dev/null
+++ b/src/lib/callWidget/contexts/answers.jsx
@@ -0,0 +1,31 @@
+import {createContext, useReducer, useState} from "react";
+
+const reducer = (state, action) => {
+ switch (action.type) {
+ case "CHANGE_ACTIVE_TAB":
+ return state.map((answer, index) => action.newValue === index ? {...answer, active: true} : {
+ ...answer,
+ active: false
+ });
+ case "CHANGE_LIST":
+ return [...action.newList]
+ default:
+ return state;
+ }
+}
+export const AnswersContext = createContext()
+export const AnswersProvider = ({children}) => {
+ const [openCallDialog, setOpenCallDialog] = useState(false)
+ const [activeTab, setActiveTab] = useState(0)
+ const [state, dispatch] = useReducer(reducer, []);
+
+ return {children}
+}
diff --git a/src/lib/callWidget/hooks/useAnswers.jsx b/src/lib/callWidget/hooks/useAnswers.jsx
new file mode 100644
index 0000000..2155cd7
--- /dev/null
+++ b/src/lib/callWidget/hooks/useAnswers.jsx
@@ -0,0 +1,38 @@
+import {useContext} from "react";
+import {AnswersContext} from "@/lib/callWidget/contexts/answers";
+
+const useAnswers = () => {
+ const {state, dispatch, activeTab, setActiveTab} = useContext(AnswersContext)
+
+ const changeActiveTabAnswers = (newValue) => {
+ dispatch({type: 'CHANGE_ACTIVE_TAB', newValue})
+ setActiveTab(newValue)
+ }
+
+ const newAnswerTab = (data) => {
+ const newAnswer = {
+ id: data.id,
+ phone_number: data.phone_number,
+ active: true
+ }
+ const newList = [...state, newAnswer]
+ dispatch({type: 'CHANGE_LIST', newList})
+ changeActiveTabAnswers(newList.length - 1)
+ }
+
+ const closeAnswerTab = (id) => {
+ const index = state.findIndex(answer => answer.id === id)
+ const newIndex = index === 0 ? 0 : index - 1
+ const newList = [...state]
+ newList.splice(index, 1);
+ if (newList.length !== 0) {
+ newList[newIndex].active = true
+ setActiveTab(newIndex)
+ }
+ dispatch({type: 'CHANGE_LIST', newList})
+ }
+
+ return {answersList: state, activeTab, setActiveTab, changeActiveTabAnswers, closeAnswerTab, newAnswerTab}
+}
+
+export default useAnswers
\ No newline at end of file
diff --git a/src/lib/callWidget/hooks/useCallDialog.jsx b/src/lib/callWidget/hooks/useCallDialog.jsx
new file mode 100644
index 0000000..30dd599
--- /dev/null
+++ b/src/lib/callWidget/hooks/useCallDialog.jsx
@@ -0,0 +1,10 @@
+import {useContext} from "react";
+import {AnswersContext} from "@/lib/callWidget/contexts/answers";
+
+const useCallDialog = () => {
+ const {openCallDialog, setOpenCallDialog} = useContext(AnswersContext)
+
+ return {openCallDialog, setOpenCallDialog}
+}
+
+export default useCallDialog
\ No newline at end of file
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index fe249a6..c5fad77 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -12,22 +12,22 @@ import {SocketProvider} from "@/lib/app/contexts/socket";
const App = ({Component, pageProps}) => {
return (<>
-
-
-
-
-
- {pageProps.messages ? : ''}
-
-
+
+
+
+
+ {pageProps.messages ? : ''}
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
>)
};