From a8f6f75d28905df05f0c48d81f950c433bb132e5 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 25 Jan 2024 20:38:59 +0100 Subject: [PATCH] fetch error message handling --- README.md | 1 + public/locales/de/translation.json | 22 +- public/locales/en/translation.json | 22 +- src/App.js | 5 +- src/Components/AppRoutes/index.js | 9 +- src/Components/Header/index.js | 167 +--- src/Components/MyFormInputs/index.js | 6 +- src/Components/MyIcon/index.js | 6 +- src/Pages/Login/index.js | 50 +- src/Pages/Store/Calendar/Auth/index.js | 67 +- src/Pages/Store/Calendar/index.js | 90 +- src/Pages/Store/Employees/index.js | 46 +- src/Pages/Store/Services/index.js | 795 ++++++++-------- src/Pages/Store/Settings/index.js | 29 +- src/Pages/Store/Website/index.js | 36 +- src/Pages/UserProfile/index.js | 33 +- src/index.css | 1 + src/utils.js | 1149 +----------------------- 18 files changed, 766 insertions(+), 1768 deletions(-) diff --git a/README.md b/README.md index e69de29..5892d5f 100644 --- a/README.md +++ b/README.md @@ -0,0 +1 @@ +# Zeit Adler Dashboard diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index 751392a..eb7fa50 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -54,6 +54,20 @@ "passwordMinLength": "Passwort muss mindestens {{minLength}} Zeichen lang sein", "calendarMaxFutureBookingDaysRequired": "Maximaler Buchungszeitraum ist erforderlich", "calendarMinEarliestBookingTimeRequired": "Minimaler frühester Buchungszeitpunkt ist erforderlich" + }, + "request": { + "inputsInvalid": { + "title": "Eingaben ungültig", + "description": "Bitte überprüfen Sie Ihre Eingaben." + }, + "failed": { + "title": "Ein Fehler ist aufgetreten", + "description": "Bitte versuchen Sie es erneut." + }, + "failedInternetProblem": { + "title": "Anfrage fehlgeschlagen", + "description": "Bitte überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut." + } } }, "pageNotFound": { @@ -98,7 +112,13 @@ }, "login": { "login": "Anmelden", - "signUp": "Registrieren" + "signUp": "Registrieren", + "request": { + "400": { + "title": "Anmeldung fehlgeschlagen", + "description": "Bitte überprüfen Sie Ihre Eingaben." + } + } }, "storeServices": { "pageTitle": "Dienstleistungen", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 88c5c9b..3cf0136 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -54,6 +54,20 @@ "passwordMinLength": "Password must be at least {{minLength}} characters", "calendarMaxFutureBookingDaysRequired": "Please enter the max. future booking days", "calendarMinEarliestBookingTimeRequired": "Please enter the min. earliest booking time" + }, + "request": { + "inputsInvalid": { + "title": "Invalid inputs", + "description": "Please check your inputs and try again." + }, + "failed": { + "title": "An error has occurred", + "description": "The request failed. Please try again." + }, + "failedInternetProblem": { + "title": "Request failed", + "description": "The request failed. Please check your internet connection and try again." + } } }, "pageNotFound": { @@ -98,7 +112,13 @@ }, "login": { "login": "Login", - "signUp": "Sign up" + "signUp": "Sign up", + "request": { + "400": { + "title": "Login failed", + "description": "Please check your inputs and try again." + } + } }, "services": { "pageTitle": "Services" diff --git a/src/App.js b/src/App.js index c0c74a0..dce815d 100644 --- a/src/App.js +++ b/src/App.js @@ -24,7 +24,10 @@ export default function App() { useEffect(() => { if (!userSession) return; - myFetch("/user", "GET") + myFetch({ + url: "/user", + method: "GET", + }) .then((data) => { setAppUserData(data); }) diff --git a/src/Components/AppRoutes/index.js b/src/Components/AppRoutes/index.js index 882cace..fdf20cb 100644 --- a/src/Components/AppRoutes/index.js +++ b/src/Components/AppRoutes/index.js @@ -17,9 +17,7 @@ const StoreWebsite = lazy(() => import("../../Pages/Store/Website")); //const Feedback = lazy(() => import("../../Pages/Feedback")); const UserProfile = lazy(() => import("../../Pages/UserProfile")); -export default function AppRoutes({ userSession, setUserSession }) { - //const appContext = useAppContext(); - +export default function AppRoutes({ setUserSession }) { return ( - + } /> diff --git a/src/Components/Header/index.js b/src/Components/Header/index.js index 8874078..d57563b 100644 --- a/src/Components/Header/index.js +++ b/src/Components/Header/index.js @@ -1,65 +1,11 @@ -import { - BellOutlined, - CheckCircleOutlined, - CloseCircleOutlined, - CloseOutlined, - DeleteOutlined, - ExclamationCircleOutlined, - InboxOutlined, - InfoCircleOutlined, - MenuFoldOutlined, - MenuUnfoldOutlined, - QuestionCircleOutlined, -} from "@ant-design/icons"; -import { Badge, Button, Drawer, List, Popconfirm, Typography } from "antd"; +import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons"; +import { Button } from "antd"; import { Header } from "antd/es/layout/layout"; -import { useEffect, useState } from "react"; -import { useHeaderContext } from "../../Contexts/HeaderContext"; -import { myFetch } from "../../utils"; -import { useWebSocketContext } from "../../Contexts/WebSocketContext"; -import { SentMessagesCommands } from "../../Handlers/WebSocketMessageHandler"; -import { useTranslation } from "react-i18next"; -import LiveTimeAgo from "../LiveTimeAgo"; -import MyPagination from "../MyPagination"; export default function HeaderMenu({ isSideMenuCollapsed, setIsSideMenuCollapsed, }) { - //const webSocketContext = useWebSocketContext(); - //const headerContext = useHeaderContext(); - //const { t } = useTranslation(); - const [isNotificationDrawerOpen, setIsNotificationDrawerOpen] = - useState(false); - - /* - const fetchNotifications = (page = 1) => { - myFetch(`/notifications?page=${page}`, "GET").then((data) => - headerContext.setNotificationResponse(data) - ); - }; - - const onPaginationChange = (page) => { - headerContext.setPaginationPage(page); - headerContext.paginationPageRef.current = page; - }; */ - - /* - useEffect(() => { - // fetch will only be called if the drawer is open and there are no notifications - // further notifications will be fetched by the websocket - if (!isNotificationDrawerOpen || headerContext.notficationResponse !== null) - return; - - fetchNotifications(1); - }, [isNotificationDrawerOpen]); - - useEffect(() => { - if (!isNotificationDrawerOpen) return; - - fetchNotifications(headerContext.paginationPage); - }, [headerContext.paginationPage]); */ - return (
); } - -/* - - - ) - } - > - {isNotificationDrawerOpen && ( - <> - {headerContext.totalNotifications === 0 || - headerContext.notficationResponse === null ? ( -
- - - {t("header.notificationDrawer.noNotifications")} - -
- ) : ( - { - return new Date(b.CreatedAt) - new Date(a.CreatedAt); - } - )} - footer={ - onPaginationChange(page)} - totalPages={headerContext.notficationResponse.TotalPages} - size="small" - /> - } - renderItem={(item) => ( - - } - title={item.Title} - description={} - /> - - { - /*webSocketContext.SendSocketMessage( - SentMessagesCommands.DeleteOneNotification, - { - notificationId: item.Id, - } - ) - - }} - /> - - )} - /> - )} - - )} - -*/ - -function NotificationTypeIcon({ type }) { - switch (type) { - case 1: - return ; - case 2: - return ; - case 3: - return ( - - ); - case 4: - return ; - default: - return ; - } -} diff --git a/src/Components/MyFormInputs/index.js b/src/Components/MyFormInputs/index.js index 4e9bde9..a281f1a 100644 --- a/src/Components/MyFormInputs/index.js +++ b/src/Components/MyFormInputs/index.js @@ -187,7 +187,11 @@ export function MyAvailableCheckFormInput({ body[fetchParameter] = value; // like accountName: value - myFetch(fetchUrl, "POST", body) + myFetch({ + url: fetchUrl, + method: "POST", + body: body, + }) .then(() => { resolve(); }) diff --git a/src/Components/MyIcon/index.js b/src/Components/MyIcon/index.js index b409a24..05a39d9 100644 --- a/src/Components/MyIcon/index.js +++ b/src/Components/MyIcon/index.js @@ -4,7 +4,7 @@ import { PlusOutlined, QuestionCircleOutlined, } from "@ant-design/icons"; -import { Popconfirm, Tooltip } from "antd"; +import { Popconfirm } from "antd"; import { useState } from "react"; import { useTranslation } from "react-i18next"; @@ -79,14 +79,14 @@ export function MyPlusIcon({ onClick }) { export function MyIcon({ popconfirmDisabled, propsPopconfirm, - propsTooltip, + // propsTooltip, onConfirm, onFetchSuccess, onCancel, popConfirmTitle, popConfirmDescription, popConfirmOkText, - tooltipTitle, + //tooltipTitle, icon, }) { const { t } = useTranslation(); diff --git a/src/Pages/Login/index.js b/src/Pages/Login/index.js index 35aa8f9..3e2ef03 100644 --- a/src/Pages/Login/index.js +++ b/src/Pages/Login/index.js @@ -3,8 +3,8 @@ import { Button, Form, Modal, Tabs, notification } from "antd"; import { EncodeStringToBase64, myFetch, - myFetchContentType, setUserSessionToLocalStorage, + showInputsInvalidNotification, } from "../../utils"; import { useState } from "react"; import { @@ -19,31 +19,27 @@ export default function Login() { const { t } = useTranslation(); const [form] = Form.useForm(); - const [api, contextHolder] = notification.useNotification(); + const [notificationApi, notificationContextHolder] = + notification.useNotification(); const [selectedMethod, setSelectedMethod] = useState("1"); const [isRequesting, setIsRequesting] = useState(false); const showErrorNotification = (errStatus) => { - if (errStatus === 401) { - api["error"]({ - message: "Account deactivated", - description: "Please contact an administrator", + if (errStatus === 400) { + notificationApi["error"]({ + message: t("login.request.400.title"), + description: t("login.request.400.description"), }); - return; } - - api["error"]({ - message: "Login failed", - description: "Please check your accountName and password!", - }); }; return ( <> - {contextHolder} + {notificationContextHolder} { - console.log(data.XAuthorization); - setUserSessionToLocalStorage(data.XAuthorization); window.location.href = "/"; }) @@ -88,9 +82,7 @@ export default function Login() { setIsRequesting(false); }); }) - .catch((info) => { - console.log("Validate Failed:", info); - }); + .catch(() => showInputsInvalidNotification(notificationApi, t)); }} > {selectedMethod === "1" ? t("login.login") : t("login.signUp")} @@ -119,9 +111,7 @@ export default function Login() { }, ]} centered - onChange={(activeKey) => { - setSelectedMethod(activeKey); - }} + onChange={(activeKey) => setSelectedMethod(activeKey)} />
diff --git a/src/Pages/Store/Calendar/Auth/index.js b/src/Pages/Store/Calendar/Auth/index.js index fda5280..ead9499 100644 --- a/src/Pages/Store/Calendar/Auth/index.js +++ b/src/Pages/Store/Calendar/Auth/index.js @@ -1,20 +1,27 @@ -import { Button, Result, Spin } from "antd"; +import { Button, Result, Spin, notification } from "antd"; import { Link, useParams, useNavigate } from "react-router-dom"; import { Constants, myFetch } from "../../../../utils"; import { useEffect, useState } from "react"; import MyCenteredContainer from "../../../../Components/MyContainer"; import { useTranslation } from "react-i18next"; -import { MySupsenseFallback } from "../../../../Components/MySupsenseFallback"; export default function StoreCalendarAuth() { const { t } = useTranslation(); + const [notificationApi, notificationContextHolder] = + notification.useNotification(); + const { status } = useParams(); const [isRequesting, setIsRequesting] = useState(true); const [storeId, setStoreId] = useState(""); useEffect(() => { - myFetch("/calendar/store", "GET") + myFetch({ + url: "/calendar/store", + method: "GET", + notificationApi: notificationApi, + t: t, + }) .then((res) => { setIsRequesting(false); setStoreId(res.storeId); @@ -33,32 +40,36 @@ export default function StoreCalendarAuth() { } return ( - - - - + <> + {notificationContextHolder} - {status === "finish" && } - , - ]} - /> + + + + + + {status === "finish" && } + , + ]} + /> + ); } diff --git a/src/Pages/Store/Calendar/index.js b/src/Pages/Store/Calendar/index.js index a4fbe7f..e6ec25c 100644 --- a/src/Pages/Store/Calendar/index.js +++ b/src/Pages/Store/Calendar/index.js @@ -10,6 +10,7 @@ import { Spin, Switch, Typography, + notification, } from "antd"; import { useTranslation } from "react-i18next"; import { @@ -38,6 +39,9 @@ const { useBreakpoint } = Grid; export default function StoreCalendar() { const { t } = useTranslation(); + const [notificationApi, notificationContextHolder] = + notification.useNotification(); + const { storeId } = useParams(); const [calendarSettings, setCalendarSettings] = useState({}); @@ -47,7 +51,12 @@ export default function StoreCalendar() { // delete session cookie document.cookie = `session=; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT;`; - myFetch("/calendar/settings", "GET") + myFetch({ + url: "/calendar/settings", + method: "GET", + notificationApi: notificationApi, + t: t, + }) .then((res) => { setIsRequesting(false); setCalendarSettings(res); @@ -67,6 +76,8 @@ export default function StoreCalendar() { return ( <> + {notificationContextHolder} + {calendarSettings.connected === false ? ( )}