diff --git a/frontend/app/error.tsx b/frontend/app/error.tsx
new file mode 100644
index 0000000..508896b
--- /dev/null
+++ b/frontend/app/error.tsx
@@ -0,0 +1,103 @@
+"use client";
+
+import { useEffect } from "react";
+import { Button } from "@/components/ui/button";
+import { AlertTriangle, RefreshCcw, Home, ArrowLeft, HelpCircle } from "lucide-react";
+import { useRouter } from "next/navigation";
+import Link from "next/link";
+
+interface ErrorProps {
+ error: Error & { digest?: string };
+ reset: () => void;
+}
+
+export default function Error({ error, reset }: ErrorProps) {
+ useEffect(() => {
+ // Log the error to an error reporting service
+ console.error("Application error:", error);
+ }, [error]);
+
+ const router = useRouter();
+
+ // Determine error type to show appropriate message
+ const getErrorMessage = () => {
+ if (error.message.includes("FARM_NOT_FOUND")) {
+ return "The farm you're looking for could not be found.";
+ }
+ if (error.message.includes("CROP_NOT_FOUND")) {
+ return "The crop you're looking for could not be found.";
+ }
+ if (error.message.includes("UNAUTHORIZED")) {
+ return "You don't have permission to access this resource.";
+ }
+ if (error.message.includes("NETWORK")) {
+ return "Network error. Please check your internet connection.";
+ }
+ return "We apologize for the inconvenience. An unexpected error has occurred.";
+ };
+
+ return (
+
+
+
+ {/* Decorative elements */}
+
+
+
+ {/* Main icon */}
+
+
+
+
Something went wrong
+
{getErrorMessage()}
+
+ {error.message && !["FARM_NOT_FOUND", "CROP_NOT_FOUND", "UNAUTHORIZED"].includes(error.message) && (
+
+
Error details:
+
{error.message}
+ {error.digest &&
Error ID: {error.digest}
}
+
+ )}
+
+
+
+
+
+
+
+
+
+ Need help?{" "}
+
+ Contact Support
+
+
+
+
+ Support Code: {error.digest ? error.digest.substring(0, 8) : "Unknown"}
+
+
+
+
+ );
+}
diff --git a/frontend/app/global-error.tsx b/frontend/app/global-error.tsx
new file mode 100644
index 0000000..f7e182f
--- /dev/null
+++ b/frontend/app/global-error.tsx
@@ -0,0 +1,51 @@
+"use client";
+
+import { Button } from "@/components/ui/button";
+import { AlertTriangle, RefreshCcw, Home } from "lucide-react";
+
+interface GlobalErrorProps {
+ error: Error & { digest?: string };
+ reset: () => void;
+}
+
+export default function GlobalError({ error, reset }: GlobalErrorProps) {
+ return (
+
+
+
+
+
+
+
Critical Error
+
The application has encountered a critical error and cannot continue.
+
+ {error.message && (
+
+
Error details:
+
{error.message}
+ {error.digest &&
Error ID: {error.digest}
}
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/app/globals.css b/frontend/app/globals.css
index 405715a..94ab5ed 100644
--- a/frontend/app/globals.css
+++ b/frontend/app/globals.css
@@ -3,7 +3,7 @@
@tailwind utilities;
body {
- font-family: Arial, Helvetica, sans-serif;
+ font-family: var(--font-poppins);
}
@layer base {
diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx
index 17285cf..eb91124 100644
--- a/frontend/app/layout.tsx
+++ b/frontend/app/layout.tsx
@@ -1,20 +1,15 @@
import type { Metadata } from "next";
-import { Open_Sans, Roboto_Mono } from "next/font/google";
+import { Poppins } from "next/font/google";
import "./globals.css";
import { ThemeProvider } from "@/components/theme-provider";
import { SessionProvider } from "@/context/SessionContext";
-const openSans = Open_Sans({
+const poppins = Poppins({
subsets: ["latin"],
display: "swap",
- variable: "--font-opensans",
-});
-
-const robotoMono = Roboto_Mono({
- subsets: ["latin"],
- display: "swap",
- variable: "--font-roboto-mono",
+ variable: "--font-poppins",
+ weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
});
// const geistMono = Geist_Mono({
@@ -36,7 +31,7 @@ export default function RootLayout({