mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-01-09 09:24:30 +01:00
feat: new error boundary component
This commit is contained in:
24
package-lock.json
generated
24
package-lock.json
generated
@@ -71,6 +71,7 @@
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-datepicker": "^4.7.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-error-boundary": "^3.1.4",
|
||||
"react-file-drop": "^3.1.4",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "^7.30.0",
|
||||
@@ -62242,6 +62243,21 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-error-boundary": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz",
|
||||
"integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"npm": ">=6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-error-overlay": {
|
||||
"version": "6.0.11",
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
|
||||
@@ -118430,6 +118446,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-error-boundary": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz",
|
||||
"integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5"
|
||||
}
|
||||
},
|
||||
"react-error-overlay": {
|
||||
"version": "6.0.11",
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-datepicker": "^4.7.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-error-boundary": "^3.1.4",
|
||||
"react-file-drop": "^3.1.4",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "^7.30.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { Component, ErrorInfo, ReactNode } from "react";
|
||||
import ErrorMessage from "../ErrorMessage/ErrorMessage";
|
||||
import ErrorMessage from "../Errors/ErrorMessage/ErrorMessage";
|
||||
|
||||
interface Props {
|
||||
place?: string
|
||||
|
||||
21
src/Components/Errors/ErrorCard/ErrorCard.stories.tsx
Normal file
21
src/Components/Errors/ErrorCard/ErrorCard.stories.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
|
||||
import ErrorCard from './ErrorCard';
|
||||
|
||||
export default {
|
||||
title: 'Shared/ErrorCard',
|
||||
component: ErrorCard,
|
||||
|
||||
} as ComponentMeta<typeof ErrorCard>;
|
||||
|
||||
const Template: ComponentStory<typeof ErrorCard> = (args) => <ErrorCard {...args} />;
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
error: {
|
||||
name: "Error Name",
|
||||
message: "Error Message",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
40
src/Components/Errors/ErrorCard/ErrorCard.tsx
Normal file
40
src/Components/Errors/ErrorCard/ErrorCard.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { useToggle } from "@react-hookz/web";
|
||||
import { FallbackProps } from "react-error-boundary";
|
||||
import { RiErrorWarningFill } from "react-icons/ri";
|
||||
import Button from "src/Components/Button/Button";
|
||||
import Card from "src/Components/Card/Card";
|
||||
|
||||
|
||||
|
||||
export default function ErrorCard({ error, resetErrorBoundary }: FallbackProps) {
|
||||
|
||||
const [showDetails, toggleDetails] = useToggle(false)
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Card className="!border-red-500">
|
||||
<div className="max-w-[60ch] mx-auto flex flex-col justify-center items-center gap-24">
|
||||
<div className="text-h1 text-red-400 "><RiErrorWarningFill /></div>
|
||||
<p className="text-body4 text-center text-gray-600">Ooops... <br /> Looks like something unexpected went wrong, please check your internet connection & try again.</p>
|
||||
<div className="flex flex-col gap-12">
|
||||
<Button onClick={() => resetErrorBoundary()} color='black'>Try Again</Button>
|
||||
<Button href="/" color='gray' variant="text" size="sm" className="">Back to homepage</Button>
|
||||
</div>
|
||||
|
||||
<div className="self-start">
|
||||
|
||||
<button className="text-gray-400 text-body5 underline" onClick={() => toggleDetails()}>{showDetails ? "Hide" : "Show"} error details</button>
|
||||
{showDetails &&
|
||||
<div className="mt-16 text-gray-600">
|
||||
<p className="text-body3 text-gray-800">{error.name}</p>
|
||||
<p className="text-body4">{error.message}</p>
|
||||
<p className="text-body4 whitespace-pre-line">{error.stack}</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
)
|
||||
}
|
||||
18
src/Components/Errors/ErrorPage/ErrorPage.tsx
Normal file
18
src/Components/Errors/ErrorPage/ErrorPage.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { FallbackProps } from 'react-error-boundary'
|
||||
import ErrorCard from '../ErrorCard/ErrorCard'
|
||||
|
||||
|
||||
export default function ErrorPage({ error, resetErrorBoundary }: FallbackProps) {
|
||||
return (
|
||||
<div className="">
|
||||
<Helmet>
|
||||
<title>{`Something went wrong...`}</title>
|
||||
</Helmet>
|
||||
<div className="page-container">
|
||||
<ErrorCard error={error} resetErrorBoundary={resetErrorBoundary} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import Button from "src/Components/Button/Button";
|
||||
import { FiCopy } from "react-icons/fi";
|
||||
import useCopyToClipboard from "src/utils/hooks/useCopyToClipboard";
|
||||
import { getPropertyFromUnknown, trimText, } from "src/utils/helperFunctions";
|
||||
import { useErrorHandler } from 'react-error-boundary';
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +34,7 @@ export const useLnurlQuery = () => {
|
||||
const doFetch = async () => {
|
||||
const res = await fetchLnurlAuth();
|
||||
if (!res?.encoded)
|
||||
setError(true)
|
||||
setError(new Error("Response doesn't contain data"))
|
||||
else {
|
||||
setLoading(false);
|
||||
setData({
|
||||
@@ -43,7 +44,7 @@ export const useLnurlQuery = () => {
|
||||
timeOut = setTimeout(doFetch, 1000 * 60 * 2)
|
||||
}
|
||||
}
|
||||
doFetch()
|
||||
doFetch().catch(err => setError(err));
|
||||
|
||||
return () => clearTimeout(timeOut)
|
||||
}, [])
|
||||
@@ -64,8 +65,9 @@ export default function LoginPage() {
|
||||
|
||||
const canFetchIsLogged = useRef(true)
|
||||
const { loadingLnurl, data: { lnurl, session_token }, error } = useLnurlQuery();
|
||||
const clipboard = useCopyToClipboard()
|
||||
|
||||
useErrorHandler(error)
|
||||
const clipboard = useCopyToClipboard()
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
@@ -198,6 +200,8 @@ export default function LoginPage() {
|
||||
|
||||
</div>;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useParams, Navigate } from 'react-router-dom'
|
||||
import ErrorMessage from 'src/Components/ErrorMessage/ErrorMessage';
|
||||
import ErrorMessage from 'src/Components/Errors/ErrorMessage/ErrorMessage';
|
||||
import { useCategoryPageQuery } from 'src/graphql';
|
||||
import HeaderImage from './HeaderImage/HeaderImage';
|
||||
import ProjectsGrid from './ProjectsGrid/ProjectsGrid';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ASSETS from 'src/assets';
|
||||
|
||||
import ErrorMessage from 'src/Components/ErrorMessage/ErrorMessage';
|
||||
import ErrorMessage from 'src/Components/Errors/ErrorMessage/ErrorMessage';
|
||||
import HeaderImage from 'src/features/Projects/pages/CategoryPage/HeaderImage/HeaderImage';
|
||||
import ProjectsGrid from 'src/features/Projects/pages/CategoryPage/ProjectsGrid/ProjectsGrid';
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Wallet_Service } from 'src/services'
|
||||
import { useProjectDetailsQuery } from 'src/graphql';
|
||||
import Lightbox from 'src/Components/Lightbox/Lightbox'
|
||||
import linkifyHtml from 'linkify-html';
|
||||
import ErrorMessage from 'src/Components/ErrorMessage/ErrorMessage';
|
||||
import ErrorMessage from 'src/Components/Errors/ErrorMessage/ErrorMessage';
|
||||
import { setVoteAmount } from 'src/redux/features/vote.slice';
|
||||
import { numberFormatter } from 'src/utils/helperFunctions';
|
||||
import { MEDIA_QUERIES } from 'src/utils/theme';
|
||||
|
||||
@@ -13,8 +13,9 @@ import { ToastContainer } from 'react-toastify';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
import 'react-loading-skeleton/dist/skeleton.css'
|
||||
import THEME from './theme';
|
||||
import ErrorBoundary from 'src/Components/ErrorBoundary/ErrorBoundary';
|
||||
import { NotificationsService } from 'src/services';
|
||||
import ErrorPage from 'src/Components/Errors/ErrorPage/ErrorPage';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
THEME.injectStyles();
|
||||
|
||||
let basename = '/';
|
||||
@@ -45,7 +46,9 @@ export default function Wrapper(props: any) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<ErrorBoundary place='app'>
|
||||
<ErrorBoundary
|
||||
FallbackComponent={ErrorPage}
|
||||
>
|
||||
<ApolloProvider client={apolloClient}>
|
||||
<Provider store={store}>
|
||||
<BrowserRouter basename={basename}>
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { Outlet, } from 'react-router-dom';
|
||||
import ErrorPage from 'src/Components/Errors/ErrorPage/ErrorPage';
|
||||
import Navbar from "src/Components/Navbar/Navbar";
|
||||
|
||||
export const NavbarLayout = () => {
|
||||
return <>
|
||||
<Navbar />
|
||||
<Outlet />
|
||||
<ErrorBoundary
|
||||
FallbackComponent={ErrorPage}
|
||||
>
|
||||
<Outlet />
|
||||
</ErrorBoundary>
|
||||
</>
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user