import { Card, Text, Group, Badge, Stack, Tooltip, ActionIcon } from "@mantine/core"; import GroupIcon from "@mui/icons-material/Group"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; import { useTranslation } from "react-i18next"; import type { BillingStatus } from "@app/services/saasBillingService"; import { BILLING_CONFIG, getFormattedOveragePrice } from "@app/config/billing"; import { Z_INDEX_OVER_CONFIG_MODAL } from "@app/styles/zIndex"; interface TeamData { teamId: number; name: string; isPersonal: boolean; isLeader: boolean; seatsUsed: number; } interface ActiveSubscriptionCardProps { tier: BillingStatus["tier"]; subscription: BillingStatus["subscription"]; usage: BillingStatus["meterUsage"]; isTrialing: boolean; price?: number; currency?: string; currentTeam?: TeamData | null; isTeamLeader?: boolean; isPersonalTeam?: boolean; } export function ActiveSubscriptionCard({ tier, subscription, usage, isTrialing, price, currency, currentTeam, isTeamLeader = false, isPersonalTeam = true, }: ActiveSubscriptionCardProps) { const { t } = useTranslation(); // Format timestamp to readable date const formatDate = (timestamp: number): string => { return new Date(timestamp * 1000).toLocaleDateString(undefined, { year: "numeric", month: "long", day: "numeric", }); }; // Get tier display name const getTierName = (): string => { switch (tier) { case "free": return t("settings.planBilling.tier.free", "Free Plan"); case "team": return t("settings.planBilling.tier.team", "Team Plan"); case "enterprise": return t("settings.planBilling.tier.enterprise", "Enterprise Plan"); default: return tier; } }; // Get price display const getPriceDisplay = (): string => { if (tier === "free") { return "$0/month"; } // Use actual price from Stripe if available if (price !== undefined && currency) { return `${currency}${price}/month`; } // Fallback to default pricing return "$10/month"; }; // Get description const getDescription = (): string => { if (tier === "free") { return t("settings.planBilling.tier.freeDescription", "50 credits per month"); } return t( "settings.planBilling.tier.teamDescription", "500 credits/month included, automatic overage billing for uninterrupted service", ); }; // Format overage cost const formatOverageCost = (cents: number, credits: number): string => { return t("settings.planBilling.billing.overageCost", { amount: `$${(cents / 100).toFixed(2)}`, credits, defaultValue: `Current overage cost: $${(cents / 100).toFixed(2)} (${credits} credits)`, }); }; // Pro/Team card if (tier === "team" || tier === "enterprise") { return ( {/* Left side: Name, badges, description */}
{!isPersonalTeam && isTeamLeader ? t("settings.planBilling.tier.team", "Team Plan") : getTierName()} {!isPersonalTeam && ( }> {t("settings.planBilling.tier.teamBadge", "Team")} )} {t("settings.planBilling.tier.teamTooltipCredits", { credits: BILLING_CONFIG.INCLUDED_CREDITS_PER_MONTH, defaultValue: `Team plan includes ${BILLING_CONFIG.INCLUDED_CREDITS_PER_MONTH} credits/month.`, })} {t("settings.planBilling.tier.teamTooltipOverage", { price: getFormattedOveragePrice(), defaultValue: `Automatic overage billing at ${getFormattedOveragePrice()}/credit ensures uninterrupted service.`, })} {t( "settings.planBilling.tier.teamTooltipFineprint", "Only pay for what you use beyond included credits.", )}
} multiline withArrow position="right" zIndex={Z_INDEX_OVER_CONFIG_MODAL} > {isTrialing && ( {t("settings.planBilling.status.trial", "Trial")} )}
{!isPersonalTeam && !isTeamLeader && ( {t("settings.planBilling.team.managedByTeam", "Managed by team")} )} {!isPersonalTeam && isTeamLeader && currentTeam && ( {t("settings.planBilling.team.memberCount", "{{count}} team members", { count: currentTeam.seatsUsed })} )} {getDescription()} {/* Show overage cost if applicable */} {usage && usage.currentPeriodCredits > 0 && ( {formatOverageCost(usage.estimatedCost, usage.currentPeriodCredits)} )} {/* Right side: Price */}
{!isPersonalTeam && !isTeamLeader ? ( {t("settings.planBilling.team.managedByTeam", "Managed by team")} ) : ( {getPriceDisplay()} )}
{/* Next billing date at bottom */} {subscription?.currentPeriodEnd && ( {t("settings.planBilling.billing.nextBillingDate", "Next billing date:")}{" "} {formatDate(subscription.currentPeriodEnd)} )}
); } // Free plan card return (
{getTierName()} {getDescription()}
{getPriceDisplay()}
); }