Skip to content

Commit

Permalink
Add error boundary
Browse files Browse the repository at this point in the history
  • Loading branch information
devcshort committed Jul 26, 2024
1 parent 2410c02 commit 75c5717
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 1 deletion.
98 changes: 98 additions & 0 deletions packages/client/components/error-boundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { ReactNode } from 'react';
import { Title, Text, Button, Stack } from '@mantine/core';
import Link from 'next/link';
import Image from 'next/image';
import axios from 'axios';

type Props = {
children: ReactNode;
appConfig?: any;
};

type State = {
hasError: false;
};

export default class ErrorBoundary extends React.Component<Props, State> {
constructor(props: Props) {
super(props);

// Define a state variable to track whether is an error or not
this.state = { hasError: false };
}

static getDerivedStateFromError(error: any) {
// Update state so the next render will show the fallback UI

return { hasError: true };
}

async componentDidCatch(error: any, errorInfo: any) {
// You can use your own error logging service here
console.log({ error, errorInfo });

try {
await axios.post('/api/webhook', {
message: error?.message,
brandName: this.props?.appConfig?.brand?.name,
faviconUrl: this.props?.appConfig?.brand?.faviconUrl,
url: window?.location?.href,
openGraphUrl: this.props?.appConfig?.brand?.openGraphUrl,
hostname: window?.location?.hostname,
});
} catch (err) {
console.log('Unable to send webhook');
}
}

render() {
// Check if the error is thrown
if (this.state.hasError) {
// You can render any custom fallback UI
return (
<Stack sx={{ position: 'relative', minHeight: '100vh' }}>
<Image
fill
src="/undraw_bug_fixing.svg"
alt=""
style={{
objectFit: 'contain',
zIndex: -1,
objectPosition: 'center',
}}
/>

<Stack
spacing="xl"
pt="100px"
pb="100px"
bg="rgba(0,0,0,0.5)"
align="center"
justify="center"
h="100vh"
>
<Title color="white">An unknown error has occurred</Title>

<Text
size="lg"
align="center"
color="white"
weight={500}
maw="500px"
>
Our development team has been notified and will be working on a
fix.
</Text>

<Button size="md" component={Link} href="/">
Back to home
</Button>
</Stack>
</Stack>
);
}

// Return children components in case of no error
return this.props.children;
}
}
1 change: 1 addition & 0 deletions packages/client/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export function middleware(request: NextRequest) {
value: sessionId,
path: '/',
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
});

return response;
Expand Down
5 changes: 4 additions & 1 deletion packages/client/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
UpdateLocationModal,
} from '../components/organisms/modals';
import { AppProps } from 'next/app';
import ErrorBoundary from '../components/error-boundary';

function App({ Component, pageProps: { session, ...pageProps } }: AppProps) {
const appConfig = useAppConfig();
Expand Down Expand Up @@ -53,7 +54,9 @@ function App({ Component, pageProps: { session, ...pageProps } }: AppProps) {
}}
>
<PrevUrlProvider>
<Component {...pageProps} />
<ErrorBoundary appConfig={appConfig}>
<Component {...pageProps} />
</ErrorBoundary>
<GoogleTagManagerScript />
</PrevUrlProvider>
</ModalsProvider>
Expand Down
61 changes: 61 additions & 0 deletions packages/client/pages/api/webhook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { type NextApiHandler } from 'next';
import axios from 'axios';
import nookies from 'nookies';
import z from 'zod';

const Webhook: NextApiHandler = async (req, res) => {
switch (req.method) {
case 'POST':
return await POST(req, res);
default:
res.statusCode = 404;
res.send('Not found');
}
};

const POST: NextApiHandler = async (req, res) => {
const cookies = nookies.get({ req });
const sessionId = cookies['session-id'];
if (process.env.WEBHOOK_ALERT_URL != null && sessionId != null) {
const bodySchema = z.object({
message: z.string(),
brandName: z.string(),
faviconUrl: z.string(),
url: z.string(),
openGraphUrl: z.string(),
hostname: z.string(),
});

const body = await bodySchema.parseAsync(req.body);

try {
await axios.post(`${process.env.WEBHOOK_ALERT_URL}`, {
embeds: [
{
title: 'An unhandled error has occurred',
description: body.message,
author: {
name: body.brandName,
icon_url: body.faviconUrl,
},
url: body.url,
image: {
url: body.openGraphUrl,
},
timestamp: new Date(),
footer: {
text: body.hostname,
},
},
],
});
} catch (err) {
console.log('unable to send webhook request.');
}
}

res.statusCode = 200;
res.send('Done');
};

export default Webhook;
1 change: 1 addition & 0 deletions packages/client/public/undraw_bug_fixing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 75c5717

Please sign in to comment.