diff --git a/example.env.local b/example.env.local
index 078bd0d..922eec0 100644
--- a/example.env.local
+++ b/example.env.local
@@ -7,5 +7,7 @@ NEXT_PUBLIC_PRIMARY_MAIN = "#1b4332"
NEXT_PUBLIC_SECONDARY_MAIN = "#800e13"
NEXT_PUBLIC_BASE_URL = "https://crm.witel.ir"
+NEXT_PUBLIC_SERVER_SOCKET_URL = "wss://crmws.witel.ir"
+NEXT_PUBLIC_POWERED_BY_URL = "https://witel.ir"
NODE_ENV = "development"
\ No newline at end of file
diff --git a/jest.setup.js b/jest.setup.js
index 4298493..7d55f67 100644
--- a/jest.setup.js
+++ b/jest.setup.js
@@ -1,5 +1,6 @@
import '@testing-library/jest-dom'
import {server} from "./mocks/server";
+import mockRouter from 'next-router-mock'
require('dotenv').config({path: './.env.local'});
@@ -10,6 +11,8 @@ beforeAll(() => {
})
beforeEach(() => {
localStorage.clear();
+ mockRouter.query = {}
+
})
afterEach(() => {
diff --git a/package.json b/package.json
index 6e19bf6..5d6417a 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"react-dom": "^18.2.0",
"react-toastify": "^9.1.3",
"sass": "^1.62.0",
+ "socket.io-client": "^4.7.2",
"stylis": "^4.1.3",
"stylis-plugin-rtl": "^2.1.1",
"swr": "^2.1.5",
diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json
index 885b641..3613a1c 100644
--- a/public/locales/fa/app.json
+++ b/public/locales/fa/app.json
@@ -2,6 +2,7 @@
"app_name": "سامانه CRM",
"app_short_name": "سامانه CRM",
"dashboard": "داشبورد",
+ "powered_by_witel": "توسعه یافته توسط وایتل",
"first_page": "خوش آمدید",
"login": "ورود",
"login_expert": "ورود کارشناس",
diff --git a/src/components/first/__tests__/index.test.js b/src/components/first/__tests__/index.test.js
index 7e60576..6710f8c 100644
--- a/src/components/first/__tests__/index.test.js
+++ b/src/components/first/__tests__/index.test.js
@@ -1,42 +1,61 @@
+import {render, screen, waitFor} from "@testing-library/react";
import FirstComponent from "@/components/first";
-import {render, screen} from "@testing-library/react";
import MockAppWithProviders from "../../../../mocks/AppWithProvider";
import {server} from "../../../../mocks/server";
import {rest} from "msw";
import {GET_USER_ROUTE} from "@/core/data/apiRoutes";
-describe('First page component', () => {
- describe('Rendering', () => {
- it('Should see app name text', () => {
- render(, {wrapper: MockAppWithProviders})
- const appNameElement = screen.getByTestId('app-name')
- expect(appNameElement).toHaveTextContent('سامانه CRM')
+describe("First Component From First Page", () => {
+ describe("Rendering", () => {
+ it("App Name Text Rendered", () => {
+ render();
+ const appNameElement = screen.queryByText(/سامانه CRM/i);
+ expect(appNameElement).toBeInTheDocument()
+ });
+ it("App version Text Rendered", () => {
+ render();
+ const versionControler = screen.queryByText(process.env.NEXT_PUBLIC_API_VERSION, {exact: false});
+ expect(versionControler).toBeInTheDocument()
+ });
+ it("Powered By Rendered With Currect URL", () => {
+ render();
+ const linkElement = screen.queryByText('توسعه یافته توسط وایتل');
+ expect(linkElement).toBeInTheDocument()
+ expect(linkElement).toHaveAttribute('href', process.env.NEXT_PUBLIC_POWERED_BY_URL);
});
});
- describe('behavior', () => {
- it('Should see login button when is not auth', async () => {
- render(, {wrapper: MockAppWithProviders})
- const buttonLoginOrDashboard = await screen.findByTestId('button-login-or-dashboard')
- expect(buttonLoginOrDashboard).toHaveTextContent('ورود کارشناس')
- expect(buttonLoginOrDashboard).not.toHaveTextContent('داشبورد')
+ describe("Behavioral", () => {
+ it("Show Login Button And Do Not Show Dashboard Button When User Is Not Authenticated", async () => {
+ render();
+ await waitFor(() => {
+ const authenticationButtonLogin = screen.queryByText(/ورود کارشناس/i)
+ const authenticationButtonDashboard = screen.queryByText(/داشبورد/i)
+ expect(authenticationButtonLogin).toBeInTheDocument()
+ expect(authenticationButtonDashboard).not.toBeInTheDocument()
+ })
});
- it('Should see dashboard button when is auth', async () => {
+ it("Show Dashboard Button And Do Not Show Login Button When User Is Authenticated", async () => {
localStorage.setItem("_token", 'token');
- render(, {wrapper: MockAppWithProviders})
- const buttonLoginOrDashboard = await screen.findByTestId('button-login-or-dashboard')
- expect(buttonLoginOrDashboard).not.toHaveTextContent('ورود کارشناس')
- expect(buttonLoginOrDashboard).toHaveTextContent('داشبورد')
+ render();
+ await waitFor(() => {
+ const authenticationButtonLogin = screen.queryByText(/ورود کارشناس/i)
+ const authenticationButtonDashboard = screen.queryByText(/داشبورد/i)
+ expect(authenticationButtonLogin).not.toBeInTheDocument()
+ expect(authenticationButtonDashboard).toBeInTheDocument()
+ })
});
- it('Should see login button when token expire', async () => {
+ it("Show Login Button And Do Not Show Dashboard Button When User Authentication Is Expired", async () => {
localStorage.setItem("_token", 'token');
server.use([rest.get(GET_USER_ROUTE, (req, res, ctx) => {
return res(ctx.status(403))
})])
- render(, {wrapper: MockAppWithProviders})
- const buttonLoginOrDashboard = await screen.findByTestId('button-login-or-dashboard')
- expect(buttonLoginOrDashboard).toHaveTextContent('ورود کارشناس')
- expect(buttonLoginOrDashboard).not.toHaveTextContent('داشبورد')
+ render();
+ await waitFor(() => {
+ const authenticationButtonLogin = screen.queryByText(/ورود کارشناس/i)
+ const authenticationButtonDashboard = screen.queryByText(/داشبورد/i)
+ expect(authenticationButtonLogin).toBeInTheDocument()
+ expect(authenticationButtonDashboard).not.toBeInTheDocument()
+ })
});
-
});
});
\ No newline at end of file
diff --git a/src/components/first/index.jsx b/src/components/first/index.jsx
index 786f25f..1d7166d 100644
--- a/src/components/first/index.jsx
+++ b/src/components/first/index.jsx
@@ -1,4 +1,4 @@
-import {NextLinkComposed} from "@/core/components/LinkRouting";
+import LinkRouting, {NextLinkComposed} from "@/core/components/LinkRouting";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import useUser from "@/lib/app/hooks/useUser";
@@ -14,7 +14,7 @@ const FirstComponent = () => {
-
+
{t("app_name")}
+ }}
+ >
+ v{process.env.NEXT_PUBLIC_API_VERSION}
+
+
+
+
+ {t("powered_by_witel")}
+
);
diff --git a/src/components/login-expert/LoginExpertComponent.jsx b/src/components/login-expert/LoginExpertComponent.jsx
new file mode 100644
index 0000000..9be301b
--- /dev/null
+++ b/src/components/login-expert/LoginExpertComponent.jsx
@@ -0,0 +1,123 @@
+import {Box, Button, Container, Paper, Stack, TextField, Typography} from "@mui/material";
+import {Field, Formik} from "formik";
+import SvgLogin from "@/core/components/svgs/SvgLogin";
+import StyledForm from "@/core/components/StyledForm";
+import PasswordField from "@/core/components/PasswordField";
+import LoginIcon from "@mui/icons-material/Login";
+import {GET_USER_TOKEN} from "@/core/data/apiRoutes";
+import * as Yup from "yup";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useUser from "@/lib/app/hooks/useUser";
+import {useTranslations} from "next-intl";
+
+const LoginExpertComponent = () =>{
+ const t = useTranslations();
+ const requestServer = useRequest()
+ const {setToken} = useUser(); // pass token to set token
+ const handleSubmit = (values, props) => {
+ requestServer(GET_USER_TOKEN, 'post', {
+ data: {
+ username: values.username,
+ password: values.password,
+ },
+ success: {
+ notification: {show: false}
+ }
+ }).then((response) => {
+ setToken(response.data.token)
+ }).catch(() => {
+ props.setSubmitting(false)
+ })
+ };
+ const initialValues = {
+ username: "",
+ password: "",
+ };
+ const validationSchema = Yup.object().shape({
+ username: Yup.string().required(t("LoginPage.username_error_message_required")),
+ password: Yup.string().required(t("LoginPage.password_error_message_required")),
+ });
+
+ return(
+
+
+
+ {(props) => (
+
+
+
+
+
+ {t("login_expert")}
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+ )
+}
+export default LoginExpertComponent
\ No newline at end of file
diff --git a/src/components/login-expert/LoginLinkRouting.jsx b/src/components/login-expert/LoginLinkRouting.jsx
new file mode 100644
index 0000000..1930b3c
--- /dev/null
+++ b/src/components/login-expert/LoginLinkRouting.jsx
@@ -0,0 +1,28 @@
+import LinkRouting from "@/core/components/LinkRouting";
+import {Stack} from "@mui/material";
+import {useRouter} from "next/router";
+import {useTranslations} from "next-intl";
+
+const LoginLinkRouting = () => {
+ const t = useTranslations();
+ const router = useRouter()
+ const backUrlDecodedPath = router.query?.back_url
+
+ return (
+
+
+ {t("LoginPage.link_routing_back_to")}{" "}
+ {backUrlDecodedPath
+ ? t("LoginPage.link_routing_previuos_page")
+ : t("LoginPage.link_routing_main_page")}
+
+
+ )
+}
+export default LoginLinkRouting
\ No newline at end of file
diff --git a/src/components/login-expert/__test__/LoginExpertComponent.test.js b/src/components/login-expert/__test__/LoginExpertComponent.test.js
new file mode 100644
index 0000000..d76e49d
--- /dev/null
+++ b/src/components/login-expert/__test__/LoginExpertComponent.test.js
@@ -0,0 +1,153 @@
+import {act, findByText, fireEvent, getByText, render, screen, waitFor} from '@testing-library/react';
+import MockAppWithProviders from '../../../../mocks/AppWithProvider';
+import mockRouter from 'next-router-mock'
+import LoginExpertComponent from "@/components/login-expert/LoginExpertComponent";
+import LoginLinkRouting from "@/components/login-expert/LoginLinkRouting";
+
+describe('Login expert component from login page', () => {
+
+ describe('Rendering', () => {
+ it('LoginExpertComponent should see login expert text on the page',() => {
+ render(
+
+
+
+ );
+ const loginExpertElement = screen.getByRole('heading', { level: 4 });
+ expect(loginExpertElement).toHaveTextContent('ورود کارشناس');
+ });
+
+ it('LoginExpertComponent from LoginComponent Button should render login text', () => {
+ render(
+
+
+
+ );
+ const button = screen.getByText("ورود");
+ // Assertions for button props
+ expect(button).toHaveAttribute('type', 'submit');
+ expect(button).toHaveTextContent('ورود');
+ });
+
+ it("Show error when username is empty", async ()=>{
+ render(
+
+
+
+ );
+
+ const usernameInput = screen.getByLabelText("نام کاربری")
+
+ expect(screen.queryByText("وارد کردن نام کاربری الزامیست")).not.toBeInTheDocument()
+
+ fireEvent.blur(usernameInput);
+
+ await waitFor(()=>{
+ expect(screen.queryByText("وارد کردن نام کاربری الزامیست")).toBeInTheDocument()
+ })
+
+ fireEvent.change(usernameInput, {target : {value : "testuser"}})
+
+ await waitFor(()=>{
+ expect(screen.queryByText("وارد کردن نام کاربری الزامیست")).not.toBeInTheDocument()
+ })
+ })
+ it("Show error when password is empty", async ()=>{
+ render(
+
+
+
+ );
+
+ const passwordInput = screen.getByLabelText("رمز عبور")
+
+ expect(screen.queryByText("وارد کردن رمز عبور الزامیست")).not.toBeInTheDocument()
+
+ fireEvent.blur(passwordInput);
+
+ await waitFor(()=>{
+ expect(screen.queryByText("وارد کردن رمز عبور الزامیست")).toBeInTheDocument()
+ })
+
+ fireEvent.change(passwordInput, {target : {value : "testuser"}})
+
+ await waitFor(()=>{
+ expect(screen.queryByText("وارد کردن رمز عبور الزامیست")).not.toBeInTheDocument()
+ })
+ })
+ });
+
+ describe("Behavior", ()=>{
+ it('Should fill the username field', async () => {
+ render(
+
+
+
+ );
+ // Get username and password input elements by their name attributes
+ const usernameInput = screen.getByLabelText('نام کاربری');
+
+ fireEvent.change(usernameInput, {target: {value: 'testuser'}});
+ await act(async ()=>{
+ // Simulate user input
+ expect(usernameInput).toHaveValue('testuser');
+ })
+ });
+
+ it('Should fill the password fields', async () => {
+ render(
+
+
+
+ );
+ // Get username and password input elements by their name attributes
+ const passwordInput = screen.getByLabelText('رمز عبور');
+ fireEvent.change(passwordInput, {target: {value: 'password123'}});
+
+ await act(async ()=>{
+ // Simulate user input
+ expect(passwordInput).toHaveValue('password123');
+ })
+ });
+
+ // this test is for when back url does not exist to run this test you should comment if in mock func
+ it('Should get main page when back url dos not exist', async () => {
+ render(
+
+
+
+ )
+ const linkElement = await screen.findByTestId("link_routing")
+ expect(linkElement).toHaveTextContent("بازگشت به صفحه اصلی")
+ });
+
+ })
+ describe("validation", ()=>{
+ it("Disabled submit button until fields completed", async ()=> {
+ render(
+
+
+
+ )
+ const usernameInput = screen.getByLabelText('نام کاربری');
+ const passwordInput = screen.getByLabelText('رمز عبور');
+ const submitButton = screen.getByText('ورود');
+
+ expect(submitButton).toBeDisabled();
+
+ fireEvent.change(usernameInput, {target: {value: 'testuser'}});
+
+ await waitFor(async () => {
+ // Now, the submit button should be enabled because both fields are completed
+ expect(submitButton).toBeDisabled();
+ });
+
+ fireEvent.change(passwordInput, {target: {value: 'password123'}});
+
+ await waitFor(async () => {
+ // Now, the submit button should be enabled because both fields are completed
+ expect(submitButton).toBeEnabled();
+ });
+ })
+ })
+});
\ No newline at end of file
diff --git a/src/components/login-expert/__test__/LoginLinkRouting.test.js b/src/components/login-expert/__test__/LoginLinkRouting.test.js
new file mode 100644
index 0000000..a63d314
--- /dev/null
+++ b/src/components/login-expert/__test__/LoginLinkRouting.test.js
@@ -0,0 +1,18 @@
+import {render, screen} from "@testing-library/react";
+import MockAppWithProviders from "../../../../mocks/AppWithProvider";
+import LoginLinkRouting from "@/components/login-expert/LoginLinkRouting";
+
+describe("Login expert component from login page",()=>{
+
+ describe('Rendering', () => {
+ it('LoginLinkRouting from LoginComponent Should get main page when back url dos not exist', async () => {
+ render(
+
+
+
+ )
+ const linkElement = await screen.findByTestId("link_routing")
+ expect(linkElement).toHaveTextContent("بازگشت به صفحه اصلی")
+ });
+ })
+})
diff --git a/src/components/login-expert/index.jsx b/src/components/login-expert/index.jsx
index 9f22a5b..dc36d9a 100644
--- a/src/components/login-expert/index.jsx
+++ b/src/components/login-expert/index.jsx
@@ -1,151 +1,16 @@
-import LinkRouting from "@/core/components/LinkRouting";
-import PasswordField from "@/core/components/PasswordField";
-import StyledForm from "@/core/components/StyledForm";
-import {GET_USER_TOKEN} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
-import useUser from "@/lib/app/hooks/useUser";
-import LoginIcon from "@mui/icons-material/Login";
-import {Box, Button, Container, Paper, Stack, TextField, Typography,} from "@mui/material";
-import {Field, Formik} from "formik";
-import {useTranslations} from "next-intl";
-import {useSearchParams} from "next/navigation";
-import * as Yup from "yup";
-import useDirection from "@/lib/app/hooks/useDirection";
-import SvgLogin from "@/core/components/svgs/SvgLogin";
-import useRequest from "@/lib/app/hooks/useRequest";
+import LoginLinkRouting from "@/components/login-expert/LoginLinkRouting";
+import LoginExpertComponent from "@/components/login-expert/LoginExpertComponent";
const LoginComponent = () => {
- const t = useTranslations();
- const {directionApp} = useDirection(); // should delete because we don't have direction anymore
- const {setToken} = useUser(); // pass token to set token
- const requestServer = useRequest()
-
- // getting url query
- const searchParams = useSearchParams();
- const backUrlDecodedPath = searchParams.get("back_url");
-
- //formik properties
- const handleSubmit = (values, props) => {
- requestServer(GET_USER_TOKEN, 'post', {
- data: {
- username: values.username,
- password: values.password,
- },
- success: {
- notification: {show: false}
- }
- }).then((response) => {
- setToken(response.data.token)
- }).catch(() => {
- props.setSubmitting(false)
- })
- };
- const initialValues = {
- username: "",
- password: "",
- };
- const validationSchema = Yup.object().shape({
- username: Yup.string().required(t("LoginPage.username_error_message_required")),
- password: Yup.string().required(t("LoginPage.password_error_message_required")),
- });
return (
-
-
-
- {(props) => (
-
-
-
-
-
- {t("login_expert")}
-
-
-
-
-
-
-
-
-
-
-
- )}
-
-
-
+
-
-
- {t("LoginPage.link_routing_back_to")}{" "}
- {backUrlDecodedPath
- ? t("LoginPage.link_routing_previuos_page")
- : t("LoginPage.link_routing_main_page")}
-
-
+
);
};
diff --git a/src/core/components/PasswordField/__test__/index.test.js b/src/core/components/PasswordField/__test__/index.test.js
new file mode 100644
index 0000000..479f91f
--- /dev/null
+++ b/src/core/components/PasswordField/__test__/index.test.js
@@ -0,0 +1,31 @@
+import {fireEvent, getByRole, render, screen} from "@testing-library/react";
+import PasswordField from "@/core/components/PasswordField";
+import {Formik} from "formik";
+
+describe('Password Field component in core folder', () => {
+ describe('Rendering', () => {
+ it('Show password when visibility icon clicked',() => {
+ render (
+ {}}>
+ {(props)=>(
+
+ )}
+
+ )
+
+ const iconElement = screen.getByLabelText("رمز عبور")
+ const iconButton = screen.getByRole("button")
+
+
+ expect(iconElement).toHaveAttribute('type', 'password');
+
+ fireEvent.click(iconButton);
+
+ expect(iconElement).toHaveAttribute("type", "text");
+
+ fireEvent.click(iconButton);
+
+ expect(iconElement).toHaveAttribute('type', 'password');
+ })
+ })
+})
\ No newline at end of file
diff --git a/src/core/components/PasswordField.jsx b/src/core/components/PasswordField/index.jsx
similarity index 100%
rename from src/core/components/PasswordField.jsx
rename to src/core/components/PasswordField/index.jsx
diff --git a/src/core/components/notifications/ErrorNotification.jsx b/src/core/components/notifications/ErrorNotification.jsx
index 4ff1ab0..05e2fb9 100644
--- a/src/core/components/notifications/ErrorNotification.jsx
+++ b/src/core/components/notifications/ErrorNotification.jsx
@@ -36,4 +36,4 @@ const ErrorNotification = (t, status, message) => {
);
};
-export default ErrorNotification;
+export default ErrorNotification;
\ No newline at end of file
diff --git a/src/core/components/notifications/PendingNotification.jsx b/src/core/components/notifications/PendingNotification.jsx
index 846b847..6183f6b 100644
--- a/src/core/components/notifications/PendingNotification.jsx
+++ b/src/core/components/notifications/PendingNotification.jsx
@@ -9,4 +9,4 @@ const PendingNotification = (t) => {
});
};
-export default PendingNotification;
+export default PendingNotification;
\ No newline at end of file
diff --git a/src/core/components/notifications/SuccessNotification.jsx b/src/core/components/notifications/SuccessNotification.jsx
index 998deaa..3507cef 100644
--- a/src/core/components/notifications/SuccessNotification.jsx
+++ b/src/core/components/notifications/SuccessNotification.jsx
@@ -39,4 +39,4 @@ const SuccessNotification = (t, status) => {
);
};
-export default SuccessNotification;
+export default SuccessNotification;
\ No newline at end of file
diff --git a/src/core/components/notifications/UploadFileNotification.jsx b/src/core/components/notifications/UploadFileNotification.jsx
index 6556944..89ebbb2 100644
--- a/src/core/components/notifications/UploadFileNotification.jsx
+++ b/src/core/components/notifications/UploadFileNotification.jsx
@@ -35,4 +35,4 @@ const UploadFileNotification = (t) => {
);
};
-export default UploadFileNotification;
+export default UploadFileNotification;
\ No newline at end of file
diff --git a/src/core/components/notifications/WarningNotification.jsx b/src/core/components/notifications/WarningNotification.jsx
index 8493180..19d6a2f 100644
--- a/src/core/components/notifications/WarningNotification.jsx
+++ b/src/core/components/notifications/WarningNotification.jsx
@@ -37,4 +37,4 @@ const WarningNotification = (t, status) => {
);
};
-export default WarningNotification;
+export default WarningNotification;
\ No newline at end of file
diff --git a/src/core/utils/errorHandler.js b/src/core/utils/errorHandler.js
index 9bd18f1..8dbd364 100644
--- a/src/core/utils/errorHandler.js
+++ b/src/core/utils/errorHandler.js
@@ -48,7 +48,7 @@ const isServerError = status => status >= 500 && status <= 599;
const isClientError = status => status >= 400 && status <= 499;
const errorLogic = (response, t, notification) => {
- if (notification) ErrorNotification(t, response.status)
+ if (notification) ErrorNotification(t, response.status, response.data.message)
}
const errorValidation = (response, t, notification) => {
if (notification) {
diff --git a/src/lib/app/contexts/socket.jsx b/src/lib/app/contexts/socket.jsx
new file mode 100644
index 0000000..7da4f43
--- /dev/null
+++ b/src/lib/app/contexts/socket.jsx
@@ -0,0 +1,15 @@
+import {createContext, useMemo} from "react";
+import {io} from "socket.io-client";
+
+export const SocketContext = createContext()
+
+export const SocketProvider = ({children}) => {
+ const socket = useMemo(() => io(process.env.NEXT_PUBLIC_SERVER_SOCKET_URL, {
+ autoConnect: false,
+ auth: {
+ token: ""
+ }
+ }), [])
+
+ 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 10611b8..0d7adeb 100644
--- a/src/lib/app/contexts/user.jsx
+++ b/src/lib/app/contexts/user.jsx
@@ -2,6 +2,7 @@ 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,
@@ -39,6 +40,7 @@ const reducer = (state, action) => {
export const UserContext = createContext();
export const UserProvider = ({children}) => {
+ const socket = useSocket()
const [state, dispatch] = useReducer(reducer, initialUser);
const clearUser = useCallback(() => {
@@ -75,7 +77,7 @@ export const UserProvider = ({children}) => {
headers: {authorization: `Bearer ${state.token}`},
})
.then(({data}) => {
- if (typeof callback === "function") callback(data);
+ if (typeof callback === "function") callback(data.data);
})
.catch(error => {
if (error.response) {
@@ -100,12 +102,16 @@ 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/useSocket.jsx b/src/lib/app/hooks/useSocket.jsx
new file mode 100644
index 0000000..3b9855d
--- /dev/null
+++ b/src/lib/app/hooks/useSocket.jsx
@@ -0,0 +1,10 @@
+import {useContext} from "react";
+import {SocketContext} from "@/lib/app/contexts/socket";
+
+const useSocket = () => {
+ const {socket} = useContext(SocketContext)
+
+ return socket
+}
+
+export default useSocket
\ No newline at end of file
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index e76fbcb..fe249a6 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -7,24 +7,27 @@ import {UserProvider} from "@/lib/app/contexts/user";
import "moment/locale/fa";
import {NextIntlProvider} from "next-intl";
import TitlePage from "@/core/components/TitlePage";
+import {SocketProvider} from "@/lib/app/contexts/socket";
const App = ({Component, pageProps}) => {
return (<>
-
-
-
-
- {pageProps.messages ? : ''}
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ {pageProps.messages ? : ''}
+
+
+
+
+
+
+
+
+
+
>)
};