This commit is contained in:
nprasad2077 committed 2026-09-04 03:53:42 -05:00
1 parent 4b8ae1bbac
commit 9c7dee2c7c
8 files changed
+74 -24

No files matched your search

+6
View File
@@ -4,10 +4,16 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/medical-history-doctor-svgrepo-com.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Interactive Medicare Enrollment Dashboard featuring CMS monthly enrollment data, Medicare Advantage (MA) penetration rates, and state & county trends." />
<meta name="theme-color" content="#1e3a5f" />
<link rel="apple-touch-icon" href="/medical-history-doctor-192.png" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="preconnect" href="https://data.cms.gov" />
<link rel="preconnect" href="https://a.basemaps.cartocdn.com" />
<link rel="preconnect" href="https://b.basemaps.cartocdn.com" />
<link rel="preconnect" href="https://c.basemaps.cartocdn.com" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" />
<title>Medicare Enrollment Dashboard</title>
</head>
<body>
+32 -7
View File
@@ -72,12 +72,37 @@ function Dashboard() {
if (isLoading) {
return (
<div className="min-h-screen bg-background flex items-center justify-center">
<div className="flex flex-col items-center gap-3">
<div className="w-8 h-8 border-4 border-gray-200 border-t-gray-600 rounded-full animate-spin" />
<p className="text-sm text-muted-foreground">Loading Medicare Enrollment Data...</p>
<main className="min-h-screen bg-background font-[var(--font-family)]" aria-busy="true" aria-label="Loading Medicare Enrollment Dashboard">
<div className="w-full max-w-[1560px] mx-auto p-6 lg:p-8 space-y-6 lg:space-y-8 animate-pulse">
{/* Header Skeleton */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-gray-200 rounded-xl" />
<div className="space-y-2">
<div className="w-64 h-7 bg-gray-200 rounded" />
<div className="w-40 h-4 bg-gray-200 rounded" />
</div>
</div>
<div className="w-64 h-10 bg-gray-100 rounded-lg" />
</div>
{/* Metrics Skeleton */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
{[1, 2, 3, 4].map(i => (
<div key={i} className="h-28 bg-white border border-gray-200 rounded-xl p-5" />
))}
</div>
{/* Main Grid Skeleton */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-6">
<div className="h-[480px] bg-white border border-gray-200 rounded-xl" />
<div className="h-[360px] bg-white border border-gray-200 rounded-xl" />
</div>
<div className="h-[520px] bg-white border border-gray-200 rounded-xl" />
</div>
</div>
</div>
</main>
)
}
@@ -89,7 +114,7 @@ function Dashboard() {
const trendLabel = selectedCounty || (selectedState ? stateData?.find(s => s.state === selectedState)?.name : null)
return (
<div className="min-h-screen bg-background font-[var(--font-family)]">
<main className="min-h-screen bg-background font-[var(--font-family)]">
<div className="w-full max-w-[1560px] mx-auto p-6 lg:p-8 space-y-6 lg:space-y-8">
<Header view={view} setView={setView} latestData={latestData} onReset={handleBackToAll} />
<SummaryMetrics data={latestData} view={view} />
@@ -135,7 +160,7 @@ function Dashboard() {
</div>
</div>
</div>
</div>
</main>
)
}
+8 -8
View File
@@ -180,12 +180,12 @@ export default function StateDetail({ view, state, stateData, countyData, county
<table className="w-full text-xs">
<thead className="sticky top-0 bg-gray-50 z-10">
<tr className="border-b border-gray-200">
<th className="text-left py-2 px-3 font-medium text-gray-600">County</th>
<th className="text-right py-2 px-3 font-medium text-gray-600">TOTAL</th>
<th className="text-right py-2 px-3 font-medium text-gray-600">{cat2}</th>
<th className="text-right py-2 px-3 font-medium text-gray-600">{cat1}</th>
<th className="text-right py-2 px-3 font-medium text-gray-600">{cat2}%</th>
<th className="text-right py-2 px-3 font-medium text-gray-600">{cat1}%</th>
<th className="text-left py-2 px-3 font-semibold text-gray-700">County</th>
<th className="text-right py-2 px-3 font-semibold text-gray-700">TOTAL</th>
<th className="text-right py-2 px-3 font-semibold text-gray-700">{cat2}</th>
<th className="text-right py-2 px-3 font-semibold text-gray-700">{cat1}</th>
<th className="text-right py-2 px-3 font-semibold text-gray-700">{cat2}%</th>
<th className="text-right py-2 px-3 font-semibold text-gray-700">{cat1}%</th>
</tr>
</thead>
<tbody>
@@ -210,10 +210,10 @@ export default function StateDetail({ view, state, stateData, countyData, county
{countyLoading ? (
<div className="flex flex-col items-center gap-2">
<div className="w-6 h-6 border-[3px] border-gray-200 border-t-blue-600 rounded-full animate-spin" />
<span className="text-xs text-gray-500">Loading counties...</span>
<span className="text-xs text-gray-600">Loading counties...</span>
</div>
) : (
<span className="text-xs text-gray-400">No county data available</span>
<span className="text-xs text-gray-600">No county data available</span>
)}
</td></tr>
)}
+2 -2
View File
@@ -64,9 +64,9 @@ export default function SummaryMetrics({ data, view }) {
<CardContent className="p-5">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-500">{m.label}</p>
<p className="text-sm font-medium text-gray-700">{m.label}</p>
<p className="text-3xl font-bold text-gray-900 mt-1 tracking-tight">{m.value}</p>
<p className="text-xs text-gray-400 mt-0.5">{m.sub}</p>
<p className="text-xs text-gray-600 font-medium mt-0.5">{m.sub}</p>
</div>
<div className={`w-11 h-11 ${m.iconBg} rounded-xl flex items-center justify-center shrink-0`}>
<m.icon className={`w-5 h-5 ${m.iconColor}`} />
+3 -3
View File
@@ -178,7 +178,7 @@ export default function TrendPanel({ view, yearlyTrend, monthlyTrend, selectedSt
<button
onClick={() => setTab('yearly')}
className={`px-3 py-1.5 rounded-md text-xs font-medium transition-all ${
tab === 'yearly' ? 'bg-white text-gray-900 shadow-sm' : 'text-gray-500 hover:text-gray-700'
tab === 'yearly' ? 'bg-white text-gray-900 shadow-sm' : 'text-gray-700 hover:text-gray-900'
}`}
>
Yearly Trend
@@ -186,7 +186,7 @@ export default function TrendPanel({ view, yearlyTrend, monthlyTrend, selectedSt
<button
onClick={() => setTab('monthly')}
className={`px-3 py-1.5 rounded-md text-xs font-medium transition-all ${
tab === 'monthly' ? 'bg-white text-gray-900 shadow-sm' : 'text-gray-500 hover:text-gray-700'
tab === 'monthly' ? 'bg-white text-gray-900 shadow-sm' : 'text-gray-700 hover:text-gray-900'
}`}
>
12-Month Trend
@@ -195,7 +195,7 @@ export default function TrendPanel({ view, yearlyTrend, monthlyTrend, selectedSt
<button
onClick={() => setTab('grid')}
className={`px-3 py-1.5 rounded-md text-xs font-medium transition-all ${
tab === 'grid' ? 'bg-white text-gray-900 shadow-sm' : 'text-gray-500 hover:text-gray-700'
tab === 'grid' ? 'bg-white text-gray-900 shadow-sm' : 'text-gray-700 hover:text-gray-900'
}`}
>
Grid
+2 -2
View File
@@ -8,8 +8,8 @@ export function CardHeader({ className, ...props }) {
return <div className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />;
}
export function CardTitle({ className, ...props }) {
return <h3 className={cn("text-lg font-semibold leading-none tracking-tight", className)} {...props} />;
export function CardTitle({ className, as: Component = "h2", ...props }) {
return <Component className={cn("text-lg font-semibold leading-none tracking-tight", className)} {...props} />;
}
export function CardContent({ className, ...props }) {
-1
View File
@@ -1,4 +1,3 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
@import 'tailwindcss' source(none);
@source '../**/*.{js,jsx,ts,tsx}';
@import 'tw-animate-css';
+21 -1
View File
@@ -39,5 +39,25 @@ export default defineConfig({
]
}
})
]
],
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules/recharts') || id.includes('node_modules/d3-')) {
return 'vendor-charts'
}
if (id.includes('node_modules/leaflet') || id.includes('node_modules/react-leaflet')) {
return 'vendor-maps'
}
if (id.includes('node_modules/@tanstack')) {
return 'vendor-query'
}
if (id.includes('node_modules/lucide-react')) {
return 'vendor-icons'
}
}
}
}
}
})