From 3be0d04f282fcf05042559f4fe20fab2790b796a Mon Sep 17 00:00:00 2001 From: adam-skowronek Date: Wed, 11 Jan 2023 23:27:02 +0100 Subject: [PATCH] Add basic error handling --- frontend/src/App.tsx | 102 ++++++++++++++----------- frontend/src/assets/svg/icon-error.svg | 1 + frontend/src/components/BaseModal.tsx | 72 +++++++++++++++++ frontend/src/context/MainContext.tsx | 8 ++ frontend/src/context/WithAxios.tsx | 29 +++++++ 5 files changed, 166 insertions(+), 46 deletions(-) create mode 100644 frontend/src/assets/svg/icon-error.svg create mode 100644 frontend/src/components/BaseModal.tsx create mode 100644 frontend/src/context/MainContext.tsx create mode 100644 frontend/src/context/WithAxios.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index df90597..9df700a 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState } from 'react' import { QueryClient, QueryClientProvider } from 'react-query' import { Navigate, Route, Routes } from 'react-router-dom' import './App.css' @@ -28,6 +28,9 @@ import GradeCard from './views/GradeCard' import Group from './views/coordinator/Group' import dayjs from 'dayjs' import WorkloadStatistics from './views/coordinator/WorkloadStatistics' +import { MainContext } from './context/MainContext' +import WithAxios from './context/WithAxios' +import BaseModal from './components/BaseModal' require('dayjs/locale/pl') dayjs.locale('pl') @@ -41,53 +44,60 @@ const queryClient = new QueryClient({ }) function App() { + const [isModalOpen, setIsModalOpen] = useState(false) + return (
- - - } /> - }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } - /> - } /> - } - /> - } - /> - - }> - } /> - } /> - } /> - } /> - - }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - + + + + + } /> + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } + /> + } /> + } + /> + } + /> + + }> + } /> + } /> + } /> + } /> + + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + + +
) } diff --git a/frontend/src/assets/svg/icon-error.svg b/frontend/src/assets/svg/icon-error.svg new file mode 100644 index 0000000..0ddb22d --- /dev/null +++ b/frontend/src/assets/svg/icon-error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/components/BaseModal.tsx b/frontend/src/components/BaseModal.tsx new file mode 100644 index 0000000..fd1a7ac --- /dev/null +++ b/frontend/src/components/BaseModal.tsx @@ -0,0 +1,72 @@ +import { ReactElement, useContext } from 'react' +import Modal from 'react-modal' +import { MainContext } from '../context/MainContext' +import { ReactComponent as IconRemove } from '../assets/svg/icon-remove.svg' +import { ReactComponent as IconError } from '../assets/svg/icon-error.svg' + +export interface ModalData { + title: string + message: string + icon?: ReactElement +} + +export interface BaseModalProps { + isOpen: boolean + modalData?: ModalData | null +} + +const customStyles = { + overlay: { + backgroundColor: 'rgba(125,125,125, 0.55)', + zIndex: 100, + }, + content: { + top: '50%', + left: '50%', + right: 'auto', + bottom: 'auto', + marginRight: '-50%', + transform: 'translate(-50%, -50%)', + padding: '15px', + width: '460px', + height: '250px', + borderRadius: '25px', + backgroundColor: '#f7f7f7', + }, +} + +const BaseModal = ({ isOpen, modalData }: BaseModalProps) => { + Modal.setAppElement('#root') + const { setIsModalOpen } = useContext(MainContext) + const { icon, message, title } = modalData ?? {} + return ( + <> + setIsModalOpen(false)} + > +
+ +
+ + +

+ Przepraszamy, wystąpił błąd.
Spróbuj ponownie. +

+
+
+
+ + ) +} + +export default BaseModal diff --git a/frontend/src/context/MainContext.tsx b/frontend/src/context/MainContext.tsx new file mode 100644 index 0000000..ad334df --- /dev/null +++ b/frontend/src/context/MainContext.tsx @@ -0,0 +1,8 @@ +import React, { Dispatch, SetStateAction } from 'react' + +type ContextProps = { + isModalOpen: boolean + setIsModalOpen: Dispatch> +} + +export const MainContext = React.createContext({} as ContextProps) diff --git a/frontend/src/context/WithAxios.tsx b/frontend/src/context/WithAxios.tsx new file mode 100644 index 0000000..26b10d7 --- /dev/null +++ b/frontend/src/context/WithAxios.tsx @@ -0,0 +1,29 @@ +import { FunctionComponent, useContext, useMemo } from 'react' +import axiosInstance from '../api/axiosInstance' +import { MainContext } from './MainContext' + +const WithAxios: FunctionComponent<{ children: React.ReactNode }> = ({ + children, +}) => { + const { setIsModalOpen } = useContext(MainContext) + useMemo(() => { + axiosInstance.interceptors.request.use(async (request) => { + return request + }) + axiosInstance.interceptors.response.use( + (response) => { + return response + }, + (error) => { + setIsModalOpen(false) + if (error.response?.status) { + setIsModalOpen(true) + } + return Promise.reject(error) + }, + ) + }, [setIsModalOpen]) + return <>{children} +} + +export default WithAxios