From 12c969e512cd79f3eafa8c039b01fae159654b7d Mon Sep 17 00:00:00 2001 From: Ai-chan-0411 Date: Sun, 12 Apr 2026 23:18:40 +0900 Subject: [PATCH] feat: display friendly error messages on API failure closes #34 Add user-friendly error messages when GitHub API calls fail: - ErrorMessage component with error type detection (rate limit/not found/network) - Retry button for transient errors - Replaces generic red error box with proper Alert component Signed-off-by: Ai-chan-0411 --- app/api/compare/route.ts | 13 +++++--- app/page.tsx | 11 +++---- components/error-message.tsx | 61 ++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 components/error-message.tsx diff --git a/app/api/compare/route.ts b/app/api/compare/route.ts index 809b290..3ba353d 100644 --- a/app/api/compare/route.ts +++ b/app/api/compare/route.ts @@ -36,10 +36,15 @@ export async function GET(request: Request) { return NextResponse.json({ success: true, users: results }); } catch (error: any) { console.error("GitHub score error:", error); - const message = - error?.message === "User not found" - ? "GitHub user not found" - : "Failed to calculate score"; + let message = "Failed to calculate score"; + if (error?.message === "User not found") { + message = "User not found"; + } else if ( + error?.message?.toLowerCase().includes("rate limit") || + error?.status === 403 + ) { + message = "GitHub API rate limit exceeded. Please try again later."; + } return NextResponse.json( { success: false, error: message }, { status: 500 } diff --git a/app/page.tsx b/app/page.tsx index a1b5596..82d267c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,6 +2,7 @@ import { useMemo, useState } from "react"; import { CompareForm } from "../components/compare-form"; +import { ErrorMessage } from "../components/error-message"; import { ResultDashboard } from "../components/result-dashboard"; import { DashboardSkeleton } from "../components/skeletons"; import { UserResult } from "@/types/user-result"; @@ -65,7 +66,7 @@ export default function HomePage() { console.log("Swapped users", data); }; return ( -
+
{" "}
@@ -74,10 +75,10 @@ export default function HomePage() { DevImpact
- +
-
+
- {error} -
+ setError(null)} /> )} {data && } {!loading && !error && !data && ( diff --git a/components/error-message.tsx b/components/error-message.tsx new file mode 100644 index 0000000..d3cd449 --- /dev/null +++ b/components/error-message.tsx @@ -0,0 +1,61 @@ +import { AlertCircle } from "lucide-react"; +import { Alert, AlertDescription, AlertTitle } from "./ui/alert"; + +type ErrorMessageProps = { + error: string; + onRetry?: () => void; +}; + +function getErrorDetails(error: string): { + title: string; + description: string; +} { + const lower = error.toLowerCase(); + if (lower.includes("not found") || lower.includes("user not found")) { + return { + title: "User not found", + description: + "The GitHub username you entered does not exist. Please check the spelling and try again.", + }; + } + if (lower.includes("rate limit") || lower.includes("rate_limit")) { + return { + title: "Rate limit exceeded", + description: + "GitHub API rate limit has been reached. Please wait a few minutes and try again.", + }; + } + if (lower.includes("network") || lower.includes("failed to fetch")) { + return { + title: "Network error", + description: + "Could not connect to the server. Check your internet connection and try again.", + }; + } + return { + title: "Something went wrong", + description: error || "An unexpected error occurred. Please try again.", + }; +} + +export function ErrorMessage({ error, onRetry }: ErrorMessageProps) { + const { title, description } = getErrorDetails(error); + + return ( + + + {title} + +

{description}

+ {onRetry && ( + + )} +
+
+ ); +}