-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
231 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './button/button' | ||
export * from './link/link' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* A custom Link component that extends the functionality of the React Router Link component. | ||
* It adds support for opening links in a new tab and applies a consistent set of styles. | ||
* | ||
* @param props - The props for the Link component, including the standard Link props from React Router. | ||
* @param props.newTab - Whether to open the link in a new tab. | ||
* @param props.className - Additional CSS classes to apply to the link. | ||
* @param ref - A ref to the underlying anchor element. | ||
* @returns A React Router Link component with the custom functionality and styles applied. | ||
* | ||
* Example usage: | ||
* ```tsx | ||
* <Link href="/path" className="custom-class">Link Text</Link> | ||
* ``` | ||
*/ | ||
|
||
import type React from 'react' | ||
import { forwardRef } from 'react' | ||
import { Link as RouterLink, type LinkProps as RouterLinkProps } from 'react-router' | ||
import { clx } from '#/libs/utils' | ||
|
||
interface LinkProps extends Omit<RouterLinkProps, 'to'> { | ||
href: string | ||
newTab?: boolean | ||
} | ||
|
||
const Link = forwardRef(function Component( | ||
props: LinkProps & React.ComponentPropsWithoutRef<'a'>, | ||
ref: React.ForwardedRef<HTMLAnchorElement> | ||
) { | ||
const { className, newTab, ...rest } = props | ||
const NEW_TAB_REL = 'noopener noreferrer' | ||
const NEW_TAB_TARGET = '_blank' | ||
const DEFAULT_TARGET = '_self' | ||
|
||
return ( | ||
<RouterLink | ||
to={props.href} | ||
className={clx(className)} | ||
rel={newTab ? NEW_TAB_REL : undefined} | ||
target={newTab ? NEW_TAB_TARGET : DEFAULT_TARGET} | ||
ref={ref} | ||
{...rest} | ||
/> | ||
) | ||
}) | ||
|
||
export { Link } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { useNavigate } from 'react-router' | ||
import { Link } from '#/components/base-ui' | ||
import { errorStyles } from './error.css' | ||
|
||
interface InternalErrorProps { | ||
message: string | ||
details: string | ||
stack: string | undefined | ||
statusCode: number | ||
} | ||
|
||
export default function InternalError({ message, details, stack, statusCode }: InternalErrorProps) { | ||
const navigate = useNavigate() | ||
|
||
const handleBack = () => { | ||
if (window.history.length > 1) { | ||
navigate(-1) | ||
} else { | ||
navigate('/') | ||
} | ||
} | ||
|
||
return ( | ||
<div className={errorStyles.wrapper}> | ||
<div className={errorStyles.decorativeGradient}> | ||
<div className={errorStyles.gradientInner}> | ||
<div className={errorStyles.gradientBg} /> | ||
</div> | ||
</div> | ||
<div className={errorStyles.decorativeCode}> | ||
<h2 className={errorStyles.decorativeText}>{statusCode}</h2> | ||
</div> | ||
<div className={errorStyles.content}> | ||
<div className={errorStyles.container}> | ||
<p className={errorStyles.errorCode}>{statusCode}</p> | ||
<h1 className={errorStyles.title}>{message}</h1> | ||
<p className={errorStyles.description}>{details}</p> | ||
{stack && ( | ||
<pre className={errorStyles.pre}> | ||
<code>{stack}</code> | ||
</pre> | ||
)} | ||
<div className={errorStyles.actions}> | ||
<button type="button" onClick={handleBack} className={errorStyles.primaryButton}> | ||
Go back | ||
</button> | ||
<Link href="/docs/troubleshooting" className={errorStyles.secondaryButton} newTab> | ||
Troubleshooting Guide | ||
</Link> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
export const errorStyles = { | ||
wrapper: 'relative min-h-screen bg-gray-50 dark:bg-gray-950 overflow-hidden', | ||
decorativeGradient: 'absolute inset-0 overflow-hidden', | ||
gradientInner: 'absolute -inset-[10px] opacity-50', | ||
gradientBg: [ | ||
'absolute top-0 h-[40rem] w-full', | ||
'bg-gradient-to-b from-gray-500/20 via-transparent to-transparent dark:from-gray-900/30 dark:via-transparent dark:to-transparent', | ||
'before:absolute before:inset-0 before:bg-[radial-gradient(circle_at_center,_var(--tw-gradient-stops))] before:from-gray-400/10 dark:before:from-gray-500/10 before:via-transparent before:to-transparent', | ||
'after:absolute after:inset-0 after:bg-[radial-gradient(circle_at_center,_var(--tw-gradient-stops))] after:from-indigo-400/10 dark:after:from-indigo-500/10 after:via-transparent after:to-transparent', | ||
].join(' '), | ||
content: | ||
'relative flex min-h-screen flex-col items-center justify-center px-4 py-16 sm:px-6 lg:px-8', | ||
container: 'relative z-20 text-center', | ||
errorCode: 'text-2xl font-bold text-red-500 dark:text-red-400', | ||
title: 'mt-4 text-3xl font-bold tracking-tight text-gray-900 dark:text-gray-100 sm:text-5xl', | ||
description: 'mt-6 text-base leading-7 text-gray-600 dark:text-gray-400', | ||
actions: 'mt-10 flex items-center justify-center gap-x-4', | ||
primaryButton: [ | ||
'min-w-[140px] rounded-lg bg-gray-900 px-4 py-2.5 text-sm cursor-pointer font-semibold text-white', | ||
'transition-all duration-200 hover:bg-gray-800 hover:shadow-lg hover:shadow-gray-500/20', | ||
'focus:outline-hidden focus:ring-2 focus:ring-gray-400/50 focus:ring-offset-2', | ||
'focus:ring-offset-gray-50 dark:focus:ring-offset-gray-950', | ||
].join(' '), | ||
secondaryButton: [ | ||
'min-w-[140px] rounded-lg border border-gray-200 dark:border-gray-800 bg-white/80 dark:bg-gray-900/80 px-4 py-2.5', | ||
'text-sm cursor-pointer font-semibold text-gray-700 dark:text-gray-200', | ||
'transition-all duration-200 hover:bg-gray-50 dark:hover:bg-gray-800 hover:border-gray-500/30', | ||
'hover:text-gray-500 dark:hover:text-gray-400 hover:shadow-lg hover:shadow-gray-500/10', | ||
'focus:outline-hidden focus:ring-2 focus:ring-gray-400/50 focus:ring-offset-2', | ||
'focus:ring-offset-gray-50 dark:focus:ring-offset-gray-950', | ||
].join(' '), | ||
decorativeCode: | ||
'fixed inset-0 flex items-center justify-center z-10 pointer-events-none select-none', | ||
decorativeText: | ||
'text-[12rem] sm:text-[16rem] md:text-[20rem] font-black text-red-100/30 dark:text-red-900/20 mix-blend-overlay', | ||
pre: 'mt-6 w-full overflow-x-auto rounded-md border bg-background/80 p-4 font-mono text-sm', | ||
} as const |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
/* @ref: https://reactrouter.com/start/framework/routing */ | ||
|
||
import { type RouteConfig, index } from '@react-router/dev/routes' | ||
|
||
export default [index('routes/home.tsx')] satisfies RouteConfig | ||
export default [ | ||
index('./routes/home.tsx'), | ||
// route('/healthz', './routes/healthz.ts'), | ||
] satisfies RouteConfig |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import {} from '@react-router/node' | ||
import consola from 'consola' | ||
import { LoaderFunctionArgs } from 'react-router' | ||
// import { getRequestIpAddress } from '#/utils/request.server' | ||
|
||
export async function loader({ request }: LoaderFunctionArgs) { | ||
const host = request.headers.get('X-Forwarded-Host') ?? request.headers.get('host') | ||
const url = new URL('/', `http://${host}`) | ||
|
||
// TODO: put some real logic here | ||
// if we can connect to the database and make a simple query | ||
// and make a HEAD request to ourselves, then we're good. | ||
|
||
try { | ||
await Promise.all([ | ||
fetch(url.toString(), { method: 'HEAD' }).then((r) => { | ||
if (!r.ok) return Promise.reject(r) | ||
}), | ||
]) | ||
|
||
const flyRegion = process.env.FLY_REGION | ||
const flyMachineId = process.env.FLY_MACHINE_ID | ||
const flyRequestId = request.headers.get('Fly-Request-Id') | ||
const serviceId = `${flyRegion}::${flyMachineId}::${flyRequestId}` | ||
const clientIpAddr = request.headers.get('X-Client-IP') | ||
const isHostedOnFly = flyRegion && flyMachineId | ||
|
||
const responsePayload = { | ||
status: '🫡 All is well!', | ||
id: isHostedOnFly ? serviceId : host, | ||
ip: clientIpAddr, | ||
} | ||
|
||
// return json(responsePayload, { status: 200, headers: { 'Cache-Control': 'no-store' } }) | ||
return responsePayload | ||
} catch (error: unknown) { | ||
consola.error('healthcheck ❌', { error }) | ||
return new Response('Unhealthy', { status: 500, headers: { 'Cache-Control': 'no-store' } }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters