diff --git a/components/common/ErrorBoundary.js b/components/common/ErrorBoundary.js new file mode 100644 index 00000000..5bb11a9e --- /dev/null +++ b/components/common/ErrorBoundary.js @@ -0,0 +1,33 @@ +/* eslint-disable no-console */ +import { ErrorBoundary as Boundary } from 'react-error-boundary'; +import { Button } from 'react-basics'; +import useMessages from 'hooks/useMessages'; +import styles from './ErrorBoundry.module.css'; + +const logError = (error, info) => { + console.error(error, info.componentStack); +}; + +export function ErrorBoundary({ children }) { + const { formatMessage, messages } = useMessages(); + + const fallbackRender = ({ error, resetErrorBoundary }) => { + console.log({ error }); + return ( +
+

{formatMessage(messages.error)}

+

{error.message}

+
{error.stack}
+ +
+ ); + }; + + return ( + + {children} + + ); +} + +export default ErrorBoundary; diff --git a/components/common/ErrorBoundry.module.css b/components/common/ErrorBoundry.module.css new file mode 100644 index 00000000..915022c4 --- /dev/null +++ b/components/common/ErrorBoundry.module.css @@ -0,0 +1,19 @@ +.error { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; + z-index: var(--z-index-overlay); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 600px; + gap: 20px; +} + +.error button { + align-self: center; +} diff --git a/components/input/DateFilter.js b/components/input/DateFilter.js index 68dcd417..b6c1ee72 100644 --- a/components/input/DateFilter.js +++ b/components/input/DateFilter.js @@ -23,7 +23,7 @@ export function DateFilter({ websiteId, value, className }) { if (data) { setDateRange({ value, ...getDateRangeValues(new Date(data.createdAt), Date.now()) }); } - } else { + } else if (value !== 'all') { setDateRange(value); } } @@ -61,7 +61,7 @@ export function DateFilter({ websiteId, value, className }) { value: '90day', }, { label: formatMessage(labels.thisYear), value: '1year' }, - { + websiteId && { label: formatMessage(labels.allTime), value: 'all', divider: true, @@ -71,7 +71,7 @@ export function DateFilter({ websiteId, value, className }) { value: 'custom', divider: true, }, - ]; + ].filter(n => n); const renderValue = value => { return value === 'custom' ? ( diff --git a/lib/date.js b/lib/date.js index 41d01304..1cfca75d 100644 --- a/lib/date.js +++ b/lib/date.js @@ -53,7 +53,7 @@ export function parseDateRange(value, locale = 'en-US') { const match = value.match(/^(?[0-9-]+)(?hour|day|week|month|year)$/); - if (!match) return; + if (!match) return {}; const { num, unit } = match.groups; diff --git a/package.json b/package.json index a586ebb0..db84659f 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "react-basics": "^0.77.0", "react-beautiful-dnd": "^13.1.0", "react-dom": "^18.2.0", + "react-error-boundary": "^4.0.4", "react-intl": "^5.24.7", "react-simple-maps": "^2.3.0", "react-spring": "^9.4.4", diff --git a/pages/_app.js b/pages/_app.js index f1a34521..22458215 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -3,6 +3,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import Head from 'next/head'; import Script from 'next/script'; import { useRouter } from 'next/router'; +import ErrorBoundary from 'components/common/ErrorBoundary'; import useLocale from 'hooks/useLocale'; import useConfig from 'hooks/useConfig'; import '@fontsource/inter/400.css'; @@ -41,21 +42,37 @@ export default function App({ Component, pageProps }) { textComponent={Wrapper} onError={() => null} > - - - - - - - - - - - - - - - {!pathname.includes('/share/') &&