diff --git a/src/app/(admin)/dashboard/page.tsx b/src/app/(admin)/dashboard/page.tsx
index 19f15f5..749c9d6 100644
--- a/src/app/(admin)/dashboard/page.tsx
+++ b/src/app/(admin)/dashboard/page.tsx
@@ -1,4 +1,7 @@
+import { StatsCard } from "@/components/dashboard/stats-card"
import { getSession } from "@/lib/auth/session"
+import { getDashboardStats } from "@/lib/dashboard/stats"
+import { LinkIcon, MousePointerClick, TrendingUp } from "lucide-react"
export default async function Dashboard() {
const { session, redirect } = await getSession()
@@ -7,10 +10,42 @@ export default async function Dashboard() {
redirect("/sign-in")
}
+ const stats = await getDashboardStats()
+
+ // Determine the most visited URL display value
+ const mostVisitedDisplay = stats.mostVisitedUrl
+ ? `${stats.mostVisitedUrl.title} (${stats.mostVisitedUrl.visitCount})`
+ : "No URLs"
+
+ const mostVisitedDescription = stats.mostVisitedUrl
+ ? `/${stats.mostVisitedUrl.slug} - ${stats.mostVisitedUrl.visitCount} visits`
+ : "Create your first shortened URL"
+
return (
Dashboard
-
Welcome to your dashboard! Use the sidebar to navigate to different sections.
+
Welcome to your dashboard! Use the sidebar to navigate to different sections.
+
+
+ }
+ description="Total number of shortened links"
+ />
+ }
+ description="Combined visits across all links"
+ />
+ }
+ description={mostVisitedDescription}
+ />
+
)
}
diff --git a/src/components/dashboard/stats-card.tsx b/src/components/dashboard/stats-card.tsx
new file mode 100644
index 0000000..20ea170
--- /dev/null
+++ b/src/components/dashboard/stats-card.tsx
@@ -0,0 +1,25 @@
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+
+interface StatsCardProps {
+ title: string
+ value: number | string
+ icon?: React.ReactNode
+ description?: string
+}
+
+export function StatsCard({ title, value, icon, description }: StatsCardProps) {
+ const displayValue = typeof value === "number" ? value.toLocaleString() : value
+
+ return (
+
+
+ {title}
+ {icon}
+
+
+ {displayValue}
+ {description && {description}
}
+
+
+ )
+}
diff --git a/src/lib/dashboard/stats.ts b/src/lib/dashboard/stats.ts
new file mode 100644
index 0000000..97c1971
--- /dev/null
+++ b/src/lib/dashboard/stats.ts
@@ -0,0 +1,40 @@
+import { count, desc, eq } from "drizzle-orm"
+import { db } from "../drizzle/db"
+import { urls, visits } from "../drizzle/schema"
+
+export async function getDashboardStats() {
+ try {
+ // Get count of shortened URLs
+ const [urlsCount] = await db.select({ count: count() }).from(urls)
+
+ // Get count of total visits
+ const [visitsCount] = await db.select({ count: count() }).from(visits)
+
+ // Get most visited URL
+ const mostVisitedUrl = await db
+ .select({
+ id: urls.id,
+ title: urls.title,
+ slug: urls.slug,
+ visitCount: count(visits.id)
+ })
+ .from(urls)
+ .leftJoin(visits, eq(urls.id, visits.urlId))
+ .groupBy(urls.id, urls.title, urls.slug)
+ .orderBy(desc(count(visits.id)))
+ .limit(1)
+
+ return {
+ totalUrls: urlsCount.count,
+ totalVisits: visitsCount.count,
+ mostVisitedUrl: mostVisitedUrl[0] || null
+ }
+ } catch (error) {
+ console.error("Failed to fetch dashboard stats:", error)
+ return {
+ totalUrls: 0,
+ totalVisits: 0,
+ mostVisitedUrl: null
+ }
+ }
+}