From 62e282abd4167cc3304e17ffa7623cf756e81acf Mon Sep 17 00:00:00 2001 From: AliMahmoudDev <123aliactionx5@gmail.com> Date: Tue, 14 Jul 2026 16:28:31 +0000 Subject: [PATCH] feat: create specialized Badge component for Health Scores Add HealthBadge component that displays health scores with color-coded tier labels: Excellent (80+), Good (60+), Warning (40+), Critical (<40). - New HealthBadge component with sm/md/lg sizes and optional label - Color-coded badges using ring and background styles - Integrated into dashboard repository cards - Shows badge only when healthScore is available Closes #6 --- apps/web/src/app/dashboard/page.tsx | 12 +++-- apps/web/src/components/health-badge.tsx | 57 ++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 apps/web/src/components/health-badge.tsx diff --git a/apps/web/src/app/dashboard/page.tsx b/apps/web/src/app/dashboard/page.tsx index 2a230c5..10c9180 100644 --- a/apps/web/src/app/dashboard/page.tsx +++ b/apps/web/src/app/dashboard/page.tsx @@ -5,6 +5,7 @@ import { auth } from "@clerk/nextjs/server"; import { eq } from "drizzle-orm"; import { redirect } from "next/navigation"; import Link from "next/link"; +import { HealthBadge } from "@/components/health-badge"; export default async function DashboardPage() { const { userId } = await auth(); @@ -70,9 +71,14 @@ export default async function DashboardPage() { {repo.isPrivate ? 'Private' : 'Public'} - - {repo.syncStatus} - +
+ {repo.healthScore !== null && repo.healthScore !== undefined && ( + + )} + + {repo.syncStatus} + +
diff --git a/apps/web/src/components/health-badge.tsx b/apps/web/src/components/health-badge.tsx new file mode 100644 index 0000000..7d5066e --- /dev/null +++ b/apps/web/src/components/health-badge.tsx @@ -0,0 +1,57 @@ +interface HealthBadgeProps { + score: number; + size?: "sm" | "md" | "lg"; + showLabel?: boolean; +} + +function getScoreTier(score: number): { label: string; bgColor: string; textColor: string; ringColor: string } { + if (score >= 80) { + return { + label: "Excellent", + bgColor: "bg-green-50", + textColor: "text-green-700", + ringColor: "ring-green-600/20", + }; + } + if (score >= 60) { + return { + label: "Good", + bgColor: "bg-blue-50", + textColor: "text-blue-700", + ringColor: "ring-blue-600/20", + }; + } + if (score >= 40) { + return { + label: "Warning", + bgColor: "bg-yellow-50", + textColor: "text-yellow-700", + ringColor: "ring-yellow-600/20", + }; + } + return { + label: "Critical", + bgColor: "bg-red-50", + textColor: "text-red-700", + ringColor: "ring-red-600/20", + }; +} + +const sizeClasses = { + sm: "text-xs px-2 py-0.5", + md: "text-sm px-2.5 py-1", + lg: "text-base px-3 py-1.5", +}; + +export function HealthBadge({ score, size = "md", showLabel = true }: HealthBadgeProps) { + const tier = getScoreTier(score); + + return ( + + {score} + {showLabel && {tier.label}} + + ); +}