From 8dd1d1bb7c18cad50db1020a0212f81e0c5c6736 Mon Sep 17 00:00:00 2001 From: Matthias Meister Date: Fri, 3 Apr 2026 18:53:21 +0200 Subject: [PATCH] refactor(billing): centralize tier credits and align topup UI --- components/billing/topup-panel.tsx | 54 ++---------------------- components/dashboard/credit-overview.tsx | 18 ++------ 2 files changed, 6 insertions(+), 66 deletions(-) diff --git a/components/billing/topup-panel.tsx b/components/billing/topup-panel.tsx index 217f07c..254fe97 100644 --- a/components/billing/topup-panel.tsx +++ b/components/billing/topup-panel.tsx @@ -1,22 +1,13 @@ "use client"; -import { useState } from "react"; import { useTranslations } from "next-intl"; -import { CreditCard, Zap } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { Slider } from "@/components/ui/slider"; import { authClient } from "@/lib/auth-client"; import { TOPUP_PRODUCTS } from "@/lib/polar-products"; -import { calculateCustomTopup } from "@/lib/topup-calculator"; import { toast } from "@/lib/toast"; -const CUSTOM_TOPUP_PRODUCT_ID = "POLAR_PRODUCT_ID_TOPUP_CUSTOM"; - export function TopupPanel() { const t = useTranslations('toasts'); - const [customAmount, setCustomAmount] = useState(20); - const { credits, bonusRate } = calculateCustomTopup(customAmount); async function handleTopup(polarProductId: string) { toast.info( @@ -47,48 +38,9 @@ export function TopupPanel() { -
-

Custom amount

-
- EUR {customAmount} -
-

- {credits.toLocaleString("de-DE")} Cr -

- {bonusRate > 0 && ( -

- - +{Math.round(bonusRate * 100)}% bonus -

- )} -
-
- - setCustomAmount(value)} - /> - -
- EUR 5 - EUR 200 -
- - - -

- Larger amounts include a bonus. Top-ups are always available, even on free plan. -

-
+

+ Angezeigt werden nur kaufbare Top-up Pakete aus der serverseitigen Polar-Produktkonfiguration. +

); } diff --git a/components/dashboard/credit-overview.tsx b/components/dashboard/credit-overview.tsx index b877372..c7c31cd 100644 --- a/components/dashboard/credit-overview.tsx +++ b/components/dashboard/credit-overview.tsx @@ -11,27 +11,15 @@ import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Progress } from "@/components/ui/progress"; import { api } from "@/convex/_generated/api"; +import { normalizeTier, TIER_MONTHLY_CREDITS } from "@/lib/polar-products"; import { cn } from "@/lib/utils"; import { toast } from "@/lib/toast"; -// --------------------------------------------------------------------------- -// Tier-Config — monatliches Credit-Kontingent pro Tier (in Cent) -// --------------------------------------------------------------------------- - -const TIER_MONTHLY_CREDITS: Record = { - free: 50, - starter: 400, - pro: 3300, - max: 6700, - business: 6700, -}; - const TIER_BADGE_STYLES: Record = { free: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400", starter: "bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-400", pro: "bg-purple-100 text-purple-700 dark:bg-purple-900/40 dark:text-purple-400", max: "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-400", - business: "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-400", }; // --------------------------------------------------------------------------- @@ -90,8 +78,8 @@ export function CreditOverview() { } // ── Computed Values ──────────────────────────────────────────────────── - const tier = subscription.tier; - const monthlyCredits = TIER_MONTHLY_CREDITS[tier] ?? 0; + const tier = normalizeTier(subscription.tier); + const monthlyCredits = TIER_MONTHLY_CREDITS[tier]; const usagePercent = monthlyCredits > 0 ? Math.min(100, Math.round((usageStats.monthlyUsage / monthlyCredits) * 100)) : 0;