"use client"; import { useState } from "react"; import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../../../../../shadcnui"; import { formatCurrency, formatDate } from "../../../components/utils"; import { StripeCustomerService } from "../../../stripe-customer"; import { StripePriceInterface } from "../../../stripe-price/data/stripe-price.interface"; import { StripeSubscriptionInterface, StripeSubscriptionService, SubscriptionStatus } from "../../data"; import { CancelSubscriptionDialog } from "../forms/CancelSubscriptionDialog"; import { SubscriptionStatusBadge } from "../widgets/SubscriptionStatusBadge"; /** * Formats the plan name from price data. * Format: "Product Name - Nickname (Interval)" e.g., "Only 35 - Pro (Monthly)" */ function formatPlanName(price: StripePriceInterface | undefined): string { if (!price) return "N/A"; const productName = price.product?.name || ""; const nickname = price.nickname || ""; // Format interval: "month" -> "Monthly", "year" -> "Yearly", etc. let interval = ""; if (price.recurring?.interval) { const intervalMap: Record = { day: "Daily", week: "Weekly", month: "Monthly", year: "Yearly", }; interval = intervalMap[price.recurring.interval] || price.recurring.interval; } // Build the plan label: "Product - Nickname" or just "Product" const parts = [productName, nickname].filter(Boolean); const planLabel = parts.join(" - "); // Add interval in parentheses if available return interval ? `${planLabel} (${interval})` : planLabel || "N/A"; } /** * Formats the billing amount from price data. */ function formatBillingAmount(price: StripePriceInterface | undefined): string { if (!price?.unitAmount) return "N/A"; return formatCurrency(price.unitAmount, price.currency); } type SubscriptionDetailsProps = { subscription: StripeSubscriptionInterface; open: boolean; onOpenChange: (open: boolean) => void; onSubscriptionChange: () => void; onChangePlan?: (subscription: StripeSubscriptionInterface) => void; }; export function SubscriptionDetails({ subscription, open, onOpenChange, onSubscriptionChange, onChangePlan, }: SubscriptionDetailsProps) { const [showCancel, setShowCancel] = useState(false); const [isProcessing, setIsProcessing] = useState(false); const handlePause = async () => { setIsProcessing(true); try { await StripeSubscriptionService.pauseSubscription({ subscriptionId: subscription.id }); onSubscriptionChange(); } catch (error) { console.error("[SubscriptionDetails] Failed to pause subscription:", error); } finally { setIsProcessing(false); } }; const handleResume = async () => { setIsProcessing(true); try { await StripeSubscriptionService.resumeSubscription({ subscriptionId: subscription.id }); onSubscriptionChange(); } catch (error) { console.error("[SubscriptionDetails] Failed to resume subscription:", error); } finally { setIsProcessing(false); } }; const handleManageViaPortal = async () => { try { const { url } = await StripeCustomerService.createPortalSession(); window.open(url, "_blank"); } catch (error) { console.error("[SubscriptionDetails] Failed to create portal session:", error); } }; const canPause = subscription.status === SubscriptionStatus.ACTIVE; const canResume = subscription.status === SubscriptionStatus.PAUSED; const canCancel = subscription.status === SubscriptionStatus.ACTIVE || subscription.status === SubscriptionStatus.TRIALING || subscription.status === SubscriptionStatus.PAUSED; return ( <> Subscription Details View and manage your subscription
{/* Status */}
Status:
{/* Plan Info */}
Plan: {formatPlanName(subscription.price)}
Billing Amount: {formatBillingAmount(subscription.price)}
{/* Current Period */}
Current Period: {formatDate(subscription.currentPeriodStart)} - {formatDate(subscription.currentPeriodEnd)}
{/* Trial Info */} {subscription.trialEnd && (
Trial Ends: {formatDate(subscription.trialEnd)}
)} {/* Cancellation Warning */} {subscription.cancelAtPeriodEnd && (

This subscription will be canceled at the end of the current period on{" "} {formatDate(subscription.currentPeriodEnd)}.

)} {/* Action Buttons */}
{onChangePlan && ( )} {canPause && ( )} {canResume && ( )} {canCancel && ( )}
{/* Cancel Subscription Dialog */} {showCancel && ( { onSubscriptionChange(); setShowCancel(false); }} /> )} ); }