Skip to content
16 changes: 16 additions & 0 deletions src/public/staticwebapp.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"navigationFallback": {
"rewrite": "/404.html",
"exclude": [
"/images/*.{png,jpg,gif,svg,ico,webp}",
"/_next/*",
"/favicon.ico"
]
},
"responseOverrides": {
"404": {
"rewrite": "/404.html",
"statusCode": 404
}
}
}
45 changes: 45 additions & 0 deletions src/src/app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use client";

import { useEffect } from "react";
import { useRouter } from "next/navigation";
import ErrorMessage from "@/components/shared/ErrorMessage";

export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {

Check warning on line 13 in src/src/app/error.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=lfarci_loganfarci.com&issues=AZrBvPZRsxyvI3pRQgN4&open=AZrBvPZRsxyvI3pRQgN4&pullRequest=96
const router = useRouter();

useEffect(() => {
// Log errors in development for debugging
if (process.env.NODE_ENV === "development") {
console.error(error);
}
}, [error]);

return (
<ErrorMessage
title="Oops!"
heading="Something went wrong"
message="An unexpected error has occurred. Please try again or return to the home page."
>
<div className="flex gap-4">
<button
onClick={() => reset()}
className="px-6 py-3 bg-primary text-text-inverse font-medium rounded-lg hover:bg-primary-hover transition-colors duration-200"
>
Try Again
</button>
<button
onClick={() => router.push("/")}
className="px-6 py-3 bg-surface-hover text-text-primary font-medium rounded-lg border border-border hover:bg-surface-elevated transition-colors duration-200"
>
Back to Home
</button>
</div>
</ErrorMessage>
);
}
19 changes: 19 additions & 0 deletions src/src/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Link from "next/link";
import ErrorMessage from "@/components/shared/ErrorMessage";

export default function NotFound() {
return (
<ErrorMessage
title="404"
heading="Page Not Found"
message="Sorry, the page you are looking for does not exist or has been moved."
>
<Link
href="/"
className="px-6 py-3 bg-primary text-text-inverse font-medium rounded-lg hover:bg-primary-hover transition-colors duration-200"
>
Back to Home
</Link>
</ErrorMessage>
);
}
28 changes: 28 additions & 0 deletions src/src/components/shared/ErrorMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client";

import { ReactNode } from "react";
import { typographyStyles } from "@/components/shared/typography/core/styles";

interface ErrorMessageProps {
title: string;
heading: string;
message: string;
children?: ReactNode;
}

export default function ErrorMessage({ title, heading, message, children }: ErrorMessageProps) {

Check warning on line 13 in src/src/components/shared/ErrorMessage.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=lfarci_loganfarci.com&issues=AZrPNfR_73gg9spoBSV6&open=AZrPNfR_73gg9spoBSV6&pullRequest=96
return (
<section className="flex flex-col items-center justify-center min-h-[60vh] text-center px-4">
<h1 className={`${typographyStyles.heading1} text-6xl md:text-8xl mb-4`}>
{title}
</h1>
<h2 className={`${typographyStyles.heading2} mb-6`}>
{heading}
</h2>
<p className={`${typographyStyles.text} mb-8 max-w-md`}>
{message}
</p>
{children}
</section>
);
}