From b5114dfe2233fd1148167c34226464a5ea41a590 Mon Sep 17 00:00:00 2001 From: MananTank Date: Mon, 23 Jun 2025 23:02:36 +0000 Subject: [PATCH] [TOOL-4858] Update Team Usage Overview page UI for free plan (#7423) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ## PR-Codex overview This PR focuses on improving the handling of team usage and upsell features in the dashboard. It introduces new components and logic to display upsell content based on the team's billing plan. ### Detailed summary - Updated import paths for `getTeamBySlug` and `UpsellWrapper`. - Added `UpsellContent` component to display upsell information. - Implemented logic to show upsell content if the team is on a "free" plan. - Refactored the `UpsellWrapper` to include `UpsellContent`. - Enhanced rendering of benefits in `UpsellContent`. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` ## Summary by CodeRabbit - **Refactor** - Improved code structure by extracting upsell card UI into a dedicated component, resulting in cleaner and more maintainable code. - Updated import paths for consistency and clarity. - **Style** - Adjusted layout classes for better visual alignment of upsell content. - **Bug Fixes** - Unified error handling for usage page, ensuring a consistent message for all error scenarios. Free plan users now see a clear upgrade prompt. --- .../@/components/blocks/upsell-wrapper.tsx | 173 ++++++++++-------- .../[team_slug]/(team)/~/audit-log/layout.tsx | 4 +- .../team/[team_slug]/(team)/~/usage/page.tsx | 37 ++-- 3 files changed, 123 insertions(+), 91 deletions(-) diff --git a/apps/dashboard/src/@/components/blocks/upsell-wrapper.tsx b/apps/dashboard/src/@/components/blocks/upsell-wrapper.tsx index 943589c7596..31e71e3fb32 100644 --- a/apps/dashboard/src/@/components/blocks/upsell-wrapper.tsx +++ b/apps/dashboard/src/@/components/blocks/upsell-wrapper.tsx @@ -47,7 +47,7 @@ export function UpsellWrapper({ } return ( -
+
{/* Background content - blurred and non-interactive */}
@@ -59,84 +59,109 @@ export function UpsellWrapper({
{/* Upsell content */} -
- - -
- -
+
+ +
+
+ ); +} -
- - - Unlock {featureName} - - - {featureDescription} - -
- +export function UpsellContent(props: { + teamSlug: string; + featureName: string; + featureDescription: string; + requiredPlan: Team["billingPlan"]; + currentPlan: Team["billingPlan"]; + benefits?: { + description: string; + status: "available" | "soon"; + }[]; +}) { + return ( + + +
+ +
- - {benefits.length > 0 && ( -
-

- What you'll get: -

-
- {benefits.map((benefit) => ( -
-
- -
- {benefit.description} - {benefit.status === "soon" && ( - - Coming Soon - - )} -
- ))} -
-
- )} +
+ +
+ + Unlock {props.featureName} + + + {props.featureDescription} + +
+
+
-
- - +
+ +
+ {benefit.description} + {benefit.status === "soon" && ( + + Coming Soon + + )} +
+ ))}
+
+ )} -
-

- You are currently on the{" "} - {currentPlan}{" "} - plan. -

-
- - -
-
+
+ + +
+ +
+

+ You are currently on the{" "} + {props.currentPlan}{" "} + plan. +

+
+ + ); } diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/audit-log/layout.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/audit-log/layout.tsx index b3295bf6114..16f58d38a37 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/audit-log/layout.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/audit-log/layout.tsx @@ -1,6 +1,6 @@ import { redirect } from "next/navigation"; -import { getTeamBySlug } from "../../../../../../../@/api/team"; -import { UpsellWrapper } from "../../../../../../../@/components/blocks/upsell-wrapper"; +import { getTeamBySlug } from "@/api/team"; +import { UpsellWrapper } from "@/components/blocks/upsell-wrapper"; export default async function Layout(props: { children: React.ReactNode; diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/page.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/page.tsx index 99bcdb3d59a..262d5449e70 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/page.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/page.tsx @@ -3,6 +3,7 @@ import { InfoIcon } from "lucide-react"; import { redirect } from "next/navigation"; import { getTeamBySlug } from "@/api/team"; import { getBilledUsage } from "@/api/usage/billing-preview"; +import { UpsellContent } from "@/components/blocks/upsell-wrapper"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Card, @@ -12,6 +13,7 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { getValidTeamPlan } from "@/utils/getValidTeamPlan"; import { getValidAccount } from "../../../../../account/settings/getAccount"; import { formatPrice, @@ -34,23 +36,28 @@ export default async function Page(props: { } const usagePreview = await getBilledUsage(team.slug); + const validPlan = getValidTeamPlan(team); + + if (validPlan === "free") { + return ( +
+ +
+ ); + } if (usagePreview.status === "error") { - switch (usagePreview.reason) { - case "free_plan": - return ( -
- You are on a free plan. Please upgrade to a paid plan to view your - usage. -
- ); - default: - return ( -
- Something went wrong. Please try again later. -
- ); - } + return ( +
+ Something went wrong. Please try again later. +
+ ); } const grandTotalCents = usagePreview.data.result.reduce((total, category) => {