-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Feat(saas): Admin Dashboard with Analytics This pull request introduces a new admin dashboard to the RapidLaunch SaaS platform, providing administrators with valuable insights and management capabilities. **Key features:** * **Comprehensive dashboard**: Provides a central hub for administrators to monitor key metrics and manage various aspects of the platform. * **Analytics integration**: Includes detailed analytics on user activity, subscription data, and other relevant metrics, empowering data-driven decision making.
- Loading branch information
Showing
23 changed files
with
2,268 additions
and
2,901 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
starterkits/saas/src/app/(app)/admin/dashboard/_components/revenue-chart.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
"use client"; | ||
|
||
import { LineChart } from "@/components/charts"; | ||
import { | ||
Card, | ||
CardContent, | ||
CardDescription, | ||
CardHeader, | ||
CardTitle, | ||
} from "@/components/ui/card"; | ||
import { thousandToK } from "@/lib/utils"; | ||
|
||
type RevenueChartProps = { | ||
data: { | ||
Date: string; | ||
RevenueCount: number; | ||
}[]; | ||
}; | ||
|
||
export function RevenueChart({ data }: RevenueChartProps) { | ||
return ( | ||
<Card> | ||
<CardHeader> | ||
<CardTitle>Revenue Analytics</CardTitle> | ||
<CardDescription> | ||
Count of revenue each month for last 6 months | ||
</CardDescription> | ||
</CardHeader> | ||
<CardContent> | ||
<LineChart | ||
data={data} | ||
xAxisDataKey="Date" | ||
yAxisDataKey="RevenueCount" | ||
lineDataKeys={["RevenueCount"]} | ||
lineProps={[{ stroke: "hsl(var(--primary))" }]} | ||
yAxisProps={{ | ||
tickFormatter: (value) => { | ||
if (value >= 10000) { | ||
return `${thousandToK(Number(value)).toFixed(1)}k`; | ||
} else { | ||
return `${value}`; | ||
} | ||
}, | ||
}} | ||
/> | ||
</CardContent> | ||
</Card> | ||
); | ||
} |
24 changes: 24 additions & 0 deletions
24
starterkits/saas/src/app/(app)/admin/dashboard/_components/stats-card.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; | ||
import type { IconProps } from "@/components/ui/icons"; | ||
|
||
type StatsCardProps = { | ||
title: string; | ||
value: string | number; | ||
subText: string; | ||
Icon: React.ComponentType<IconProps>; | ||
}; | ||
|
||
export function StatsCard({ title, value, Icon, subText }: StatsCardProps) { | ||
return ( | ||
<Card> | ||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> | ||
<CardTitle className="text-sm font-medium">{title}</CardTitle> | ||
<Icon className="h-4 w-4 text-muted-foreground" /> | ||
</CardHeader> | ||
<CardContent> | ||
<div className="text-2xl font-bold">{value}</div> | ||
<p className="text-xs text-muted-foreground">{subText}</p> | ||
</CardContent> | ||
</Card> | ||
); | ||
} |
49 changes: 49 additions & 0 deletions
49
starterkits/saas/src/app/(app)/admin/dashboard/_components/subs-chart.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
"use client"; | ||
|
||
import { LineChart } from "@/components/charts"; | ||
import { | ||
Card, | ||
CardContent, | ||
CardDescription, | ||
CardHeader, | ||
CardTitle, | ||
} from "@/components/ui/card"; | ||
import { thousandToK } from "@/lib/utils"; | ||
|
||
type SubsChartProps = { | ||
data: { | ||
Date: string; | ||
SubsCount: number; | ||
}[]; | ||
}; | ||
|
||
export function SubsChart({ data }: SubsChartProps) { | ||
return ( | ||
<Card> | ||
<CardHeader> | ||
<CardTitle>Subscription Analytics</CardTitle> | ||
<CardDescription> | ||
Count of subscriptions each month for last 6 months | ||
</CardDescription> | ||
</CardHeader> | ||
<CardContent> | ||
<LineChart | ||
data={data} | ||
xAxisDataKey="Date" | ||
yAxisDataKey="SubsCount" | ||
lineDataKeys={["SubsCount"]} | ||
lineProps={[{ stroke: "hsl(var(--primary))" }]} | ||
yAxisProps={{ | ||
tickFormatter: (value) => { | ||
if (value >= 10000) { | ||
return `${thousandToK(Number(value)).toFixed(1)}k`; | ||
} else { | ||
return value as string; | ||
} | ||
}, | ||
}} | ||
/> | ||
</CardContent> | ||
</Card> | ||
); | ||
} |
49 changes: 49 additions & 0 deletions
49
starterkits/saas/src/app/(app)/admin/dashboard/_components/users-chart.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
"use client"; | ||
|
||
import { LineChart } from "@/components/charts"; | ||
import { | ||
Card, | ||
CardContent, | ||
CardDescription, | ||
CardHeader, | ||
CardTitle, | ||
} from "@/components/ui/card"; | ||
import { thousandToK } from "@/lib/utils"; | ||
|
||
type UsersChartProps = { | ||
data: { | ||
Date: string; | ||
UsersCount: number; | ||
}[]; | ||
}; | ||
|
||
export function UsersChart({ data }: UsersChartProps) { | ||
return ( | ||
<Card> | ||
<CardHeader> | ||
<CardTitle>Users Analytics</CardTitle> | ||
<CardDescription> | ||
Count of users joined each month for last 6 months | ||
</CardDescription> | ||
</CardHeader> | ||
<CardContent> | ||
<LineChart | ||
data={data} | ||
xAxisDataKey="Date" | ||
yAxisDataKey="UsersCount" | ||
lineDataKeys={["UsersCount"]} | ||
lineProps={[{ stroke: "hsl(var(--primary))" }]} | ||
yAxisProps={{ | ||
tickFormatter: (value) => { | ||
if (value >= 10000) { | ||
return `${thousandToK(Number(value)).toFixed(1)}k`; | ||
} else { | ||
return value as string; | ||
} | ||
}, | ||
}} | ||
/> | ||
</CardContent> | ||
</Card> | ||
); | ||
} |
10 changes: 10 additions & 0 deletions
10
starterkits/saas/src/app/(app)/admin/dashboard/_constants/page-config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* This file contains the page configuration for the users page. | ||
* This is used to generate the page title and description. | ||
*/ | ||
|
||
export const adminDashConfig = { | ||
title: "Admin Dashboard", | ||
description: | ||
"View insights and analytics to monitor your app's performance and user behavior.", | ||
} as const; |
14 changes: 14 additions & 0 deletions
14
starterkits/saas/src/app/(app)/admin/dashboard/loading.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { AppPageLoading } from "@/app/(app)/_components/page-loading"; | ||
import { adminDashConfig } from "@/app/(app)/admin/dashboard/_constants/page-config"; | ||
import { Skeleton } from "@/components/ui/skeleton"; | ||
|
||
export default function AdminFeedbackPageLoading() { | ||
return ( | ||
<AppPageLoading | ||
title={adminDashConfig.title} | ||
description={adminDashConfig.description} | ||
> | ||
<Skeleton className="h-96 w-full" /> | ||
</AppPageLoading> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,100 @@ | ||
import { getUser } from "@/server/auth"; | ||
import { AppPageShell } from "@/app/(app)/_components/page-shell"; | ||
import { RevenueChart } from "@/app/(app)/admin/dashboard/_components/revenue-chart"; | ||
import { StatsCard } from "@/app/(app)/admin/dashboard/_components/stats-card"; | ||
import { SubsChart } from "@/app/(app)/admin/dashboard/_components/subs-chart"; | ||
import { UsersChart } from "@/app/(app)/admin/dashboard/_components/users-chart"; | ||
import { adminDashConfig } from "@/app/(app)/admin/dashboard/_constants/page-config"; | ||
import { buttonVariants } from "@/components/ui/button"; | ||
import { siteUrls } from "@/config/urls"; | ||
import { cn } from "@/lib/utils"; | ||
import { | ||
getRevenueCount, | ||
getSubscriptionsCount, | ||
} from "@/server/actions/subscription/query"; | ||
import { getUsersCount } from "@/server/actions/user/queries"; | ||
import { | ||
DollarSignIcon, | ||
UserRoundCheckIcon, | ||
UserRoundPlusIcon, | ||
Users2Icon, | ||
} from "lucide-react"; | ||
import Link from "next/link"; | ||
|
||
export default async function AdminDashPage() { | ||
const user = await getUser(); | ||
const usersCountData = await getUsersCount(); | ||
const usersChartData = usersCountData.usersCountByMonth; | ||
|
||
const subscriptionsCountData = await getSubscriptionsCount({}); | ||
|
||
const activeSubscriptionsCountData = await getSubscriptionsCount({ | ||
status: "active", | ||
}); | ||
const subsChartData = subscriptionsCountData.subscriptionsCountByMonth; | ||
|
||
const revenueCountData = await getRevenueCount(); | ||
const revenueChartData = revenueCountData.revenueCountByMonth; | ||
|
||
return ( | ||
<div> | ||
<h1>Admin Dashboard</h1> | ||
<p>Welcome {user?.name}</p> | ||
<p>{user?.isNewUser ? "Yes" : "No"}</p> | ||
</div> | ||
<AppPageShell | ||
title={adminDashConfig.title} | ||
description={adminDashConfig.description} | ||
> | ||
<div className="grid w-full gap-8"> | ||
<p className="text-sm"> | ||
This a simple dashboard with Analytics, to see detailed | ||
Analytics go to{" "} | ||
<Link | ||
href={siteUrls.admin.analytics} | ||
className={cn( | ||
buttonVariants({ | ||
variant: "link", | ||
size: "default", | ||
className: "px-0 underline", | ||
}), | ||
)} | ||
> | ||
PostHog Dashboard | ||
</Link> | ||
</p> | ||
|
||
<div className="grid grid-cols-4 gap-4"> | ||
<StatsCard | ||
title="Users" | ||
value={String(usersCountData.totalCount)} | ||
Icon={Users2Icon} | ||
subText="Total users joined" | ||
/> | ||
|
||
<StatsCard | ||
title="Revenue" | ||
value={revenueCountData.totalRevenue} | ||
Icon={DollarSignIcon} | ||
subText="Total revenue generated" | ||
/> | ||
|
||
<StatsCard | ||
title="Subscriptions" | ||
value={String(subscriptionsCountData.totalCount)} | ||
Icon={UserRoundPlusIcon} | ||
subText="Total subscriptions made" | ||
/> | ||
|
||
<StatsCard | ||
title="Active Subscriptions" | ||
value={String(activeSubscriptionsCountData.totalCount)} | ||
Icon={UserRoundCheckIcon} | ||
subText="Current active subscriptions" | ||
/> | ||
</div> | ||
|
||
<div className="grid grid-cols-2 gap-4"> | ||
<UsersChart data={usersChartData} /> | ||
|
||
<SubsChart data={subsChartData} /> | ||
|
||
<RevenueChart data={revenueChartData} /> | ||
</div> | ||
</div> | ||
</AppPageShell> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.