Add basic error handling

This commit is contained in:
adam-skowronek 2023-01-11 23:27:02 +01:00
parent 6be66634f3
commit 3be0d04f28
5 changed files with 166 additions and 46 deletions

View File

@ -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,8 +44,12 @@ const queryClient = new QueryClient({
})
function App() {
const [isModalOpen, setIsModalOpen] = useState(false)
return (
<div>
<MainContext.Provider value={{ isModalOpen, setIsModalOpen }}>
<WithAxios>
<QueryClientProvider client={queryClient}>
<Routes>
<Route index element={<Login />} />
@ -88,6 +95,9 @@ function App() {
</Route>
</Routes>
</QueryClientProvider>
<BaseModal isOpen={isModalOpen} />
</WithAxios>
</MainContext.Provider>
</div>
)
}

View File

@ -0,0 +1 @@
<svg height="16" width="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.866 0-7 3.13401-7 7s3.134 7 7 7 7-3.13401 7-7-3.134-7-7-7zm-1 2h2v4l-.5 3h-1l-.5-3zm1 8a1 1 0 0 1 0 2 1 1 0 0 1 0-2z" fill="#ef2929"/></svg>

After

Width:  |  Height:  |  Size: 240 B

View File

@ -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 (
<>
<Modal
isOpen={isOpen}
style={customStyles}
contentLabel="Info modal"
onRequestClose={() => setIsModalOpen(false)}
>
<div className="flex flex-col p-2">
<button
className="self-end"
onClick={() => {
if (setIsModalOpen) setIsModalOpen(false)
}}
>
<IconRemove />
</button>
<div className="flex justify-center align-center items-center mt-8 flex-col">
<IconError style={{ transform: 'scale(2)' }} />
<h2 className="font-bold text-xl text-center mt-5">
Przepraszamy, wystąpił błąd. <br /> Spróbuj ponownie.
</h2>
</div>
</div>
</Modal>
</>
)
}
export default BaseModal

View File

@ -0,0 +1,8 @@
import React, { Dispatch, SetStateAction } from 'react'
type ContextProps = {
isModalOpen: boolean
setIsModalOpen: Dispatch<SetStateAction<boolean>>
}
export const MainContext = React.createContext<ContextProps>({} as ContextProps)

View File

@ -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