From 0a7165c646df99ea6b43c04a00e7ebcc527e5988 Mon Sep 17 00:00:00 2001 From: Amirhossein Mahmoodi Date: Wed, 23 Aug 2023 11:12:18 +0330 Subject: [PATCH] add GlobalHead.jsx and NetworkComponent.jsx and useNetwork.jsx and fixed bugs --- public/locales/fa/app.json | 2 + .../dashboard/edit-profile/index.jsx | 72 +----------------- src/core/components/GlobalHead.jsx | 58 +++++++++++++++ src/core/components/NetworkComponent.jsx | 34 +++++++++ .../notifications/PendingNotification.jsx | 1 + src/core/data/sidebarMenu.jsx | 2 +- src/core/utils/errorHandler.js | 6 +- src/core/utils/succesHandler.js | 2 +- src/layouts/AppLayout.jsx | 73 +++---------------- .../sidebar/SidebarListItem.jsx | 1 - src/lib/app/hooks/useNetwork.jsx | 58 +++++++++++++++ src/lib/app/hooks/useNotification.jsx | 7 +- src/lib/app/hooks/useRequest.jsx | 26 +++---- src/pages/dashboard/passenger-boss/index.jsx | 2 +- 14 files changed, 186 insertions(+), 158 deletions(-) create mode 100644 src/core/components/GlobalHead.jsx create mode 100644 src/core/components/NetworkComponent.jsx create mode 100644 src/lib/app/hooks/useNetwork.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 2caf47f..e78f16e 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -12,6 +12,8 @@ "lessThan": "کوچکتر از", "greaterThan": "بزرگتر از", "between": "میان", + "online_message": "شما به اینترنت وصل هستید", + "offline_message": "اتصال شما به اینترنت قطع شده است", "header": { "open_profile": "پروفایل", "edit_profile": " پروفایل", diff --git a/src/components/dashboard/edit-profile/index.jsx b/src/components/dashboard/edit-profile/index.jsx index d377123..3018aa3 100644 --- a/src/components/dashboard/edit-profile/index.jsx +++ b/src/components/dashboard/edit-profile/index.jsx @@ -16,7 +16,6 @@ import ImageResizer from "@/core/components/ImageConvertor"; const DashboardEditProfile = () => { const t = useTranslations(); const {user, token, getUser, changeUser} = useUser(); - console.log(user); const {directionApp} = useDirection(); const editAvatar = async (avatar) => { @@ -42,51 +41,7 @@ const DashboardEditProfile = () => { } }; const handleSubmit = (values, {setSubmitting}) => { - // const formData = new FormData(); - // formData.append("email", values.expert_email); - // if (values.change_avatar !== false) { - // editAvatar(values.expert_avatar) - // .then(() => { - // return axios.post(UPDATE_PROFILE, formData, { - // headers: { - // authorization: `Bearer ${token}`, - // "Content-Type": "multipart/form-data", - // }, - // }); - // }) - // .then((response) => { - // Notifications( t, response); - // getUser((data) => { - // changeUser(data); - // }); - // }) - // .catch((error) => { - // Notifications( t, error.response); - // }) - // .finally(() => { - // setSubmitting(false); - // }); - // } else { - // axios - // .post(UPDATE_PROFILE, formData, { - // headers: { - // authorization: `Bearer ${token}`, - // "Content-Type": "multipart/form-data", - // }, - // }) - // .then((response) => { - // Notifications( t, response); - // getUser((data) => { - // changeUser(data); - // }); - // }) - // .catch((error) => { - // Notifications( t, error.response); - // }) - // .finally(() => { - // setSubmitting(false); - // }); - // } + }; const initialValues = { expert_avatar: null, @@ -96,17 +51,7 @@ const DashboardEditProfile = () => { province_name: user.province_name, position: user.position, }; - const validationSchema = Yup.object().shape({ - // username: Yup.string().required(t("UpdateProfile.error_message_required")), - // name: Yup.string().required(t("UpdateProfile.error_message_required")), - // email: Yup.string() - // .email(t("UpdateProfile.error_invalid_email")) - // .required(t("UpdateProfile.error_message_required")), - // province_name: Yup.string().required( - // t("UpdateProfile.error_message_required") - // ), - // position: Yup.string().required(t("UpdateProfile.error_message_required")), - }); + const validationSchema = Yup.object().shape({}); return ( @@ -264,19 +209,6 @@ const DashboardEditProfile = () => { /> - {/* */} diff --git a/src/core/components/GlobalHead.jsx b/src/core/components/GlobalHead.jsx new file mode 100644 index 0000000..5d6186d --- /dev/null +++ b/src/core/components/GlobalHead.jsx @@ -0,0 +1,58 @@ +import Head from "next/head"; + +const GlobalHead = () => { + return ( + + + + + + + + + + + + + + + + + + + + + ) +} + +export default GlobalHead \ No newline at end of file diff --git a/src/core/components/NetworkComponent.jsx b/src/core/components/NetworkComponent.jsx new file mode 100644 index 0000000..8ebbb68 --- /dev/null +++ b/src/core/components/NetworkComponent.jsx @@ -0,0 +1,34 @@ +import useNetwork from "@/lib/app/hooks/useNetwork"; +import {useEffect, useRef} from "react"; +import {toast} from "react-toastify"; +import WifiIcon from '@mui/icons-material/Wifi'; +import WifiOffIcon from '@mui/icons-material/WifiOff'; +import {useTranslations} from "next-intl"; + +const NetworkComponent = () => { + const toastId = useRef(null); + const network = useNetwork() + const t = useTranslations() + + useEffect(() => { + if (network.online) { + toast.update(toastId.current, { + type: toast.TYPE.SUCCESS, + render: t('online_message'), + autoClose: 2000, + closeButton: true, + closeOnClick: true, + icon: + }); + return + } + toast.dismiss() + toastId.current = toast.warn(t('offline_message'), { + autoClose: false, closeButton: false, closeOnClick: false, icon: + }) + }, [network.online]); + + return '' +} + +export default NetworkComponent \ No newline at end of file diff --git a/src/core/components/notifications/PendingNotification.jsx b/src/core/components/notifications/PendingNotification.jsx index f3a0af4..846b847 100644 --- a/src/core/components/notifications/PendingNotification.jsx +++ b/src/core/components/notifications/PendingNotification.jsx @@ -3,6 +3,7 @@ import {toast} from "react-toastify"; const PendingNotification = (t) => { toast(t("notifications.pending"), { autoClose: false, + closeButton: false, closeOnClick: false, draggable: false, }); diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx index c1b7605..c2dc246 100644 --- a/src/core/data/sidebarMenu.jsx +++ b/src/core/data/sidebarMenu.jsx @@ -42,7 +42,7 @@ const sidebarMenu = [ { key: "sidebar.passenger-boss", secondary: "secondary.passenger-boss", - name: "province_manager_navgan", + name: "province_working_group", type: "page", route: "/dashboard/passenger-boss", icon: , diff --git a/src/core/utils/errorHandler.js b/src/core/utils/errorHandler.js index 6bee241..9bd18f1 100644 --- a/src/core/utils/errorHandler.js +++ b/src/core/utils/errorHandler.js @@ -3,15 +3,15 @@ import WarningNotification from "@/core/components/notifications/WarningNotifica import {toast} from "react-toastify"; export const errorSetting = (t, notification) => { - //todo + if (notification) toast.dismiss(); } export const errorRequest = (t, notification) => { - //todo + if (notification) toast.dismiss(); } export const errorResponse = (response, clearToken, t, notification) => { - toast.dismiss(); + if (notification) toast.dismiss(); if (isServerError(response.status)) { errorServer(response, t, notification) } else if (isClientError(response.status)) { diff --git a/src/core/utils/succesHandler.js b/src/core/utils/succesHandler.js index b698967..a61ac85 100644 --- a/src/core/utils/succesHandler.js +++ b/src/core/utils/succesHandler.js @@ -2,8 +2,8 @@ import SuccessNotification from "@/core/components/notifications/SuccessNotifica import {toast} from "react-toastify"; export const successRequest = (response, t, options) => { - toast.dismiss(); if (options.notification && options.success.notification.show) { + toast.dismiss(); SuccessNotification(t, response.status) } } \ No newline at end of file diff --git a/src/layouts/AppLayout.jsx b/src/layouts/AppLayout.jsx index 6d9bd96..4fc5e1d 100644 --- a/src/layouts/AppLayout.jsx +++ b/src/layouts/AppLayout.jsx @@ -2,12 +2,13 @@ import theme from "@/core/utils/theme"; import useLanguage from "@/lib/app/hooks/useLanguage"; import useLoading from "@/lib/app/hooks/useLoading"; import useUser from "@/lib/app/hooks/useUser"; -import Head from "next/head"; import NextNProgress from "nextjs-progressbar"; import {useEffect} from "react"; import {ToastContainer} from "react-toastify"; import useDirection from "@/lib/app/hooks/useDirection"; import "react-toastify/dist/ReactToastify.css"; +import NetworkComponent from "@/core/components/NetworkComponent"; +import GlobalHead from "@/core/components/GlobalHead"; function AppLayout({children, isBot}) { const {languageIsReady} = useLanguage(); @@ -40,66 +41,16 @@ function AppLayout({children, isBot}) { if (!languageIsReady) return; } - return ( - <> - - - - - - - - - - - - - - - - - - - - - - - {children} - - ); + return (<> + + + + + {children} + ); } export default AppLayout; diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx index 6eb1f55..ebeb14c 100644 --- a/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx +++ b/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx @@ -10,7 +10,6 @@ import useNotification from "@/lib/app/hooks/useNotification"; const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => { const t = useTranslations(); const {notification_count} = useNotification() - console.log(notification_count) return ( diff --git a/src/lib/app/hooks/useNetwork.jsx b/src/lib/app/hooks/useNetwork.jsx new file mode 100644 index 0000000..84e2950 --- /dev/null +++ b/src/lib/app/hooks/useNetwork.jsx @@ -0,0 +1,58 @@ +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 { + online: navigator.onLine, + }; + }); + useEffect(() => { + const handleOnline = () => { + setState((prevState) => ({ + ...prevState, + online: true, + })); + }; + const handleOffline = () => { + setState((prevState) => ({ + ...prevState, + online: false, + })); + }; + + window.addEventListener("online", handleOnline); + window.addEventListener("offline", handleOffline); + return () => { + window.removeEventListener("online", handleOnline); + window.removeEventListener("offline", handleOffline); + }; + }, []); + + return state; +} + +export default useNetwork; \ No newline at end of file diff --git a/src/lib/app/hooks/useNotification.jsx b/src/lib/app/hooks/useNotification.jsx index 726d4c0..e32f829 100644 --- a/src/lib/app/hooks/useNotification.jsx +++ b/src/lib/app/hooks/useNotification.jsx @@ -3,14 +3,11 @@ import {GET_SIDEBAR_NOTIFICATION} from "@/core/data/apiRoutes"; import useRequest from "@/lib/app/hooks/useRequest"; const useNotification = () => { - const requestServer = useRequest({auth: true}) + const requestServer = useRequest({auth: true, notification: false}) //swr config const fetcher = (...args) => { - return requestServer(args, 'get', { - pending: false, - success: {notification: {show: false}} - }).then((response) => { + return requestServer(args, 'get').then((response) => { return response.data.data; }).catch(() => { }) diff --git a/src/lib/app/hooks/useRequest.jsx b/src/lib/app/hooks/useRequest.jsx index 5c567ca..d361e08 100644 --- a/src/lib/app/hooks/useRequest.jsx +++ b/src/lib/app/hooks/useRequest.jsx @@ -4,27 +4,23 @@ import PendingNotification from "@/core/components/notifications/PendingNotifica import {useTranslations} from "next-intl"; import useUser from "@/lib/app/hooks/useUser"; import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler"; +import useNetwork from "@/lib/app/hooks/useNetwork"; const defaultOptions = { - auth: false, - data: {}, - requestOptions: { + auth: false, data: {}, requestOptions: { headers: {} - }, - notification: true, - pending: true, - success: { + }, notification: true, pending: true, success: { notification: { show: true, }, - }, - failed: { + }, failed: { notification: { show: true, }, }, } const useRequest = (initOptions) => { + const network = useNetwork() const t = useTranslations() const {token, clearToken} = useUser() let _options = {...defaultOptions, ...initOptions} @@ -32,20 +28,20 @@ const useRequest = (initOptions) => { function requestServer(url = '', method = 'get', options) { _options = {..._options, ...options} if (_options.auth) _options = { - ..._options, - requestOptions: { + ..._options, requestOptions: { ..._options.requestOptions, headers: {..._options.requestOptions.headers, authorization: `Bearer ${token}`} } } return new Promise((resolve, reject) => { + if (!network.online) { + reject() + return + } if (_options.notification && _options.failed.notification.show && _options.pending) PendingNotification(t) axios({ - url: url, - method: method, - data: _options.data, - ..._options.requestOptions + url: url, method: method, data: _options.data, ..._options.requestOptions }) .then(response => { successRequest(response, t, _options) diff --git a/src/pages/dashboard/passenger-boss/index.jsx b/src/pages/dashboard/passenger-boss/index.jsx index 75b7234..839488e 100644 --- a/src/pages/dashboard/passenger-boss/index.jsx +++ b/src/pages/dashboard/passenger-boss/index.jsx @@ -3,7 +3,7 @@ import RolePermissionMiddleware from "@/middlewares/RolePermission"; import WithAuthMiddleware from "@/middlewares/WithAuth"; import {parse} from "next-useragent"; -const requiredPermissions = ["manage_working_group_navgan"]; +const requiredPermissions = ["manage_province_working_group_navgan"]; export default function PassengerBoss() { return (