From 8833120e319fb67e2ba95b9802867ce803f288c0 Mon Sep 17 00:00:00 2001 From: AminGhasempoor Date: Sun, 5 Nov 2023 14:37:22 +0330 Subject: [PATCH] LFFE-12 add toast and correct the user and language bsaed on it --- src/core/components/DataTable.jsx | 16 +++++---- src/core/utils/errorHandler.js | 59 ++++++++++++++++--------------- src/core/utils/succesHandler.js | 9 +++-- src/lib/app/contexts/language.jsx | 8 ++--- src/lib/app/contexts/user.jsx | 9 +---- src/lib/app/hooks/useRequest.jsx | 19 ++++++---- src/pages/_app.jsx | 13 ++++--- 7 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/core/components/DataTable.jsx b/src/core/components/DataTable.jsx index 70cee09..8e3fe63 100644 --- a/src/core/components/DataTable.jsx +++ b/src/core/components/DataTable.jsx @@ -14,7 +14,6 @@ function DataTable(props) { const [columnFilters, setColumnFilters] = useState([]); const [sorting, setSorting] = useState(props.sorting || []); const [pagination, setPagination] = useState({pageIndex: 0, pageSize: 10}); - const [rowCount, setRowCount] = useState(0); const [columnFilterFns, setColumnFilterFns] = useState(() => { let output = {}; const list = props.columns.map((item) => item.enableColumnFilter ? {[item.id]: item.filterFn} : {[item.id]: ""}); @@ -34,8 +33,11 @@ function DataTable(props) { const tableLocalization = useMemo(() => languageList.find((item) => item.key == languageApp).tableLocalization, [languageApp, languageList]); const fetchUrl = useMemo(() => { - const url = new URL(props.tableUrl); - url.searchParams.set("start", `${pagination.pageIndex * pagination.pageSize}`); + const params = new URLSearchParams(); + params.set( + "start", + `${pagination.pageIndex * pagination.pageSize}` + ); const filters = columnFilters.map((filter) => { let datatype; for (const i in props.columns) { @@ -47,10 +49,10 @@ function DataTable(props) { ...filter, fn: columnFilterFns[filter.id], datatype: datatype, }; }); - url.searchParams.set("size", pagination.pageSize); - url.searchParams.set("filters", JSON.stringify(filters ?? [])); - url.searchParams.set("sorting", JSON.stringify(sorting ?? [])); - return url; + params.set("size", pagination.pageSize); + params.set("filters", JSON.stringify(filters ?? [])); + params.set("sorting", JSON.stringify(sorting ?? [])); + return `${props.tableUrl}?${params}`; }, [props.tableUrl, columnFilters, columnFilterFns, pagination, sorting, props.columns,]); const {data, isValidating, mutate} = useSWR(fetchUrl, (...args) => diff --git a/src/core/utils/errorHandler.js b/src/core/utils/errorHandler.js index 8dbd364..e380e84 100644 --- a/src/core/utils/errorHandler.js +++ b/src/core/utils/errorHandler.js @@ -1,45 +1,48 @@ -import ErrorNotification from "@/core/components/notifications/ErrorNotification"; -import WarningNotification from "@/core/components/notifications/WarningNotification"; -import {toast} from "react-toastify"; +import Notifications from "@/core/components/notifications"; -export const errorSetting = (t, notification) => { - if (notification) toast.dismiss(); +export const errorSetting = (dismissToastList, t, notification) => { + if (notification) { + dismissToastList(["pending", "warning", "error", "success"]) + } } - -export const errorRequest = (t, notification) => { - if (notification) toast.dismiss(); -} - -export const errorResponse = (response, clearToken, t, notification) => { - if (notification) toast.dismiss(); - if (isServerError(response.status)) { - errorServer(response, t, notification) - } else if (isClientError(response.status)) { - errorClient(response, clearToken, t, notification) +export const errorRequest = (dismissToastList, t, notification) => { + if (notification) { + dismissToastList(["pending", "warning", "error", "success"]) } } -const errorServer = (response, t, notification) => { - if (notification) WarningNotification(t, response.status); +export const errorResponse = (pushToastList, dismissToastList, response, clearToken, t, notification) => { + if (notification) { + dismissToastList(["pending", "warning", "error", "success"]) + } + if (isServerError(response.status)) { + errorServer(pushToastList, response, t, notification) + } else if (isClientError(response.status)) { + errorClient(pushToastList, response, clearToken, t, notification) + } } -const errorClient = (response, clearToken, t, notification) => { + +const errorServer = (pushToastList, response, t, notification) => { + if (notification) Notifications(pushToastList, "warning", t, response.status); +} +const errorClient = (pushToastList, response, clearToken, t, notification) => { switch (response.status) { case 401: clearToken() - if (notification) ErrorNotification(t, response.status) + if (notification) Notifications(pushToastList, "error", t, response.status); break; case 422: if ('type' in response.data) { - errorLogic(response, t, notification) + errorLogic(pushToastList, response, t, notification) break; } - errorValidation(response, t, notification) + errorValidation(pushToastList, response, t, notification) break; case 429: - if (notification) ErrorNotification(t, response.status) + if (notification) Notifications(pushToastList, "error", t, response.status); break default: - if (notification) ErrorNotification(t, response.status) + if (notification) Notifications(pushToastList, "error", t, response.status); break } } @@ -47,16 +50,16 @@ const errorClient = (response, clearToken, t, notification) => { 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, response.data.message) +const errorLogic = (pushToastList, response, t, notification) => { + if (notification) Notifications(pushToastList, "error", t, response.status, response.data.message); } -const errorValidation = (response, t, notification) => { +const errorValidation = (pushToastList, response, t, notification) => { if (notification) { const errorsMap = Object.keys(response.data.errors) const errorsArray = response.data.errors errorsMap.map((item, index) => { - ErrorNotification(t, response.status, errorsArray[item][0]); + Notifications(pushToastList, "error", t, response.status, errorsArray[item][0]); }) } } \ No newline at end of file diff --git a/src/core/utils/succesHandler.js b/src/core/utils/succesHandler.js index a61ac85..c852f86 100644 --- a/src/core/utils/succesHandler.js +++ b/src/core/utils/succesHandler.js @@ -1,9 +1,8 @@ -import SuccessNotification from "@/core/components/notifications/SuccessNotification"; -import {toast} from "react-toastify"; +import Notifications from "@/core/components/notifications"; -export const successRequest = (response, t, options) => { +export const successRequest = (pushToastList, dismissToastList, response, t, options) => { if (options.notification && options.success.notification.show) { - toast.dismiss(); - SuccessNotification(t, response.status) + dismissToastList(["pending", "warning", "error", "success"]) + Notifications(pushToastList, "success", t, response.status); } } \ No newline at end of file diff --git a/src/lib/app/contexts/language.jsx b/src/lib/app/contexts/language.jsx index a6df674..03e3bc3 100644 --- a/src/lib/app/contexts/language.jsx +++ b/src/lib/app/contexts/language.jsx @@ -1,8 +1,8 @@ import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable"; -import {FA_CHART_LOCALIZATION} from "&/locales/fa/chart"; import {useRouter} from "next/router"; import {createContext, useEffect, useState} from "react"; import useUser from "../hooks/useUser"; +import {FA_CHART_LOCALIZATION} from "&/locales/fa/chart"; export const LanguageContext = createContext(); @@ -20,7 +20,7 @@ export const LanguageProvider = ({children}) => { ]; const {user, userChangedLanguage, changeLanguageState} = useUser(); const [languageIsReady, setLanguageIsReady] = useState(false); - const [languageApp, setLanguageApp] = useState(); + const [languageApp, setLanguageApp] = useState(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE); const [directionApp, setDirectionApp] = useState( process.env.NEXT_PUBLIC_DEFAULT_DIRECTION ); @@ -28,9 +28,7 @@ export const LanguageProvider = ({children}) => { useEffect(() => { const lang = localStorage.getItem("_language"); - if (!lang && !languageApp) { - setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE); - } else if (lang) { + if (lang) { setLanguageApp(lang); } }, []); diff --git a/src/lib/app/contexts/user.jsx b/src/lib/app/contexts/user.jsx index 10611b8..7f5c97c 100644 --- a/src/lib/app/contexts/user.jsx +++ b/src/lib/app/contexts/user.jsx @@ -1,7 +1,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"; const initialUser = { isAuth: false, @@ -78,13 +77,7 @@ export const UserProvider = ({children}) => { if (typeof callback === "function") callback(data); }) .catch(error => { - if (error.response) { - errorResponse(error.response, clearToken, null, false) - } else if (error.request) { - errorRequest(null, false) - } else { - errorSetting(null, false) - } + if (error.response.status === 401) clearToken() }) }, [state.token] diff --git a/src/lib/app/hooks/useRequest.jsx b/src/lib/app/hooks/useRequest.jsx index d361e08..4c3be1d 100644 --- a/src/lib/app/hooks/useRequest.jsx +++ b/src/lib/app/hooks/useRequest.jsx @@ -1,10 +1,11 @@ import axios from "axios"; import {successRequest} from "@/core/utils/succesHandler"; -import PendingNotification from "@/core/components/notifications/PendingNotification"; 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"; +import Notifications from "@/core/components/notifications"; +import useToast from "@/lib/app/hooks/useToast"; const defaultOptions = { auth: false, data: {}, requestOptions: { @@ -23,6 +24,7 @@ const useRequest = (initOptions) => { const network = useNetwork() const t = useTranslations() const {token, clearToken} = useUser() + const {pushToastList, dismissToastList} = useToast(); let _options = {...defaultOptions, ...initOptions} function requestServer(url = '', method = 'get', options) { @@ -33,27 +35,30 @@ const useRequest = (initOptions) => { 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) + if (_options.notification && _options.failed.notification.show && _options.pending) { + dismissToastList(["pending", "warning", "error", "success"]); + Notifications(pushToastList, "pending", t); + } + axios({ url: url, method: method, data: _options.data, ..._options.requestOptions }) .then(response => { - successRequest(response, t, _options) + successRequest(pushToastList, dismissToastList, response, t, _options) resolve(response) }) .catch(error => { if (error.response) { - errorResponse(error.response, clearToken, t, _options.notification && _options.failed.notification.show) + errorResponse(pushToastList, dismissToastList, error.response, clearToken, t, _options.notification && _options.failed.notification.show) } else if (error.request) { - errorRequest(t, _options.notification && _options.failed.notification.show) + errorRequest(dismissToastList, t, _options.notification && _options.failed.notification.show) } else { - errorSetting(t, _options.notification && _options.failed.notification.show) + errorSetting(dismissToastList, t, _options.notification && _options.failed.notification.show) } reject(error) }) diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index d7c2169..8d2f3b0 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -8,6 +8,7 @@ import "moment/locale/fa"; import {NextIntlProvider} from "next-intl"; import TitlePage from "@/core/components/TitlePage"; import Layout from "@/layouts"; +import {ToastProvider} from "@/lib/app/contexts/toast"; const App = ({Component, pageProps}) => { @@ -19,11 +20,13 @@ const App = ({Component, pageProps}) => { {pageProps.messages ? : ''} - - - - - + + + + + + +