Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions app/api/compare/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
11 changes: 5 additions & 6 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -65,7 +66,7 @@ export default function HomePage() {
console.log("Swapped users", data);
};
return (
<main className="min-h-screen">
<main className="min-h-screen flex flex-col">
{" "}
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 max-w-7xl items-center justify-between m-auto px-4">
Expand All @@ -74,10 +75,10 @@ export default function HomePage() {
DevImpact
</span>
</div>

</div>
</header>
<div className="max-w-6xl mx-auto px-4 py-10 space-y-6">
<div className="flex-1 max-w-6xl mx-auto px-4 py-10 space-y-6 w-full">
<CompareForm
onSubmit={handleCompare}
loading={loading}
Expand All @@ -88,9 +89,7 @@ export default function HomePage() {

{loading && skeleton}
{error && (
<div className="card p-4 text-sm text-red-600 bg-red-50 border border-red-100">
{error}
</div>
<ErrorMessage error={error} onRetry={() => setError(null)} />
)}
{data && <ResultDashboard user1={data.user1} user2={data.user2} />}
{!loading && !error && !data && (
Expand Down
61 changes: 61 additions & 0 deletions components/error-message.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>{title}</AlertTitle>
<AlertDescription>
<p>{description}</p>
{onRetry && (
<button
onClick={onRetry}
className="mt-2 text-sm underline underline-offset-2 hover:no-underline"
>
Try again
</button>
)}
</AlertDescription>
</Alert>
);
}
Loading