shellphone.app/app/core/layouts/layout/index.tsx

102 lines
2.2 KiB
TypeScript
Raw Normal View History

2021-07-31 14:33:18 +00:00
import type { ErrorInfo, FunctionComponent } from "react"
import { Component } from "react"
import Head from "next/head"
import type { WithRouterProps } from "next/dist/client/with-router"
import { withRouter } from "next/router"
2021-07-18 15:32:45 +00:00
2021-07-31 14:33:18 +00:00
import appLogger from "../../../../integrations/logger"
2021-07-18 15:32:45 +00:00
2021-07-31 14:33:18 +00:00
import Footer from "./footer"
2021-07-18 15:32:45 +00:00
type Props = {
2021-07-31 14:33:18 +00:00
title: string
pageTitle?: string
hideFooter?: true
}
2021-07-18 15:32:45 +00:00
2021-07-31 14:33:18 +00:00
const logger = appLogger.child({ module: "Layout" })
2021-07-18 15:32:45 +00:00
const Layout: FunctionComponent<Props> = ({
children,
title,
pageTitle = title,
2021-07-31 14:33:18 +00:00
hideFooter = false,
2021-07-18 15:32:45 +00:00
}) => {
return (
<>
{pageTitle ? (
<Head>
<title>{pageTitle}</title>
</Head>
) : null}
<div className="h-full w-full overflow-hidden fixed bg-gray-50">
<div className="flex flex-col w-full h-full">
<div className="flex flex-col flex-1 w-full overflow-y-auto">
<main className="flex-1 my-0 h-full">
<ErrorBoundary>{children}</ErrorBoundary>
</main>
</div>
2021-07-31 14:33:18 +00:00
{!hideFooter ? <Footer /> : null}
2021-07-18 15:32:45 +00:00
</div>
</div>
</>
2021-07-31 14:33:18 +00:00
)
}
2021-07-18 15:32:45 +00:00
type ErrorBoundaryState =
| {
2021-07-31 14:33:18 +00:00
isError: false
2021-07-18 15:32:45 +00:00
}
| {
2021-07-31 14:33:18 +00:00
isError: true
errorMessage: string
}
2021-07-18 15:32:45 +00:00
const ErrorBoundary = withRouter(
class ErrorBoundary extends Component<WithRouterProps, ErrorBoundaryState> {
public readonly state = {
isError: false,
2021-07-31 14:33:18 +00:00
} as const
2021-07-18 15:32:45 +00:00
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return {
isError: true,
errorMessage: error.message,
2021-07-31 14:33:18 +00:00
}
2021-07-18 15:32:45 +00:00
}
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
2021-07-31 14:33:18 +00:00
logger.error(error, errorInfo.componentStack)
2021-07-18 15:32:45 +00:00
}
public render() {
if (this.state.isError) {
return (
<>
<h2 className="mt-6 text-center text-3xl leading-9 font-extrabold text-gray-900">
Oops, something went wrong.
</h2>
<p className="mt-2 text-center text-lg leading-5 text-gray-600">
Would you like to{" "}
<button
className="inline-flex space-x-2 items-center text-left"
onClick={this.props.router.reload}
>
<span className="transition-colors duration-150 border-b border-primary-200 hover:border-primary-500">
reload the page
</span>
</button>{" "}
?
</p>
</>
2021-07-31 14:33:18 +00:00
)
2021-07-18 15:32:45 +00:00
}
2021-07-31 14:33:18 +00:00
return this.props.children
2021-07-18 15:32:45 +00:00
}
2021-07-31 14:33:18 +00:00
}
)
2021-07-18 15:32:45 +00:00
2021-07-31 14:33:18 +00:00
export default Layout