@stackframe/react 2.8.67 → 2.8.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/components-page/account-settings/payments/payments-panel.js +10 -10
  2. package/dist/components-page/account-settings/payments/payments-panel.js.map +1 -1
  3. package/dist/esm/components-page/account-settings/payments/payments-panel.js +10 -10
  4. package/dist/esm/components-page/account-settings/payments/payments-panel.js.map +1 -1
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +127 -1
  7. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  8. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +84 -7
  9. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  10. package/dist/esm/lib/stack-app/apps/implementations/common.js +7 -1
  11. package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
  12. package/dist/esm/lib/stack-app/apps/implementations/event-tracker.js +221 -0
  13. package/dist/esm/lib/stack-app/apps/implementations/event-tracker.js.map +1 -0
  14. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js +33 -4
  15. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  16. package/dist/esm/lib/stack-app/apps/implementations/session-replay.js +221 -0
  17. package/dist/esm/lib/stack-app/apps/implementations/session-replay.js.map +1 -0
  18. package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  19. package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  20. package/dist/esm/lib/stack-app/index.js.map +1 -1
  21. package/dist/esm/lib/stack-app/projects/index.js.map +1 -1
  22. package/dist/esm/lib/stack-app/session-replays/index.js +1 -0
  23. package/dist/esm/lib/stack-app/session-replays/index.js.map +1 -0
  24. package/dist/esm/lib/stack-app/teams/index.js.map +1 -1
  25. package/dist/esm/lib/stack-app/users/index.js.map +1 -1
  26. package/dist/index.d.mts +240 -17
  27. package/dist/index.d.ts +240 -17
  28. package/dist/index.js.map +1 -1
  29. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +127 -1
  30. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  31. package/dist/lib/stack-app/apps/implementations/client-app-impl.js +83 -6
  32. package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  33. package/dist/lib/stack-app/apps/implementations/common.js +9 -1
  34. package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
  35. package/dist/lib/stack-app/apps/implementations/event-tracker.js +246 -0
  36. package/dist/lib/stack-app/apps/implementations/event-tracker.js.map +1 -0
  37. package/dist/lib/stack-app/apps/implementations/server-app-impl.js +33 -4
  38. package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  39. package/dist/lib/stack-app/apps/implementations/session-replay.js +262 -0
  40. package/dist/lib/stack-app/apps/implementations/session-replay.js.map +1 -0
  41. package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  42. package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  43. package/dist/lib/stack-app/customers/index.js.map +1 -1
  44. package/dist/lib/stack-app/email/index.js.map +1 -1
  45. package/dist/lib/stack-app/index.js.map +1 -1
  46. package/dist/lib/stack-app/projects/index.js.map +1 -1
  47. package/dist/lib/stack-app/session-replays/index.js +19 -0
  48. package/dist/lib/stack-app/session-replays/index.js.map +1 -0
  49. package/dist/lib/stack-app/teams/index.js.map +1 -1
  50. package/dist/lib/stack-app/users/index.js.map +1 -1
  51. package/package.json +4 -3
@@ -192,7 +192,7 @@ function RealPaymentsPanel(props) {
192
192
  const [paymentDialogOpen, setPaymentDialogOpen] = (0, import_react.useState)(false);
193
193
  const [setupIntentClientSecret, setSetupIntentClientSecret] = (0, import_react.useState)(null);
194
194
  const [setupIntentStripeAccountId, setSetupIntentStripeAccountId] = (0, import_react.useState)(null);
195
- const [cancelProductId, setCancelProductId] = (0, import_react.useState)(null);
195
+ const [cancelTarget, setCancelTarget] = (0, import_react.useState)(null);
196
196
  const [switchFromProductId, setSwitchFromProductId] = (0, import_react.useState)(null);
197
197
  const [switchToProductId, setSwitchToProductId] = (0, import_react.useState)(null);
198
198
  const stripePromise = (0, import_react.useMemo)(() => {
@@ -294,7 +294,7 @@ ${error}`);
294
294
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-3", children: productsForCustomerType.map((product, index) => {
295
295
  const quantitySuffix = product.quantity !== 1 ? ` \xD7${product.quantity}` : "";
296
296
  const isSubscription = product.type === "subscription";
297
- const isCancelable = isSubscription && !!product.id && !!product.subscription?.isCancelable;
297
+ const isCancelable = isSubscription && !!product.subscription?.isCancelable;
298
298
  const canSwitchPlans = isSubscription && defaultPaymentMethod && !!product.id && (product.switchOptions?.length ?? 0) > 0;
299
299
  const renewsAt = isSubscription ? product.subscription?.currentPeriodEnd ?? null : null;
300
300
  const subtitle = product.type === "one_time" ? t("One-time purchase") : renewsAt ? `${t("Renews on")} ${new Intl.DateTimeFormat(void 0, { year: "numeric", month: "short", day: "numeric" }).format(renewsAt)}` : t("Subscription");
@@ -321,7 +321,7 @@ ${error}`);
321
321
  {
322
322
  variant: "secondary",
323
323
  color: "neutral",
324
- onClick: () => setCancelProductId(product.id),
324
+ onClick: () => setCancelTarget({ productId: product.id ?? "_inline", subscriptionId: product.subscription?.subscriptionId ?? void 0 }),
325
325
  children: t("Cancel subscription")
326
326
  }
327
327
  )
@@ -331,9 +331,9 @@ ${error}`);
331
331
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
332
332
  import_stack_ui.ActionDialog,
333
333
  {
334
- open: cancelProductId !== null,
334
+ open: cancelTarget !== null,
335
335
  onOpenChange: (open) => {
336
- if (!open) setCancelProductId(null);
336
+ if (!open) setCancelTarget(null);
337
337
  },
338
338
  title: t("Cancel subscription"),
339
339
  description: t("Canceling will stop future renewals for this subscription."),
@@ -342,14 +342,14 @@ ${error}`);
342
342
  okButton: {
343
343
  label: t("Cancel subscription"),
344
344
  onClick: async () => {
345
- const productId = cancelProductId;
346
- if (!productId) return;
345
+ if (!cancelTarget) return;
346
+ const { productId, subscriptionId } = cancelTarget;
347
347
  if (props.customerType === "team") {
348
- await stackApp.cancelSubscription({ teamId: props.customer.id, productId });
348
+ await stackApp.cancelSubscription({ teamId: props.customer.id, productId, subscriptionId });
349
349
  } else {
350
- await stackApp.cancelSubscription({ productId });
350
+ await stackApp.cancelSubscription({ productId, subscriptionId });
351
351
  }
352
- setCancelProductId(null);
352
+ setCancelTarget(null);
353
353
  }
354
354
  }
355
355
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components-page/account-settings/payments/payments-panel.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { KnownErrors } from \"@stackframe/stack-shared\";\nimport { runAsynchronously } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { ActionDialog, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, Typography } from \"@stackframe/stack-ui\";\nimport { CardElement, Elements, useElements, useStripe } from \"@stripe/react-stripe-js\";\nimport { loadStripe } from \"@stripe/stripe-js\";\nimport { useMemo, useState } from \"react\";\nimport { useStackApp } from \"../../..\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { Section } from \"../section\";\nimport { Result } from \"@stackframe/stack-shared/dist/utils/results\";\nimport type { CustomerInvoiceStatus, CustomerInvoicesList, CustomerInvoicesListOptions } from \"../../../lib/stack-app/customers\";\n\ntype PaymentMethodSummary = {\n id: string,\n brand: string | null,\n last4: string | null,\n exp_month: number | null,\n exp_year: number | null,\n} | null;\n\nfunction formatPaymentMethod(pm: NonNullable<PaymentMethodSummary>) {\n const details = [\n pm.brand ? pm.brand.toUpperCase() : null,\n pm.last4 ? `•••• ${pm.last4}` : null,\n pm.exp_month && pm.exp_year ? `exp ${pm.exp_month}/${pm.exp_year}` : null,\n ].filter(Boolean);\n return details.join(\" · \");\n}\n\nconst formatInvoiceStatus = (status: CustomerInvoiceStatus, t: (value: string) => string) => {\n if (!status) {\n return t(\"Unknown\");\n }\n switch (status) {\n case \"draft\": {\n return t(\"Draft\");\n }\n case \"open\": {\n return t(\"Open\");\n }\n case \"paid\": {\n return t(\"Paid\");\n }\n case \"uncollectible\": {\n return t(\"Uncollectible\");\n }\n case \"void\": {\n return t(\"Void\");\n }\n default: {\n return t(\"Unknown\");\n }\n }\n};\n\nconst formatInvoiceAmount = (amountTotal: number | null | undefined, t: (value: string) => string) => {\n if (typeof amountTotal !== \"number\" || Number.isNaN(amountTotal)) {\n return t(\"Unknown\");\n }\n const normalized = amountTotal / 100;\n const formatted = new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(normalized);\n return `$${formatted}`;\n};\n\nconst formatInvoiceDate = (date: Date | null | undefined, t: (value: string) => string) => {\n if (!date || Number.isNaN(date.getTime())) {\n return t(\"Unknown\");\n }\n return new Intl.DateTimeFormat(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(date);\n};\n\ntype CustomerBilling = {\n hasCustomer: boolean,\n defaultPaymentMethod: PaymentMethodSummary,\n};\n\ntype CustomerPaymentMethodSetupIntent = {\n clientSecret: string,\n stripeAccountId: string,\n};\n\ntype CustomerLike = {\n id: string,\n useBilling: () => CustomerBilling,\n useProducts: () => Array<{\n id: string | null,\n quantity: number,\n displayName: string,\n customerType: \"user\" | \"team\" | \"custom\",\n type: \"one_time\" | \"subscription\",\n switchOptions?: Array<{\n productId: string,\n displayName: string,\n prices: Record<string, { interval?: [number, \"day\" | \"week\" | \"month\" | \"year\"] }>,\n }>,\n subscription: null | {\n currentPeriodEnd: Date | null,\n cancelAtPeriodEnd: boolean,\n isCancelable: boolean,\n },\n }>,\n useInvoices: (options?: CustomerInvoicesListOptions) => CustomerInvoicesList,\n createPaymentMethodSetupIntent: () => Promise<CustomerPaymentMethodSetupIntent>,\n setDefaultPaymentMethodFromSetupIntent: (setupIntentId: string) => Promise<PaymentMethodSummary>,\n switchSubscription: (options: { fromProductId: string, toProductId: string, priceId?: string, quantity?: number }) => Promise<void>,\n};\n\nfunction SetDefaultPaymentMethodForm(props: {\n clientSecret: string,\n onSetupIntentSucceeded: (setupIntentId: string) => Promise<void>,\n}) {\n const stripe = useStripe();\n const elements = useElements();\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const darkMode = \"color-scheme\" in document.documentElement.style && document.documentElement.style[\"color-scheme\"] === \"dark\";\n\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Typography className=\"font-medium\">Card details</Typography>\n <div className=\"rounded-md border border-input p-3\">\n <CardElement options={{ hidePostalCode: true, style: { base: { color: darkMode ? \"white\" : \"black\" } } }} />\n </div>\n </div>\n {errorMessage && (\n <Typography variant=\"secondary\" type=\"footnote\">\n {errorMessage}\n </Typography>\n )}\n <Button\n onClick={async () => {\n if (!stripe || !elements) {\n setErrorMessage(\"Stripe is still loading. Please try again.\");\n return;\n }\n const card = elements.getElement(CardElement);\n if (!card) {\n setErrorMessage(\"Card element not found.\");\n return;\n }\n\n const result = await stripe.confirmCardSetup(props.clientSecret, {\n payment_method: { card },\n });\n if (result.error) {\n setErrorMessage(result.error.message ?? \"Failed to save payment method.\");\n return;\n }\n if (!result.setupIntent.id) {\n setErrorMessage(\"No setup intent returned from Stripe.\");\n return;\n }\n await props.onSetupIntentSucceeded(result.setupIntent.id);\n }}\n >\n Save payment method\n </Button>\n </div>\n );\n}\n\nexport function PaymentsPanel(props: {\n title?: string,\n customer?: CustomerLike,\n customerType?: \"user\" | \"team\",\n mockMode?: boolean,\n}) {\n if (props.mockMode) {\n return <MockPaymentsPanel title={props.title} />;\n }\n if (!props.customer) {\n return null;\n }\n return <RealPaymentsPanel title={props.title} customer={props.customer} customerType={props.customerType ?? \"user\"} />;\n}\n\nfunction MockPaymentsPanel(props: { title?: string }) {\n const { t } = useTranslation();\n const defaultPaymentMethod: PaymentMethodSummary = {\n id: \"pm_mock\",\n brand: \"visa\",\n last4: \"4242\",\n exp_month: 12,\n exp_year: 2030,\n };\n\n return (\n <div className=\"space-y-4\">\n {props.title && <Typography className=\"font-medium\">{props.title}</Typography>}\n <Section\n title={t(\"Payment method\")}\n description={t(\"Manage the default payment method used for subscriptions and invoices.\")}\n >\n <Typography>{formatPaymentMethod(defaultPaymentMethod)}</Typography>\n <Button disabled>\n {t(\"Update payment method\")}\n </Button>\n </Section>\n\n <Section\n title={t(\"Active plans\")}\n description={t(\"View your active plans and purchases.\")}\n >\n <div className=\"space-y-3\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{t(\"Pro\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"Renews on\")} Jan 1, 2030</Typography>\n </div>\n <Button disabled variant=\"secondary\" color=\"neutral\">\n {t(\"Cancel subscription\")}\n </Button>\n </div>\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{t(\"Credits pack\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"One-time purchase\")}</Typography>\n </div>\n </div>\n </div>\n </Section>\n </div>\n );\n}\n\nfunction RealPaymentsPanel(props: { title?: string, customer: CustomerLike, customerType: \"user\" | \"team\" }) {\n const { t } = useTranslation();\n const stackApp = useStackApp();\n const billing = props.customer.useBilling();\n const defaultPaymentMethod = billing.defaultPaymentMethod;\n const products = props.customer.useProducts();\n const invoices = props.customer.useInvoices({ limit: 10 });\n const productsForCustomerType = products.filter(product => product.customerType === props.customerType);\n\n const [paymentDialogOpen, setPaymentDialogOpen] = useState(false);\n const [setupIntentClientSecret, setSetupIntentClientSecret] = useState<string | null>(null);\n const [setupIntentStripeAccountId, setSetupIntentStripeAccountId] = useState<string | null>(null);\n const [cancelProductId, setCancelProductId] = useState<string | null>(null);\n const [switchFromProductId, setSwitchFromProductId] = useState<string | null>(null);\n const [switchToProductId, setSwitchToProductId] = useState<string | null>(null);\n\n const stripePromise = useMemo(() => {\n if (!setupIntentStripeAccountId) return null;\n const publishableKey = process.env.NEXT_PUBLIC_STACK_STRIPE_PUBLISHABLE_KEY;\n if (!publishableKey) return null;\n return loadStripe(publishableKey, { stripeAccount: setupIntentStripeAccountId });\n }, [setupIntentStripeAccountId]);\n\n const handleAsyncError = (error: unknown) => {\n if (error instanceof KnownErrors.DefaultPaymentMethodRequired) {\n toast({\n title: t(\"No default payment method\"),\n description: t(\"Add a payment method before switching plans.\"),\n variant: \"destructive\",\n });\n return;\n }\n alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === \"development\" ? \"check the browser console for the full error.\" : \"report this to the developer.\"}\\n\\n${error}`);\n };\n\n const openPaymentDialog = () => {\n runAsynchronously(async () => {\n setPaymentDialogOpen(true);\n const res = await props.customer.createPaymentMethodSetupIntent();\n setSetupIntentClientSecret(res.clientSecret);\n setSetupIntentStripeAccountId(res.stripeAccountId);\n }, { onError: handleAsyncError });\n };\n\n const closePaymentDialog = () => {\n setPaymentDialogOpen(false);\n setSetupIntentClientSecret(null);\n setSetupIntentStripeAccountId(null);\n };\n\n const openSwitchDialog = (productId: string, firstOptionId: string | null) => {\n setSwitchFromProductId(productId);\n setSwitchToProductId(firstOptionId);\n };\n\n const closeSwitchDialog = () => {\n setSwitchFromProductId(null);\n setSwitchToProductId(null);\n };\n\n const switchSourceProduct = switchFromProductId\n ? productsForCustomerType.find((product) => product.id === switchFromProductId) ?? null\n : null;\n const switchOptions = switchSourceProduct?.switchOptions ?? [];\n const selectedSwitchOption = switchOptions.find((option) => option.productId === switchToProductId) ?? null;\n const selectedPriceId = selectedSwitchOption ? (Object.keys(selectedSwitchOption.prices)[0] ?? null) : null;\n\n return (\n <div className=\"space-y-4\">\n {props.title && <Typography className=\"font-medium\">{props.title}</Typography>}\n\n {defaultPaymentMethod && (\n <Section\n title={t(\"Payment method\")}\n description={t(\"Manage the default payment method used for subscriptions and invoices.\")}\n >\n <Typography>{formatPaymentMethod(defaultPaymentMethod)}</Typography>\n\n <Button onClick={openPaymentDialog}>\n {t(\"Update payment method\")}\n </Button>\n\n <ActionDialog\n open={paymentDialogOpen}\n onOpenChange={(open) => {\n if (!open) {\n closePaymentDialog();\n } else {\n setPaymentDialogOpen(true);\n }\n }}\n title={t(\"Update payment method\")}\n >\n {!setupIntentClientSecret || !setupIntentStripeAccountId || !stripePromise ? (\n <Skeleton className=\"h-10 w-full\" />\n ) : (\n <Elements\n stripe={stripePromise}\n options={{\n clientSecret: setupIntentClientSecret,\n }}\n >\n <SetDefaultPaymentMethodForm\n clientSecret={setupIntentClientSecret}\n onSetupIntentSucceeded={async (setupIntentId) => {\n await props.customer.setDefaultPaymentMethodFromSetupIntent(setupIntentId);\n closePaymentDialog();\n }}\n />\n </Elements>\n )}\n </ActionDialog>\n </Section>\n )}\n\n {productsForCustomerType.length > 0 && (\n <Section\n title={t(\"Active plans\")}\n description={t(\"View your active plans and purchases.\")}\n >\n <div className=\"space-y-3\">\n {productsForCustomerType.map((product, index) => {\n const quantitySuffix = product.quantity !== 1 ? ` ×${product.quantity}` : \"\";\n const isSubscription = product.type === \"subscription\";\n const isCancelable = isSubscription && !!product.id && !!product.subscription?.isCancelable;\n const canSwitchPlans = isSubscription && defaultPaymentMethod && !!product.id && (product.switchOptions?.length ?? 0) > 0;\n const renewsAt = isSubscription ? (product.subscription?.currentPeriodEnd ?? null) : null;\n\n const subtitle =\n product.type === \"one_time\"\n ? t(\"One-time purchase\")\n : renewsAt\n ? `${t(\"Renews on\")} ${new Intl.DateTimeFormat(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(renewsAt)}`\n : t(\"Subscription\");\n\n return (\n <div key={product.id ?? `${product.displayName}-${index}`} className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{product.displayName}{quantitySuffix}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{subtitle}</Typography>\n </div>\n\n <div className=\"flex flex-col items-end gap-2\">\n {canSwitchPlans && (\n <Button\n variant=\"secondary\"\n color=\"neutral\"\n onClick={() => openSwitchDialog(product.id!, product.switchOptions?.[0]?.productId ?? null)}\n >\n {t(\"Change plan\")}\n </Button>\n )}\n {isCancelable && (\n <Button\n variant=\"secondary\"\n color=\"neutral\"\n onClick={() => setCancelProductId(product.id)}\n >\n {t(\"Cancel subscription\")}\n </Button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n\n <ActionDialog\n open={cancelProductId !== null}\n onOpenChange={(open) => {\n if (!open) setCancelProductId(null);\n }}\n title={t(\"Cancel subscription\")}\n description={t(\"Canceling will stop future renewals for this subscription.\")}\n danger\n cancelButton\n okButton={{\n label: t(\"Cancel subscription\"),\n onClick: async () => {\n const productId = cancelProductId;\n if (!productId) return;\n if (props.customerType === \"team\") {\n await stackApp.cancelSubscription({ teamId: props.customer.id, productId });\n } else {\n await stackApp.cancelSubscription({ productId });\n }\n setCancelProductId(null);\n },\n }}\n />\n\n <ActionDialog\n open={switchFromProductId !== null}\n onOpenChange={(open) => {\n if (!open) closeSwitchDialog();\n }}\n title={t(\"Change plan\")}\n description={t(\"Select a new plan from the same product line.\")}\n cancelButton\n okButton={{\n label: t(\"Switch plan\"),\n onClick: async () => {\n const fromProductId = switchFromProductId;\n const toProductId = switchToProductId;\n if (!fromProductId || !toProductId) return;\n if (!selectedPriceId) return;\n const result = await Result.fromThrowingAsync(() => props.customer.switchSubscription({\n fromProductId,\n toProductId,\n priceId: selectedPriceId,\n }));\n if (result.status === \"error\") {\n handleAsyncError(result.error);\n return \"prevent-close\";\n }\n closeSwitchDialog();\n },\n props: {\n disabled: !switchFromProductId || !switchToProductId || !selectedPriceId,\n },\n }}\n >\n <div className=\"space-y-2\">\n {switchOptions.length === 0 ? (\n <Typography variant=\"secondary\" type=\"footnote\">\n {t(\"No other plans available for this subscription.\")}\n </Typography>\n ) : (\n <>\n <Typography type=\"footnote\">{t(\"Choose a plan\")}</Typography>\n <Select\n value={switchToProductId ?? undefined}\n onValueChange={(value) => setSwitchToProductId(value || null)}\n >\n <SelectTrigger className=\"w-full\">\n <SelectValue placeholder={t(\"Choose a plan\")} />\n </SelectTrigger>\n <SelectContent>\n {switchOptions.map((option: NonNullable<typeof switchOptions>[number]) => (\n <SelectItem key={option.productId} value={option.productId}>\n {option.displayName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </>\n )}\n </div>\n </ActionDialog>\n </Section>\n )\n }\n {invoices.length > 0 && (\n <>\n <Separator />\n <div className=\"space-y-2\">\n <div className=\"space-y-1\">\n <Typography className=\"font-medium\">{t(\"Invoices\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"Review past invoices and receipts.\")}</Typography>\n </div>\n <div className=\"border rounded-md\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[140px]\">{t(\"Date\")}</TableHead>\n <TableHead className=\"w-[120px]\">{t(\"Status\")}</TableHead>\n <TableHead className=\"w-[120px]\">{t(\"Amount\")}</TableHead>\n <TableHead className=\"w-[120px] text-right\">{t(\"Invoice\")}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {invoices.map((invoice, index) => {\n const createdAtTime = invoice.createdAt.getTime();\n const invoiceKey = Number.isNaN(createdAtTime) ? `invoice-${index}` : `invoice-${createdAtTime}-${index}`;\n return (\n <TableRow key={invoiceKey}>\n <TableCell>\n <Typography>{formatInvoiceDate(invoice.createdAt, t)}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{formatInvoiceStatus(invoice.status, t)}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{formatInvoiceAmount(invoice.amountTotal, t)}</Typography>\n </TableCell>\n <TableCell align=\"right\">\n {invoice.hostedInvoiceUrl ? (\n <Button asChild variant=\"secondary\" color=\"neutral\" size=\"sm\">\n <a href={invoice.hostedInvoiceUrl} target=\"_blank\" rel=\"noreferrer\">\n {t(\"View\")}\n </a>\n </Button>\n ) : (\n <Typography variant=\"secondary\" type=\"footnote\">\n {t(\"Unavailable\")}\n </Typography>\n )}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n </div>\n </>\n )}\n </div >\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,0BAA4B;AAC5B,sBAAkC;AAClC,sBAA2M;AAC3M,6BAA8D;AAC9D,uBAA2B;AAC3B,mBAAkC;AAClC,eAA4B;AAC5B,0BAA+B;AAC/B,qBAAwB;AACxB,qBAAuB;AA6GjB;AAlGN,SAAS,oBAAoB,IAAuC;AAClE,QAAM,UAAU;AAAA,IACd,GAAG,QAAQ,GAAG,MAAM,YAAY,IAAI;AAAA,IACpC,GAAG,QAAQ,4BAAQ,GAAG,KAAK,KAAK;AAAA,IAChC,GAAG,aAAa,GAAG,WAAW,OAAO,GAAG,SAAS,IAAI,GAAG,QAAQ,KAAK;AAAA,EACvE,EAAE,OAAO,OAAO;AAChB,SAAO,QAAQ,KAAK,QAAK;AAC3B;AAEA,IAAM,sBAAsB,CAAC,QAA+B,MAAiC;AAC3F,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,SAAS;AAAA,EACpB;AACA,UAAQ,QAAQ;AAAA,IACd,KAAK,SAAS;AACZ,aAAO,EAAE,OAAO;AAAA,IAClB;AAAA,IACA,KAAK,QAAQ;AACX,aAAO,EAAE,MAAM;AAAA,IACjB;AAAA,IACA,KAAK,QAAQ;AACX,aAAO,EAAE,MAAM;AAAA,IACjB;AAAA,IACA,KAAK,iBAAiB;AACpB,aAAO,EAAE,eAAe;AAAA,IAC1B;AAAA,IACA,KAAK,QAAQ;AACX,aAAO,EAAE,MAAM;AAAA,IACjB;AAAA,IACA,SAAS;AACP,aAAO,EAAE,SAAS;AAAA,IACpB;AAAA,EACF;AACF;AAEA,IAAM,sBAAsB,CAAC,aAAwC,MAAiC;AACpG,MAAI,OAAO,gBAAgB,YAAY,OAAO,MAAM,WAAW,GAAG;AAChE,WAAO,EAAE,SAAS;AAAA,EACpB;AACA,QAAM,aAAa,cAAc;AACjC,QAAM,YAAY,IAAI,KAAK,aAAa,QAAW,EAAE,uBAAuB,GAAG,uBAAuB,EAAE,CAAC,EAAE,OAAO,UAAU;AAC5H,SAAO,IAAI,SAAS;AACtB;AAEA,IAAM,oBAAoB,CAAC,MAA+B,MAAiC;AACzF,MAAI,CAAC,QAAQ,OAAO,MAAM,KAAK,QAAQ,CAAC,GAAG;AACzC,WAAO,EAAE,SAAS;AAAA,EACpB;AACA,SAAO,IAAI,KAAK,eAAe,QAAW,EAAE,MAAM,WAAW,OAAO,SAAS,KAAK,UAAU,CAAC,EAAE,OAAO,IAAI;AAC5G;AAsCA,SAAS,4BAA4B,OAGlC;AACD,QAAM,aAAS,kCAAU;AACzB,QAAM,eAAW,oCAAY;AAC7B,QAAM,CAAC,cAAc,eAAe,QAAI,uBAAwB,IAAI;AACpE,QAAM,WAAW,kBAAkB,SAAS,gBAAgB,SAAS,SAAS,gBAAgB,MAAM,cAAc,MAAM;AAExH,SACE,6CAAC,SAAI,WAAU,aACb;AAAA,iDAAC,SAAI,WAAU,aACb;AAAA,kDAAC,8BAAW,WAAU,eAAc,0BAAY;AAAA,MAChD,4CAAC,SAAI,WAAU,sCACb,sDAAC,sCAAY,SAAS,EAAE,gBAAgB,MAAM,OAAO,EAAE,MAAM,EAAE,OAAO,WAAW,UAAU,QAAQ,EAAE,EAAE,GAAG,GAC5G;AAAA,OACF;AAAA,IACC,gBACC,4CAAC,8BAAW,SAAQ,aAAY,MAAK,YAClC,wBACH;AAAA,IAEF;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,YAAY;AACnB,cAAI,CAAC,UAAU,CAAC,UAAU;AACxB,4BAAgB,4CAA4C;AAC5D;AAAA,UACF;AACA,gBAAM,OAAO,SAAS,WAAW,kCAAW;AAC5C,cAAI,CAAC,MAAM;AACT,4BAAgB,yBAAyB;AACzC;AAAA,UACF;AAEA,gBAAM,SAAS,MAAM,OAAO,iBAAiB,MAAM,cAAc;AAAA,YAC/D,gBAAgB,EAAE,KAAK;AAAA,UACzB,CAAC;AACD,cAAI,OAAO,OAAO;AAChB,4BAAgB,OAAO,MAAM,WAAW,gCAAgC;AACxE;AAAA,UACF;AACA,cAAI,CAAC,OAAO,YAAY,IAAI;AAC1B,4BAAgB,uCAAuC;AACvD;AAAA,UACF;AACA,gBAAM,MAAM,uBAAuB,OAAO,YAAY,EAAE;AAAA,QAC1D;AAAA,QACD;AAAA;AAAA,IAED;AAAA,KACF;AAEJ;AAEO,SAAS,cAAc,OAK3B;AACD,MAAI,MAAM,UAAU;AAClB,WAAO,4CAAC,qBAAkB,OAAO,MAAM,OAAO;AAAA,EAChD;AACA,MAAI,CAAC,MAAM,UAAU;AACnB,WAAO;AAAA,EACT;AACA,SAAO,4CAAC,qBAAkB,OAAO,MAAM,OAAO,UAAU,MAAM,UAAU,cAAc,MAAM,gBAAgB,QAAQ;AACtH;AAEA,SAAS,kBAAkB,OAA2B;AACpD,QAAM,EAAE,EAAE,QAAI,oCAAe;AAC7B,QAAM,uBAA6C;AAAA,IACjD,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAEA,SACE,6CAAC,SAAI,WAAU,aACZ;AAAA,UAAM,SAAS,4CAAC,8BAAW,WAAU,eAAe,gBAAM,OAAM;AAAA,IACjE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,gBAAgB;AAAA,QACzB,aAAa,EAAE,wEAAwE;AAAA,QAEvF;AAAA,sDAAC,8BAAY,8BAAoB,oBAAoB,GAAE;AAAA,UACvD,4CAAC,0BAAO,UAAQ,MACb,YAAE,uBAAuB,GAC5B;AAAA;AAAA;AAAA,IACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,cAAc;AAAA,QACvB,aAAa,EAAE,uCAAuC;AAAA,QAEtD,uDAAC,SAAI,WAAU,aACb;AAAA,uDAAC,SAAI,WAAU,0CACb;AAAA,yDAAC,SAAI,WAAU,WACb;AAAA,0DAAC,8BAAW,WAAU,YAAY,YAAE,KAAK,GAAE;AAAA,cAC3C,6CAAC,8BAAW,SAAQ,aAAY,MAAK,YAAY;AAAA,kBAAE,WAAW;AAAA,gBAAE;AAAA,iBAAY;AAAA,eAC9E;AAAA,YACA,4CAAC,0BAAO,UAAQ,MAAC,SAAQ,aAAY,OAAM,WACxC,YAAE,qBAAqB,GAC1B;AAAA,aACF;AAAA,UACA,4CAAC,SAAI,WAAU,0CACb,uDAAC,SAAI,WAAU,WACb;AAAA,wDAAC,8BAAW,WAAU,YAAY,YAAE,cAAc,GAAE;AAAA,YACpD,4CAAC,8BAAW,SAAQ,aAAY,MAAK,YAAY,YAAE,mBAAmB,GAAE;AAAA,aAC1E,GACF;AAAA,WACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;AAEA,SAAS,kBAAkB,OAAkF;AAC3G,QAAM,EAAE,EAAE,QAAI,oCAAe;AAC7B,QAAM,eAAW,sBAAY;AAC7B,QAAM,UAAU,MAAM,SAAS,WAAW;AAC1C,QAAM,uBAAuB,QAAQ;AACrC,QAAM,WAAW,MAAM,SAAS,YAAY;AAC5C,QAAM,WAAW,MAAM,SAAS,YAAY,EAAE,OAAO,GAAG,CAAC;AACzD,QAAM,0BAA0B,SAAS,OAAO,aAAW,QAAQ,iBAAiB,MAAM,YAAY;AAEtG,QAAM,CAAC,mBAAmB,oBAAoB,QAAI,uBAAS,KAAK;AAChE,QAAM,CAAC,yBAAyB,0BAA0B,QAAI,uBAAwB,IAAI;AAC1F,QAAM,CAAC,4BAA4B,6BAA6B,QAAI,uBAAwB,IAAI;AAChG,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,uBAAwB,IAAI;AAC1E,QAAM,CAAC,qBAAqB,sBAAsB,QAAI,uBAAwB,IAAI;AAClF,QAAM,CAAC,mBAAmB,oBAAoB,QAAI,uBAAwB,IAAI;AAE9E,QAAM,oBAAgB,sBAAQ,MAAM;AAClC,QAAI,CAAC,2BAA4B,QAAO;AACxC,UAAM,iBAAiB,QAAQ,IAAI;AACnC,QAAI,CAAC,eAAgB,QAAO;AAC5B,eAAO,6BAAW,gBAAgB,EAAE,eAAe,2BAA2B,CAAC;AAAA,EACjF,GAAG,CAAC,0BAA0B,CAAC;AAE/B,QAAM,mBAAmB,CAAC,UAAmB;AAC3C,QAAI,iBAAiB,gCAAY,8BAA8B;AAC7D,iCAAM;AAAA,QACJ,OAAO,EAAE,2BAA2B;AAAA,QACpC,aAAa,EAAE,8CAA8C;AAAA,QAC7D,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AACA,UAAM,uCAAuC,QAAQ,IAAI,aAAa,gBAAgB,kDAAkD,+BAA+B;AAAA;AAAA,EAAO,KAAK,EAAE;AAAA,EACvL;AAEA,QAAM,oBAAoB,MAAM;AAC9B,2CAAkB,YAAY;AAC5B,2BAAqB,IAAI;AACzB,YAAM,MAAM,MAAM,MAAM,SAAS,+BAA+B;AAChE,iCAA2B,IAAI,YAAY;AAC3C,oCAA8B,IAAI,eAAe;AAAA,IACnD,GAAG,EAAE,SAAS,iBAAiB,CAAC;AAAA,EAClC;AAEA,QAAM,qBAAqB,MAAM;AAC/B,yBAAqB,KAAK;AAC1B,+BAA2B,IAAI;AAC/B,kCAA8B,IAAI;AAAA,EACpC;AAEA,QAAM,mBAAmB,CAAC,WAAmB,kBAAiC;AAC5E,2BAAuB,SAAS;AAChC,yBAAqB,aAAa;AAAA,EACpC;AAEA,QAAM,oBAAoB,MAAM;AAC9B,2BAAuB,IAAI;AAC3B,yBAAqB,IAAI;AAAA,EAC3B;AAEA,QAAM,sBAAsB,sBACxB,wBAAwB,KAAK,CAAC,YAAY,QAAQ,OAAO,mBAAmB,KAAK,OACjF;AACJ,QAAM,gBAAgB,qBAAqB,iBAAiB,CAAC;AAC7D,QAAM,uBAAuB,cAAc,KAAK,CAAC,WAAW,OAAO,cAAc,iBAAiB,KAAK;AACvG,QAAM,kBAAkB,uBAAwB,OAAO,KAAK,qBAAqB,MAAM,EAAE,CAAC,KAAK,OAAQ;AAEvG,SACE,6CAAC,SAAI,WAAU,aACZ;AAAA,UAAM,SAAS,4CAAC,8BAAW,WAAU,eAAe,gBAAM,OAAM;AAAA,IAEhE,wBACC;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,gBAAgB;AAAA,QACzB,aAAa,EAAE,wEAAwE;AAAA,QAEvF;AAAA,sDAAC,8BAAY,8BAAoB,oBAAoB,GAAE;AAAA,UAEvD,4CAAC,0BAAO,SAAS,mBACd,YAAE,uBAAuB,GAC5B;AAAA,UAEA;AAAA,YAAC;AAAA;AAAA,cACC,MAAM;AAAA,cACN,cAAc,CAAC,SAAS;AACtB,oBAAI,CAAC,MAAM;AACT,qCAAmB;AAAA,gBACrB,OAAO;AACL,uCAAqB,IAAI;AAAA,gBAC3B;AAAA,cACF;AAAA,cACA,OAAO,EAAE,uBAAuB;AAAA,cAE/B,WAAC,2BAA2B,CAAC,8BAA8B,CAAC,gBAC3D,4CAAC,4BAAS,WAAU,eAAc,IAElC;AAAA,gBAAC;AAAA;AAAA,kBACC,QAAQ;AAAA,kBACR,SAAS;AAAA,oBACP,cAAc;AAAA,kBAChB;AAAA,kBAEA;AAAA,oBAAC;AAAA;AAAA,sBACC,cAAc;AAAA,sBACd,wBAAwB,OAAO,kBAAkB;AAC/C,8BAAM,MAAM,SAAS,uCAAuC,aAAa;AACzE,2CAAmB;AAAA,sBACrB;AAAA;AAAA,kBACF;AAAA;AAAA,cACF;AAAA;AAAA,UAEJ;AAAA;AAAA;AAAA,IACF;AAAA,IAGD,wBAAwB,SAAS,KAChC;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,cAAc;AAAA,QACvB,aAAa,EAAE,uCAAuC;AAAA,QAEtD;AAAA,sDAAC,SAAI,WAAU,aACZ,kCAAwB,IAAI,CAAC,SAAS,UAAU;AAC/C,kBAAM,iBAAiB,QAAQ,aAAa,IAAI,QAAK,QAAQ,QAAQ,KAAK;AAC1E,kBAAM,iBAAiB,QAAQ,SAAS;AACxC,kBAAM,eAAe,kBAAkB,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,QAAQ,cAAc;AAC/E,kBAAM,iBAAiB,kBAAkB,wBAAwB,CAAC,CAAC,QAAQ,OAAO,QAAQ,eAAe,UAAU,KAAK;AACxH,kBAAM,WAAW,iBAAkB,QAAQ,cAAc,oBAAoB,OAAQ;AAErF,kBAAM,WACJ,QAAQ,SAAS,aACb,EAAE,mBAAmB,IACrB,WACE,GAAG,EAAE,WAAW,CAAC,IAAI,IAAI,KAAK,eAAe,QAAW,EAAE,MAAM,WAAW,OAAO,SAAS,KAAK,UAAU,CAAC,EAAE,OAAO,QAAQ,CAAC,KAC7H,EAAE,cAAc;AAExB,mBACE,6CAAC,SAA0D,WAAU,0CACnE;AAAA,2DAAC,SAAI,WAAU,WACb;AAAA,6DAAC,8BAAW,WAAU,YAAY;AAAA,0BAAQ;AAAA,kBAAa;AAAA,mBAAe;AAAA,gBACtE,4CAAC,8BAAW,SAAQ,aAAY,MAAK,YAAY,oBAAS;AAAA,iBAC5D;AAAA,cAEA,6CAAC,SAAI,WAAU,iCACZ;AAAA,kCACC;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAQ;AAAA,oBACR,OAAM;AAAA,oBACN,SAAS,MAAM,iBAAiB,QAAQ,IAAK,QAAQ,gBAAgB,CAAC,GAAG,aAAa,IAAI;AAAA,oBAEzF,YAAE,aAAa;AAAA;AAAA,gBAClB;AAAA,gBAED,gBACC;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAQ;AAAA,oBACR,OAAM;AAAA,oBACN,SAAS,MAAM,mBAAmB,QAAQ,EAAE;AAAA,oBAE3C,YAAE,qBAAqB;AAAA;AAAA,gBAC1B;AAAA,iBAEJ;AAAA,iBAzBQ,QAAQ,MAAM,GAAG,QAAQ,WAAW,IAAI,KAAK,EA0BvD;AAAA,UAEJ,CAAC,GACH;AAAA,UAEA;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,oBAAoB;AAAA,cAC1B,cAAc,CAAC,SAAS;AACtB,oBAAI,CAAC,KAAM,oBAAmB,IAAI;AAAA,cACpC;AAAA,cACA,OAAO,EAAE,qBAAqB;AAAA,cAC9B,aAAa,EAAE,4DAA4D;AAAA,cAC3E,QAAM;AAAA,cACN,cAAY;AAAA,cACZ,UAAU;AAAA,gBACR,OAAO,EAAE,qBAAqB;AAAA,gBAC9B,SAAS,YAAY;AACnB,wBAAM,YAAY;AAClB,sBAAI,CAAC,UAAW;AAChB,sBAAI,MAAM,iBAAiB,QAAQ;AACjC,0BAAM,SAAS,mBAAmB,EAAE,QAAQ,MAAM,SAAS,IAAI,UAAU,CAAC;AAAA,kBAC5E,OAAO;AACL,0BAAM,SAAS,mBAAmB,EAAE,UAAU,CAAC;AAAA,kBACjD;AACA,qCAAmB,IAAI;AAAA,gBACzB;AAAA,cACF;AAAA;AAAA,UACF;AAAA,UAEA;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,wBAAwB;AAAA,cAC9B,cAAc,CAAC,SAAS;AACtB,oBAAI,CAAC,KAAM,mBAAkB;AAAA,cAC/B;AAAA,cACA,OAAO,EAAE,aAAa;AAAA,cACtB,aAAa,EAAE,+CAA+C;AAAA,cAC9D,cAAY;AAAA,cACZ,UAAU;AAAA,gBACR,OAAO,EAAE,aAAa;AAAA,gBACtB,SAAS,YAAY;AACnB,wBAAM,gBAAgB;AACtB,wBAAM,cAAc;AACpB,sBAAI,CAAC,iBAAiB,CAAC,YAAa;AACpC,sBAAI,CAAC,gBAAiB;AACtB,wBAAM,SAAS,MAAM,sBAAO,kBAAkB,MAAM,MAAM,SAAS,mBAAmB;AAAA,oBACpF;AAAA,oBACA;AAAA,oBACA,SAAS;AAAA,kBACX,CAAC,CAAC;AACF,sBAAI,OAAO,WAAW,SAAS;AAC7B,qCAAiB,OAAO,KAAK;AAC7B,2BAAO;AAAA,kBACT;AACA,oCAAkB;AAAA,gBACpB;AAAA,gBACA,OAAO;AAAA,kBACL,UAAU,CAAC,uBAAuB,CAAC,qBAAqB,CAAC;AAAA,gBAC3D;AAAA,cACF;AAAA,cAEA,sDAAC,SAAI,WAAU,aACZ,wBAAc,WAAW,IACxB,4CAAC,8BAAW,SAAQ,aAAY,MAAK,YAClC,YAAE,iDAAiD,GACtD,IAEA,4EACE;AAAA,4DAAC,8BAAW,MAAK,YAAY,YAAE,eAAe,GAAE;AAAA,gBAChD;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,qBAAqB;AAAA,oBAC5B,eAAe,CAAC,UAAU,qBAAqB,SAAS,IAAI;AAAA,oBAE5D;AAAA,kEAAC,iCAAc,WAAU,UACvB,sDAAC,+BAAY,aAAa,EAAE,eAAe,GAAG,GAChD;AAAA,sBACA,4CAAC,iCACE,wBAAc,IAAI,CAAC,WAClB,4CAAC,8BAAkC,OAAO,OAAO,WAC9C,iBAAO,eADO,OAAO,SAExB,CACD,GACH;AAAA;AAAA;AAAA,gBACF;AAAA,iBACF,GAEJ;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IACF;AAAA,IAGD,SAAS,SAAS,KACjB,4EACE;AAAA,kDAAC,6BAAU;AAAA,MACX,6CAAC,SAAI,WAAU,aACb;AAAA,qDAAC,SAAI,WAAU,aACb;AAAA,sDAAC,8BAAW,WAAU,eAAe,YAAE,UAAU,GAAE;AAAA,UACnD,4CAAC,8BAAW,SAAQ,aAAY,MAAK,YAAY,YAAE,oCAAoC,GAAE;AAAA,WAC3F;AAAA,QACA,4CAAC,SAAI,WAAU,qBACb,uDAAC,yBACC;AAAA,sDAAC,+BACC,uDAAC,4BACC;AAAA,wDAAC,6BAAU,WAAU,aAAa,YAAE,MAAM,GAAE;AAAA,YAC5C,4CAAC,6BAAU,WAAU,aAAa,YAAE,QAAQ,GAAE;AAAA,YAC9C,4CAAC,6BAAU,WAAU,aAAa,YAAE,QAAQ,GAAE;AAAA,YAC9C,4CAAC,6BAAU,WAAU,wBAAwB,YAAE,SAAS,GAAE;AAAA,aAC5D,GACF;AAAA,UACA,4CAAC,6BACE,mBAAS,IAAI,CAAC,SAAS,UAAU;AAChC,kBAAM,gBAAgB,QAAQ,UAAU,QAAQ;AAChD,kBAAM,aAAa,OAAO,MAAM,aAAa,IAAI,WAAW,KAAK,KAAK,WAAW,aAAa,IAAI,KAAK;AACvG,mBACE,6CAAC,4BACC;AAAA,0DAAC,6BACC,sDAAC,8BAAY,4BAAkB,QAAQ,WAAW,CAAC,GAAE,GACvD;AAAA,cACA,4CAAC,6BACC,sDAAC,8BAAY,8BAAoB,QAAQ,QAAQ,CAAC,GAAE,GACtD;AAAA,cACA,4CAAC,6BACC,sDAAC,8BAAY,8BAAoB,QAAQ,aAAa,CAAC,GAAE,GAC3D;AAAA,cACA,4CAAC,6BAAU,OAAM,SACd,kBAAQ,mBACP,4CAAC,0BAAO,SAAO,MAAC,SAAQ,aAAY,OAAM,WAAU,MAAK,MACvD,sDAAC,OAAE,MAAM,QAAQ,kBAAkB,QAAO,UAAS,KAAI,cACpD,YAAE,MAAM,GACX,GACF,IAEA,4CAAC,8BAAW,SAAQ,aAAY,MAAK,YAClC,YAAE,aAAa,GAClB,GAEJ;AAAA,iBAtBa,UAuBf;AAAA,UAEJ,CAAC,GACH;AAAA,WACF,GACF;AAAA,SACF;AAAA,OACF;AAAA,KAEJ;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../src/components-page/account-settings/payments/payments-panel.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { KnownErrors } from \"@stackframe/stack-shared\";\nimport { runAsynchronously } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { ActionDialog, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, Typography } from \"@stackframe/stack-ui\";\nimport { CardElement, Elements, useElements, useStripe } from \"@stripe/react-stripe-js\";\nimport { loadStripe } from \"@stripe/stripe-js\";\nimport { useMemo, useState } from \"react\";\nimport { useStackApp } from \"../../..\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { Section } from \"../section\";\nimport { Result } from \"@stackframe/stack-shared/dist/utils/results\";\nimport type { CustomerInvoiceStatus, CustomerInvoicesList, CustomerInvoicesListOptions } from \"../../../lib/stack-app/customers\";\n\ntype PaymentMethodSummary = {\n id: string,\n brand: string | null,\n last4: string | null,\n exp_month: number | null,\n exp_year: number | null,\n} | null;\n\nfunction formatPaymentMethod(pm: NonNullable<PaymentMethodSummary>) {\n const details = [\n pm.brand ? pm.brand.toUpperCase() : null,\n pm.last4 ? `•••• ${pm.last4}` : null,\n pm.exp_month && pm.exp_year ? `exp ${pm.exp_month}/${pm.exp_year}` : null,\n ].filter(Boolean);\n return details.join(\" · \");\n}\n\nconst formatInvoiceStatus = (status: CustomerInvoiceStatus, t: (value: string) => string) => {\n if (!status) {\n return t(\"Unknown\");\n }\n switch (status) {\n case \"draft\": {\n return t(\"Draft\");\n }\n case \"open\": {\n return t(\"Open\");\n }\n case \"paid\": {\n return t(\"Paid\");\n }\n case \"uncollectible\": {\n return t(\"Uncollectible\");\n }\n case \"void\": {\n return t(\"Void\");\n }\n default: {\n return t(\"Unknown\");\n }\n }\n};\n\nconst formatInvoiceAmount = (amountTotal: number | null | undefined, t: (value: string) => string) => {\n if (typeof amountTotal !== \"number\" || Number.isNaN(amountTotal)) {\n return t(\"Unknown\");\n }\n const normalized = amountTotal / 100;\n const formatted = new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(normalized);\n return `$${formatted}`;\n};\n\nconst formatInvoiceDate = (date: Date | null | undefined, t: (value: string) => string) => {\n if (!date || Number.isNaN(date.getTime())) {\n return t(\"Unknown\");\n }\n return new Intl.DateTimeFormat(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(date);\n};\n\ntype CustomerBilling = {\n hasCustomer: boolean,\n defaultPaymentMethod: PaymentMethodSummary,\n};\n\ntype CustomerPaymentMethodSetupIntent = {\n clientSecret: string,\n stripeAccountId: string,\n};\n\ntype CustomerLike = {\n id: string,\n useBilling: () => CustomerBilling,\n useProducts: () => Array<{\n id: string | null,\n quantity: number,\n displayName: string,\n customerType: \"user\" | \"team\" | \"custom\",\n type: \"one_time\" | \"subscription\",\n switchOptions?: Array<{\n productId: string,\n displayName: string,\n prices: Record<string, { interval?: [number, \"day\" | \"week\" | \"month\" | \"year\"] }>,\n }>,\n subscription: null | {\n subscriptionId: string | null,\n currentPeriodEnd: Date | null,\n cancelAtPeriodEnd: boolean,\n isCancelable: boolean,\n },\n }>,\n useInvoices: (options?: CustomerInvoicesListOptions) => CustomerInvoicesList,\n createPaymentMethodSetupIntent: () => Promise<CustomerPaymentMethodSetupIntent>,\n setDefaultPaymentMethodFromSetupIntent: (setupIntentId: string) => Promise<PaymentMethodSummary>,\n switchSubscription: (options: { fromProductId: string, toProductId: string, priceId?: string, quantity?: number }) => Promise<void>,\n};\n\nfunction SetDefaultPaymentMethodForm(props: {\n clientSecret: string,\n onSetupIntentSucceeded: (setupIntentId: string) => Promise<void>,\n}) {\n const stripe = useStripe();\n const elements = useElements();\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const darkMode = \"color-scheme\" in document.documentElement.style && document.documentElement.style[\"color-scheme\"] === \"dark\";\n\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Typography className=\"font-medium\">Card details</Typography>\n <div className=\"rounded-md border border-input p-3\">\n <CardElement options={{ hidePostalCode: true, style: { base: { color: darkMode ? \"white\" : \"black\" } } }} />\n </div>\n </div>\n {errorMessage && (\n <Typography variant=\"secondary\" type=\"footnote\">\n {errorMessage}\n </Typography>\n )}\n <Button\n onClick={async () => {\n if (!stripe || !elements) {\n setErrorMessage(\"Stripe is still loading. Please try again.\");\n return;\n }\n const card = elements.getElement(CardElement);\n if (!card) {\n setErrorMessage(\"Card element not found.\");\n return;\n }\n\n const result = await stripe.confirmCardSetup(props.clientSecret, {\n payment_method: { card },\n });\n if (result.error) {\n setErrorMessage(result.error.message ?? \"Failed to save payment method.\");\n return;\n }\n if (!result.setupIntent.id) {\n setErrorMessage(\"No setup intent returned from Stripe.\");\n return;\n }\n await props.onSetupIntentSucceeded(result.setupIntent.id);\n }}\n >\n Save payment method\n </Button>\n </div>\n );\n}\n\nexport function PaymentsPanel(props: {\n title?: string,\n customer?: CustomerLike,\n customerType?: \"user\" | \"team\",\n mockMode?: boolean,\n}) {\n if (props.mockMode) {\n return <MockPaymentsPanel title={props.title} />;\n }\n if (!props.customer) {\n return null;\n }\n return <RealPaymentsPanel title={props.title} customer={props.customer} customerType={props.customerType ?? \"user\"} />;\n}\n\nfunction MockPaymentsPanel(props: { title?: string }) {\n const { t } = useTranslation();\n const defaultPaymentMethod: PaymentMethodSummary = {\n id: \"pm_mock\",\n brand: \"visa\",\n last4: \"4242\",\n exp_month: 12,\n exp_year: 2030,\n };\n\n return (\n <div className=\"space-y-4\">\n {props.title && <Typography className=\"font-medium\">{props.title}</Typography>}\n <Section\n title={t(\"Payment method\")}\n description={t(\"Manage the default payment method used for subscriptions and invoices.\")}\n >\n <Typography>{formatPaymentMethod(defaultPaymentMethod)}</Typography>\n <Button disabled>\n {t(\"Update payment method\")}\n </Button>\n </Section>\n\n <Section\n title={t(\"Active plans\")}\n description={t(\"View your active plans and purchases.\")}\n >\n <div className=\"space-y-3\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{t(\"Pro\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"Renews on\")} Jan 1, 2030</Typography>\n </div>\n <Button disabled variant=\"secondary\" color=\"neutral\">\n {t(\"Cancel subscription\")}\n </Button>\n </div>\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{t(\"Credits pack\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"One-time purchase\")}</Typography>\n </div>\n </div>\n </div>\n </Section>\n </div>\n );\n}\n\nfunction RealPaymentsPanel(props: { title?: string, customer: CustomerLike, customerType: \"user\" | \"team\" }) {\n const { t } = useTranslation();\n const stackApp = useStackApp();\n const billing = props.customer.useBilling();\n const defaultPaymentMethod = billing.defaultPaymentMethod;\n const products = props.customer.useProducts();\n const invoices = props.customer.useInvoices({ limit: 10 });\n const productsForCustomerType = products.filter(product => product.customerType === props.customerType);\n\n const [paymentDialogOpen, setPaymentDialogOpen] = useState(false);\n const [setupIntentClientSecret, setSetupIntentClientSecret] = useState<string | null>(null);\n const [setupIntentStripeAccountId, setSetupIntentStripeAccountId] = useState<string | null>(null);\n const [cancelTarget, setCancelTarget] = useState<{ productId: string, subscriptionId?: string } | null>(null);\n const [switchFromProductId, setSwitchFromProductId] = useState<string | null>(null);\n const [switchToProductId, setSwitchToProductId] = useState<string | null>(null);\n\n const stripePromise = useMemo(() => {\n if (!setupIntentStripeAccountId) return null;\n const publishableKey = process.env.NEXT_PUBLIC_STACK_STRIPE_PUBLISHABLE_KEY;\n if (!publishableKey) return null;\n return loadStripe(publishableKey, { stripeAccount: setupIntentStripeAccountId });\n }, [setupIntentStripeAccountId]);\n\n const handleAsyncError = (error: unknown) => {\n if (error instanceof KnownErrors.DefaultPaymentMethodRequired) {\n toast({\n title: t(\"No default payment method\"),\n description: t(\"Add a payment method before switching plans.\"),\n variant: \"destructive\",\n });\n return;\n }\n alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === \"development\" ? \"check the browser console for the full error.\" : \"report this to the developer.\"}\\n\\n${error}`);\n };\n\n const openPaymentDialog = () => {\n runAsynchronously(async () => {\n setPaymentDialogOpen(true);\n const res = await props.customer.createPaymentMethodSetupIntent();\n setSetupIntentClientSecret(res.clientSecret);\n setSetupIntentStripeAccountId(res.stripeAccountId);\n }, { onError: handleAsyncError });\n };\n\n const closePaymentDialog = () => {\n setPaymentDialogOpen(false);\n setSetupIntentClientSecret(null);\n setSetupIntentStripeAccountId(null);\n };\n\n const openSwitchDialog = (productId: string, firstOptionId: string | null) => {\n setSwitchFromProductId(productId);\n setSwitchToProductId(firstOptionId);\n };\n\n const closeSwitchDialog = () => {\n setSwitchFromProductId(null);\n setSwitchToProductId(null);\n };\n\n const switchSourceProduct = switchFromProductId\n ? productsForCustomerType.find((product) => product.id === switchFromProductId) ?? null\n : null;\n const switchOptions = switchSourceProduct?.switchOptions ?? [];\n const selectedSwitchOption = switchOptions.find((option) => option.productId === switchToProductId) ?? null;\n const selectedPriceId = selectedSwitchOption ? (Object.keys(selectedSwitchOption.prices)[0] ?? null) : null;\n\n return (\n <div className=\"space-y-4\">\n {props.title && <Typography className=\"font-medium\">{props.title}</Typography>}\n\n {defaultPaymentMethod && (\n <Section\n title={t(\"Payment method\")}\n description={t(\"Manage the default payment method used for subscriptions and invoices.\")}\n >\n <Typography>{formatPaymentMethod(defaultPaymentMethod)}</Typography>\n\n <Button onClick={openPaymentDialog}>\n {t(\"Update payment method\")}\n </Button>\n\n <ActionDialog\n open={paymentDialogOpen}\n onOpenChange={(open) => {\n if (!open) {\n closePaymentDialog();\n } else {\n setPaymentDialogOpen(true);\n }\n }}\n title={t(\"Update payment method\")}\n >\n {!setupIntentClientSecret || !setupIntentStripeAccountId || !stripePromise ? (\n <Skeleton className=\"h-10 w-full\" />\n ) : (\n <Elements\n stripe={stripePromise}\n options={{\n clientSecret: setupIntentClientSecret,\n }}\n >\n <SetDefaultPaymentMethodForm\n clientSecret={setupIntentClientSecret}\n onSetupIntentSucceeded={async (setupIntentId) => {\n await props.customer.setDefaultPaymentMethodFromSetupIntent(setupIntentId);\n closePaymentDialog();\n }}\n />\n </Elements>\n )}\n </ActionDialog>\n </Section>\n )}\n\n {productsForCustomerType.length > 0 && (\n <Section\n title={t(\"Active plans\")}\n description={t(\"View your active plans and purchases.\")}\n >\n <div className=\"space-y-3\">\n {productsForCustomerType.map((product, index) => {\n const quantitySuffix = product.quantity !== 1 ? ` ×${product.quantity}` : \"\";\n const isSubscription = product.type === \"subscription\";\n const isCancelable = isSubscription && !!product.subscription?.isCancelable;\n const canSwitchPlans = isSubscription && defaultPaymentMethod && !!product.id && (product.switchOptions?.length ?? 0) > 0;\n const renewsAt = isSubscription ? (product.subscription?.currentPeriodEnd ?? null) : null;\n const subtitle =\n product.type === \"one_time\"\n ? t(\"One-time purchase\")\n : renewsAt\n ? `${t(\"Renews on\")} ${new Intl.DateTimeFormat(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(renewsAt)}`\n : t(\"Subscription\");\n\n return (\n <div key={product.id ?? `${product.displayName}-${index}`} className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{product.displayName}{quantitySuffix}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{subtitle}</Typography>\n </div>\n\n <div className=\"flex flex-col items-end gap-2\">\n {canSwitchPlans && (\n <Button\n variant=\"secondary\"\n color=\"neutral\"\n onClick={() => openSwitchDialog(product.id!, product.switchOptions?.[0]?.productId ?? null)}\n >\n {t(\"Change plan\")}\n </Button>\n )}\n {isCancelable && (\n <Button\n variant=\"secondary\"\n color=\"neutral\"\n onClick={() => setCancelTarget({ productId: product.id ?? \"_inline\", subscriptionId: product.subscription?.subscriptionId ?? undefined })}\n >\n {t(\"Cancel subscription\")}\n </Button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n\n <ActionDialog\n open={cancelTarget !== null}\n onOpenChange={(open) => {\n if (!open) setCancelTarget(null);\n }}\n title={t(\"Cancel subscription\")}\n description={t(\"Canceling will stop future renewals for this subscription.\")}\n danger\n cancelButton\n okButton={{\n label: t(\"Cancel subscription\"),\n onClick: async () => {\n if (!cancelTarget) return;\n const { productId, subscriptionId } = cancelTarget;\n if (props.customerType === \"team\") {\n await stackApp.cancelSubscription({ teamId: props.customer.id, productId, subscriptionId });\n } else {\n await stackApp.cancelSubscription({ productId, subscriptionId });\n }\n setCancelTarget(null);\n },\n }}\n />\n\n <ActionDialog\n open={switchFromProductId !== null}\n onOpenChange={(open) => {\n if (!open) closeSwitchDialog();\n }}\n title={t(\"Change plan\")}\n description={t(\"Select a new plan from the same product line.\")}\n cancelButton\n okButton={{\n label: t(\"Switch plan\"),\n onClick: async () => {\n const fromProductId = switchFromProductId;\n const toProductId = switchToProductId;\n if (!fromProductId || !toProductId) return;\n if (!selectedPriceId) return;\n const result = await Result.fromThrowingAsync(() => props.customer.switchSubscription({\n fromProductId,\n toProductId,\n priceId: selectedPriceId,\n }));\n if (result.status === \"error\") {\n handleAsyncError(result.error);\n return \"prevent-close\";\n }\n closeSwitchDialog();\n },\n props: {\n disabled: !switchFromProductId || !switchToProductId || !selectedPriceId,\n },\n }}\n >\n <div className=\"space-y-2\">\n {switchOptions.length === 0 ? (\n <Typography variant=\"secondary\" type=\"footnote\">\n {t(\"No other plans available for this subscription.\")}\n </Typography>\n ) : (\n <>\n <Typography type=\"footnote\">{t(\"Choose a plan\")}</Typography>\n <Select\n value={switchToProductId ?? undefined}\n onValueChange={(value) => setSwitchToProductId(value || null)}\n >\n <SelectTrigger className=\"w-full\">\n <SelectValue placeholder={t(\"Choose a plan\")} />\n </SelectTrigger>\n <SelectContent>\n {switchOptions.map((option: NonNullable<typeof switchOptions>[number]) => (\n <SelectItem key={option.productId} value={option.productId}>\n {option.displayName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </>\n )}\n </div>\n </ActionDialog>\n </Section>\n )\n }\n {invoices.length > 0 && (\n <>\n <Separator />\n <div className=\"space-y-2\">\n <div className=\"space-y-1\">\n <Typography className=\"font-medium\">{t(\"Invoices\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"Review past invoices and receipts.\")}</Typography>\n </div>\n <div className=\"border rounded-md\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[140px]\">{t(\"Date\")}</TableHead>\n <TableHead className=\"w-[120px]\">{t(\"Status\")}</TableHead>\n <TableHead className=\"w-[120px]\">{t(\"Amount\")}</TableHead>\n <TableHead className=\"w-[120px] text-right\">{t(\"Invoice\")}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {invoices.map((invoice, index) => {\n const createdAtTime = invoice.createdAt.getTime();\n const invoiceKey = Number.isNaN(createdAtTime) ? `invoice-${index}` : `invoice-${createdAtTime}-${index}`;\n return (\n <TableRow key={invoiceKey}>\n <TableCell>\n <Typography>{formatInvoiceDate(invoice.createdAt, t)}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{formatInvoiceStatus(invoice.status, t)}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{formatInvoiceAmount(invoice.amountTotal, t)}</Typography>\n </TableCell>\n <TableCell align=\"right\">\n {invoice.hostedInvoiceUrl ? (\n <Button asChild variant=\"secondary\" color=\"neutral\" size=\"sm\">\n <a href={invoice.hostedInvoiceUrl} target=\"_blank\" rel=\"noreferrer\">\n {t(\"View\")}\n </a>\n </Button>\n ) : (\n <Typography variant=\"secondary\" type=\"footnote\">\n {t(\"Unavailable\")}\n </Typography>\n )}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n </div>\n </>\n )}\n </div >\n );\n}\n"],"mappings":"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","names":[]}
@@ -169,7 +169,7 @@ function RealPaymentsPanel(props) {
169
169
  const [paymentDialogOpen, setPaymentDialogOpen] = useState(false);
170
170
  const [setupIntentClientSecret, setSetupIntentClientSecret] = useState(null);
171
171
  const [setupIntentStripeAccountId, setSetupIntentStripeAccountId] = useState(null);
172
- const [cancelProductId, setCancelProductId] = useState(null);
172
+ const [cancelTarget, setCancelTarget] = useState(null);
173
173
  const [switchFromProductId, setSwitchFromProductId] = useState(null);
174
174
  const [switchToProductId, setSwitchToProductId] = useState(null);
175
175
  const stripePromise = useMemo(() => {
@@ -271,7 +271,7 @@ ${error}`);
271
271
  /* @__PURE__ */ jsx("div", { className: "space-y-3", children: productsForCustomerType.map((product, index) => {
272
272
  const quantitySuffix = product.quantity !== 1 ? ` \xD7${product.quantity}` : "";
273
273
  const isSubscription = product.type === "subscription";
274
- const isCancelable = isSubscription && !!product.id && !!product.subscription?.isCancelable;
274
+ const isCancelable = isSubscription && !!product.subscription?.isCancelable;
275
275
  const canSwitchPlans = isSubscription && defaultPaymentMethod && !!product.id && (product.switchOptions?.length ?? 0) > 0;
276
276
  const renewsAt = isSubscription ? product.subscription?.currentPeriodEnd ?? null : null;
277
277
  const subtitle = product.type === "one_time" ? t("One-time purchase") : renewsAt ? `${t("Renews on")} ${new Intl.DateTimeFormat(void 0, { year: "numeric", month: "short", day: "numeric" }).format(renewsAt)}` : t("Subscription");
@@ -298,7 +298,7 @@ ${error}`);
298
298
  {
299
299
  variant: "secondary",
300
300
  color: "neutral",
301
- onClick: () => setCancelProductId(product.id),
301
+ onClick: () => setCancelTarget({ productId: product.id ?? "_inline", subscriptionId: product.subscription?.subscriptionId ?? void 0 }),
302
302
  children: t("Cancel subscription")
303
303
  }
304
304
  )
@@ -308,9 +308,9 @@ ${error}`);
308
308
  /* @__PURE__ */ jsx(
309
309
  ActionDialog,
310
310
  {
311
- open: cancelProductId !== null,
311
+ open: cancelTarget !== null,
312
312
  onOpenChange: (open) => {
313
- if (!open) setCancelProductId(null);
313
+ if (!open) setCancelTarget(null);
314
314
  },
315
315
  title: t("Cancel subscription"),
316
316
  description: t("Canceling will stop future renewals for this subscription."),
@@ -319,14 +319,14 @@ ${error}`);
319
319
  okButton: {
320
320
  label: t("Cancel subscription"),
321
321
  onClick: async () => {
322
- const productId = cancelProductId;
323
- if (!productId) return;
322
+ if (!cancelTarget) return;
323
+ const { productId, subscriptionId } = cancelTarget;
324
324
  if (props.customerType === "team") {
325
- await stackApp.cancelSubscription({ teamId: props.customer.id, productId });
325
+ await stackApp.cancelSubscription({ teamId: props.customer.id, productId, subscriptionId });
326
326
  } else {
327
- await stackApp.cancelSubscription({ productId });
327
+ await stackApp.cancelSubscription({ productId, subscriptionId });
328
328
  }
329
- setCancelProductId(null);
329
+ setCancelTarget(null);
330
330
  }
331
331
  }
332
332
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/components-page/account-settings/payments/payments-panel.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { KnownErrors } from \"@stackframe/stack-shared\";\nimport { runAsynchronously } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { ActionDialog, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, Typography } from \"@stackframe/stack-ui\";\nimport { CardElement, Elements, useElements, useStripe } from \"@stripe/react-stripe-js\";\nimport { loadStripe } from \"@stripe/stripe-js\";\nimport { useMemo, useState } from \"react\";\nimport { useStackApp } from \"../../..\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { Section } from \"../section\";\nimport { Result } from \"@stackframe/stack-shared/dist/utils/results\";\nimport type { CustomerInvoiceStatus, CustomerInvoicesList, CustomerInvoicesListOptions } from \"../../../lib/stack-app/customers\";\n\ntype PaymentMethodSummary = {\n id: string,\n brand: string | null,\n last4: string | null,\n exp_month: number | null,\n exp_year: number | null,\n} | null;\n\nfunction formatPaymentMethod(pm: NonNullable<PaymentMethodSummary>) {\n const details = [\n pm.brand ? pm.brand.toUpperCase() : null,\n pm.last4 ? `•••• ${pm.last4}` : null,\n pm.exp_month && pm.exp_year ? `exp ${pm.exp_month}/${pm.exp_year}` : null,\n ].filter(Boolean);\n return details.join(\" · \");\n}\n\nconst formatInvoiceStatus = (status: CustomerInvoiceStatus, t: (value: string) => string) => {\n if (!status) {\n return t(\"Unknown\");\n }\n switch (status) {\n case \"draft\": {\n return t(\"Draft\");\n }\n case \"open\": {\n return t(\"Open\");\n }\n case \"paid\": {\n return t(\"Paid\");\n }\n case \"uncollectible\": {\n return t(\"Uncollectible\");\n }\n case \"void\": {\n return t(\"Void\");\n }\n default: {\n return t(\"Unknown\");\n }\n }\n};\n\nconst formatInvoiceAmount = (amountTotal: number | null | undefined, t: (value: string) => string) => {\n if (typeof amountTotal !== \"number\" || Number.isNaN(amountTotal)) {\n return t(\"Unknown\");\n }\n const normalized = amountTotal / 100;\n const formatted = new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(normalized);\n return `$${formatted}`;\n};\n\nconst formatInvoiceDate = (date: Date | null | undefined, t: (value: string) => string) => {\n if (!date || Number.isNaN(date.getTime())) {\n return t(\"Unknown\");\n }\n return new Intl.DateTimeFormat(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(date);\n};\n\ntype CustomerBilling = {\n hasCustomer: boolean,\n defaultPaymentMethod: PaymentMethodSummary,\n};\n\ntype CustomerPaymentMethodSetupIntent = {\n clientSecret: string,\n stripeAccountId: string,\n};\n\ntype CustomerLike = {\n id: string,\n useBilling: () => CustomerBilling,\n useProducts: () => Array<{\n id: string | null,\n quantity: number,\n displayName: string,\n customerType: \"user\" | \"team\" | \"custom\",\n type: \"one_time\" | \"subscription\",\n switchOptions?: Array<{\n productId: string,\n displayName: string,\n prices: Record<string, { interval?: [number, \"day\" | \"week\" | \"month\" | \"year\"] }>,\n }>,\n subscription: null | {\n currentPeriodEnd: Date | null,\n cancelAtPeriodEnd: boolean,\n isCancelable: boolean,\n },\n }>,\n useInvoices: (options?: CustomerInvoicesListOptions) => CustomerInvoicesList,\n createPaymentMethodSetupIntent: () => Promise<CustomerPaymentMethodSetupIntent>,\n setDefaultPaymentMethodFromSetupIntent: (setupIntentId: string) => Promise<PaymentMethodSummary>,\n switchSubscription: (options: { fromProductId: string, toProductId: string, priceId?: string, quantity?: number }) => Promise<void>,\n};\n\nfunction SetDefaultPaymentMethodForm(props: {\n clientSecret: string,\n onSetupIntentSucceeded: (setupIntentId: string) => Promise<void>,\n}) {\n const stripe = useStripe();\n const elements = useElements();\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const darkMode = \"color-scheme\" in document.documentElement.style && document.documentElement.style[\"color-scheme\"] === \"dark\";\n\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Typography className=\"font-medium\">Card details</Typography>\n <div className=\"rounded-md border border-input p-3\">\n <CardElement options={{ hidePostalCode: true, style: { base: { color: darkMode ? \"white\" : \"black\" } } }} />\n </div>\n </div>\n {errorMessage && (\n <Typography variant=\"secondary\" type=\"footnote\">\n {errorMessage}\n </Typography>\n )}\n <Button\n onClick={async () => {\n if (!stripe || !elements) {\n setErrorMessage(\"Stripe is still loading. Please try again.\");\n return;\n }\n const card = elements.getElement(CardElement);\n if (!card) {\n setErrorMessage(\"Card element not found.\");\n return;\n }\n\n const result = await stripe.confirmCardSetup(props.clientSecret, {\n payment_method: { card },\n });\n if (result.error) {\n setErrorMessage(result.error.message ?? \"Failed to save payment method.\");\n return;\n }\n if (!result.setupIntent.id) {\n setErrorMessage(\"No setup intent returned from Stripe.\");\n return;\n }\n await props.onSetupIntentSucceeded(result.setupIntent.id);\n }}\n >\n Save payment method\n </Button>\n </div>\n );\n}\n\nexport function PaymentsPanel(props: {\n title?: string,\n customer?: CustomerLike,\n customerType?: \"user\" | \"team\",\n mockMode?: boolean,\n}) {\n if (props.mockMode) {\n return <MockPaymentsPanel title={props.title} />;\n }\n if (!props.customer) {\n return null;\n }\n return <RealPaymentsPanel title={props.title} customer={props.customer} customerType={props.customerType ?? \"user\"} />;\n}\n\nfunction MockPaymentsPanel(props: { title?: string }) {\n const { t } = useTranslation();\n const defaultPaymentMethod: PaymentMethodSummary = {\n id: \"pm_mock\",\n brand: \"visa\",\n last4: \"4242\",\n exp_month: 12,\n exp_year: 2030,\n };\n\n return (\n <div className=\"space-y-4\">\n {props.title && <Typography className=\"font-medium\">{props.title}</Typography>}\n <Section\n title={t(\"Payment method\")}\n description={t(\"Manage the default payment method used for subscriptions and invoices.\")}\n >\n <Typography>{formatPaymentMethod(defaultPaymentMethod)}</Typography>\n <Button disabled>\n {t(\"Update payment method\")}\n </Button>\n </Section>\n\n <Section\n title={t(\"Active plans\")}\n description={t(\"View your active plans and purchases.\")}\n >\n <div className=\"space-y-3\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{t(\"Pro\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"Renews on\")} Jan 1, 2030</Typography>\n </div>\n <Button disabled variant=\"secondary\" color=\"neutral\">\n {t(\"Cancel subscription\")}\n </Button>\n </div>\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{t(\"Credits pack\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"One-time purchase\")}</Typography>\n </div>\n </div>\n </div>\n </Section>\n </div>\n );\n}\n\nfunction RealPaymentsPanel(props: { title?: string, customer: CustomerLike, customerType: \"user\" | \"team\" }) {\n const { t } = useTranslation();\n const stackApp = useStackApp();\n const billing = props.customer.useBilling();\n const defaultPaymentMethod = billing.defaultPaymentMethod;\n const products = props.customer.useProducts();\n const invoices = props.customer.useInvoices({ limit: 10 });\n const productsForCustomerType = products.filter(product => product.customerType === props.customerType);\n\n const [paymentDialogOpen, setPaymentDialogOpen] = useState(false);\n const [setupIntentClientSecret, setSetupIntentClientSecret] = useState<string | null>(null);\n const [setupIntentStripeAccountId, setSetupIntentStripeAccountId] = useState<string | null>(null);\n const [cancelProductId, setCancelProductId] = useState<string | null>(null);\n const [switchFromProductId, setSwitchFromProductId] = useState<string | null>(null);\n const [switchToProductId, setSwitchToProductId] = useState<string | null>(null);\n\n const stripePromise = useMemo(() => {\n if (!setupIntentStripeAccountId) return null;\n const publishableKey = process.env.NEXT_PUBLIC_STACK_STRIPE_PUBLISHABLE_KEY;\n if (!publishableKey) return null;\n return loadStripe(publishableKey, { stripeAccount: setupIntentStripeAccountId });\n }, [setupIntentStripeAccountId]);\n\n const handleAsyncError = (error: unknown) => {\n if (error instanceof KnownErrors.DefaultPaymentMethodRequired) {\n toast({\n title: t(\"No default payment method\"),\n description: t(\"Add a payment method before switching plans.\"),\n variant: \"destructive\",\n });\n return;\n }\n alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === \"development\" ? \"check the browser console for the full error.\" : \"report this to the developer.\"}\\n\\n${error}`);\n };\n\n const openPaymentDialog = () => {\n runAsynchronously(async () => {\n setPaymentDialogOpen(true);\n const res = await props.customer.createPaymentMethodSetupIntent();\n setSetupIntentClientSecret(res.clientSecret);\n setSetupIntentStripeAccountId(res.stripeAccountId);\n }, { onError: handleAsyncError });\n };\n\n const closePaymentDialog = () => {\n setPaymentDialogOpen(false);\n setSetupIntentClientSecret(null);\n setSetupIntentStripeAccountId(null);\n };\n\n const openSwitchDialog = (productId: string, firstOptionId: string | null) => {\n setSwitchFromProductId(productId);\n setSwitchToProductId(firstOptionId);\n };\n\n const closeSwitchDialog = () => {\n setSwitchFromProductId(null);\n setSwitchToProductId(null);\n };\n\n const switchSourceProduct = switchFromProductId\n ? productsForCustomerType.find((product) => product.id === switchFromProductId) ?? null\n : null;\n const switchOptions = switchSourceProduct?.switchOptions ?? [];\n const selectedSwitchOption = switchOptions.find((option) => option.productId === switchToProductId) ?? null;\n const selectedPriceId = selectedSwitchOption ? (Object.keys(selectedSwitchOption.prices)[0] ?? null) : null;\n\n return (\n <div className=\"space-y-4\">\n {props.title && <Typography className=\"font-medium\">{props.title}</Typography>}\n\n {defaultPaymentMethod && (\n <Section\n title={t(\"Payment method\")}\n description={t(\"Manage the default payment method used for subscriptions and invoices.\")}\n >\n <Typography>{formatPaymentMethod(defaultPaymentMethod)}</Typography>\n\n <Button onClick={openPaymentDialog}>\n {t(\"Update payment method\")}\n </Button>\n\n <ActionDialog\n open={paymentDialogOpen}\n onOpenChange={(open) => {\n if (!open) {\n closePaymentDialog();\n } else {\n setPaymentDialogOpen(true);\n }\n }}\n title={t(\"Update payment method\")}\n >\n {!setupIntentClientSecret || !setupIntentStripeAccountId || !stripePromise ? (\n <Skeleton className=\"h-10 w-full\" />\n ) : (\n <Elements\n stripe={stripePromise}\n options={{\n clientSecret: setupIntentClientSecret,\n }}\n >\n <SetDefaultPaymentMethodForm\n clientSecret={setupIntentClientSecret}\n onSetupIntentSucceeded={async (setupIntentId) => {\n await props.customer.setDefaultPaymentMethodFromSetupIntent(setupIntentId);\n closePaymentDialog();\n }}\n />\n </Elements>\n )}\n </ActionDialog>\n </Section>\n )}\n\n {productsForCustomerType.length > 0 && (\n <Section\n title={t(\"Active plans\")}\n description={t(\"View your active plans and purchases.\")}\n >\n <div className=\"space-y-3\">\n {productsForCustomerType.map((product, index) => {\n const quantitySuffix = product.quantity !== 1 ? ` ×${product.quantity}` : \"\";\n const isSubscription = product.type === \"subscription\";\n const isCancelable = isSubscription && !!product.id && !!product.subscription?.isCancelable;\n const canSwitchPlans = isSubscription && defaultPaymentMethod && !!product.id && (product.switchOptions?.length ?? 0) > 0;\n const renewsAt = isSubscription ? (product.subscription?.currentPeriodEnd ?? null) : null;\n\n const subtitle =\n product.type === \"one_time\"\n ? t(\"One-time purchase\")\n : renewsAt\n ? `${t(\"Renews on\")} ${new Intl.DateTimeFormat(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(renewsAt)}`\n : t(\"Subscription\");\n\n return (\n <div key={product.id ?? `${product.displayName}-${index}`} className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{product.displayName}{quantitySuffix}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{subtitle}</Typography>\n </div>\n\n <div className=\"flex flex-col items-end gap-2\">\n {canSwitchPlans && (\n <Button\n variant=\"secondary\"\n color=\"neutral\"\n onClick={() => openSwitchDialog(product.id!, product.switchOptions?.[0]?.productId ?? null)}\n >\n {t(\"Change plan\")}\n </Button>\n )}\n {isCancelable && (\n <Button\n variant=\"secondary\"\n color=\"neutral\"\n onClick={() => setCancelProductId(product.id)}\n >\n {t(\"Cancel subscription\")}\n </Button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n\n <ActionDialog\n open={cancelProductId !== null}\n onOpenChange={(open) => {\n if (!open) setCancelProductId(null);\n }}\n title={t(\"Cancel subscription\")}\n description={t(\"Canceling will stop future renewals for this subscription.\")}\n danger\n cancelButton\n okButton={{\n label: t(\"Cancel subscription\"),\n onClick: async () => {\n const productId = cancelProductId;\n if (!productId) return;\n if (props.customerType === \"team\") {\n await stackApp.cancelSubscription({ teamId: props.customer.id, productId });\n } else {\n await stackApp.cancelSubscription({ productId });\n }\n setCancelProductId(null);\n },\n }}\n />\n\n <ActionDialog\n open={switchFromProductId !== null}\n onOpenChange={(open) => {\n if (!open) closeSwitchDialog();\n }}\n title={t(\"Change plan\")}\n description={t(\"Select a new plan from the same product line.\")}\n cancelButton\n okButton={{\n label: t(\"Switch plan\"),\n onClick: async () => {\n const fromProductId = switchFromProductId;\n const toProductId = switchToProductId;\n if (!fromProductId || !toProductId) return;\n if (!selectedPriceId) return;\n const result = await Result.fromThrowingAsync(() => props.customer.switchSubscription({\n fromProductId,\n toProductId,\n priceId: selectedPriceId,\n }));\n if (result.status === \"error\") {\n handleAsyncError(result.error);\n return \"prevent-close\";\n }\n closeSwitchDialog();\n },\n props: {\n disabled: !switchFromProductId || !switchToProductId || !selectedPriceId,\n },\n }}\n >\n <div className=\"space-y-2\">\n {switchOptions.length === 0 ? (\n <Typography variant=\"secondary\" type=\"footnote\">\n {t(\"No other plans available for this subscription.\")}\n </Typography>\n ) : (\n <>\n <Typography type=\"footnote\">{t(\"Choose a plan\")}</Typography>\n <Select\n value={switchToProductId ?? undefined}\n onValueChange={(value) => setSwitchToProductId(value || null)}\n >\n <SelectTrigger className=\"w-full\">\n <SelectValue placeholder={t(\"Choose a plan\")} />\n </SelectTrigger>\n <SelectContent>\n {switchOptions.map((option: NonNullable<typeof switchOptions>[number]) => (\n <SelectItem key={option.productId} value={option.productId}>\n {option.displayName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </>\n )}\n </div>\n </ActionDialog>\n </Section>\n )\n }\n {invoices.length > 0 && (\n <>\n <Separator />\n <div className=\"space-y-2\">\n <div className=\"space-y-1\">\n <Typography className=\"font-medium\">{t(\"Invoices\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"Review past invoices and receipts.\")}</Typography>\n </div>\n <div className=\"border rounded-md\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[140px]\">{t(\"Date\")}</TableHead>\n <TableHead className=\"w-[120px]\">{t(\"Status\")}</TableHead>\n <TableHead className=\"w-[120px]\">{t(\"Amount\")}</TableHead>\n <TableHead className=\"w-[120px] text-right\">{t(\"Invoice\")}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {invoices.map((invoice, index) => {\n const createdAtTime = invoice.createdAt.getTime();\n const invoiceKey = Number.isNaN(createdAtTime) ? `invoice-${index}` : `invoice-${createdAtTime}-${index}`;\n return (\n <TableRow key={invoiceKey}>\n <TableCell>\n <Typography>{formatInvoiceDate(invoice.createdAt, t)}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{formatInvoiceStatus(invoice.status, t)}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{formatInvoiceAmount(invoice.amountTotal, t)}</Typography>\n </TableCell>\n <TableCell align=\"right\">\n {invoice.hostedInvoiceUrl ? (\n <Button asChild variant=\"secondary\" color=\"neutral\" size=\"sm\">\n <a href={invoice.hostedInvoiceUrl} target=\"_blank\" rel=\"noreferrer\">\n {t(\"View\")}\n </a>\n </Button>\n ) : (\n <Typography variant=\"secondary\" type=\"footnote\">\n {t(\"Unavailable\")}\n </Typography>\n )}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n </div>\n </>\n )}\n </div >\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../src/components-page/account-settings/payments/payments-panel.tsx"],"sourcesContent":["'use client';\n\n\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\nimport { KnownErrors } from \"@stackframe/stack-shared\";\nimport { runAsynchronously } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { ActionDialog, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, Typography } from \"@stackframe/stack-ui\";\nimport { CardElement, Elements, useElements, useStripe } from \"@stripe/react-stripe-js\";\nimport { loadStripe } from \"@stripe/stripe-js\";\nimport { useMemo, useState } from \"react\";\nimport { useStackApp } from \"../../..\";\nimport { useTranslation } from \"../../../lib/translations\";\nimport { Section } from \"../section\";\nimport { Result } from \"@stackframe/stack-shared/dist/utils/results\";\nimport type { CustomerInvoiceStatus, CustomerInvoicesList, CustomerInvoicesListOptions } from \"../../../lib/stack-app/customers\";\n\ntype PaymentMethodSummary = {\n id: string,\n brand: string | null,\n last4: string | null,\n exp_month: number | null,\n exp_year: number | null,\n} | null;\n\nfunction formatPaymentMethod(pm: NonNullable<PaymentMethodSummary>) {\n const details = [\n pm.brand ? pm.brand.toUpperCase() : null,\n pm.last4 ? `•••• ${pm.last4}` : null,\n pm.exp_month && pm.exp_year ? `exp ${pm.exp_month}/${pm.exp_year}` : null,\n ].filter(Boolean);\n return details.join(\" · \");\n}\n\nconst formatInvoiceStatus = (status: CustomerInvoiceStatus, t: (value: string) => string) => {\n if (!status) {\n return t(\"Unknown\");\n }\n switch (status) {\n case \"draft\": {\n return t(\"Draft\");\n }\n case \"open\": {\n return t(\"Open\");\n }\n case \"paid\": {\n return t(\"Paid\");\n }\n case \"uncollectible\": {\n return t(\"Uncollectible\");\n }\n case \"void\": {\n return t(\"Void\");\n }\n default: {\n return t(\"Unknown\");\n }\n }\n};\n\nconst formatInvoiceAmount = (amountTotal: number | null | undefined, t: (value: string) => string) => {\n if (typeof amountTotal !== \"number\" || Number.isNaN(amountTotal)) {\n return t(\"Unknown\");\n }\n const normalized = amountTotal / 100;\n const formatted = new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(normalized);\n return `$${formatted}`;\n};\n\nconst formatInvoiceDate = (date: Date | null | undefined, t: (value: string) => string) => {\n if (!date || Number.isNaN(date.getTime())) {\n return t(\"Unknown\");\n }\n return new Intl.DateTimeFormat(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(date);\n};\n\ntype CustomerBilling = {\n hasCustomer: boolean,\n defaultPaymentMethod: PaymentMethodSummary,\n};\n\ntype CustomerPaymentMethodSetupIntent = {\n clientSecret: string,\n stripeAccountId: string,\n};\n\ntype CustomerLike = {\n id: string,\n useBilling: () => CustomerBilling,\n useProducts: () => Array<{\n id: string | null,\n quantity: number,\n displayName: string,\n customerType: \"user\" | \"team\" | \"custom\",\n type: \"one_time\" | \"subscription\",\n switchOptions?: Array<{\n productId: string,\n displayName: string,\n prices: Record<string, { interval?: [number, \"day\" | \"week\" | \"month\" | \"year\"] }>,\n }>,\n subscription: null | {\n subscriptionId: string | null,\n currentPeriodEnd: Date | null,\n cancelAtPeriodEnd: boolean,\n isCancelable: boolean,\n },\n }>,\n useInvoices: (options?: CustomerInvoicesListOptions) => CustomerInvoicesList,\n createPaymentMethodSetupIntent: () => Promise<CustomerPaymentMethodSetupIntent>,\n setDefaultPaymentMethodFromSetupIntent: (setupIntentId: string) => Promise<PaymentMethodSummary>,\n switchSubscription: (options: { fromProductId: string, toProductId: string, priceId?: string, quantity?: number }) => Promise<void>,\n};\n\nfunction SetDefaultPaymentMethodForm(props: {\n clientSecret: string,\n onSetupIntentSucceeded: (setupIntentId: string) => Promise<void>,\n}) {\n const stripe = useStripe();\n const elements = useElements();\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const darkMode = \"color-scheme\" in document.documentElement.style && document.documentElement.style[\"color-scheme\"] === \"dark\";\n\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Typography className=\"font-medium\">Card details</Typography>\n <div className=\"rounded-md border border-input p-3\">\n <CardElement options={{ hidePostalCode: true, style: { base: { color: darkMode ? \"white\" : \"black\" } } }} />\n </div>\n </div>\n {errorMessage && (\n <Typography variant=\"secondary\" type=\"footnote\">\n {errorMessage}\n </Typography>\n )}\n <Button\n onClick={async () => {\n if (!stripe || !elements) {\n setErrorMessage(\"Stripe is still loading. Please try again.\");\n return;\n }\n const card = elements.getElement(CardElement);\n if (!card) {\n setErrorMessage(\"Card element not found.\");\n return;\n }\n\n const result = await stripe.confirmCardSetup(props.clientSecret, {\n payment_method: { card },\n });\n if (result.error) {\n setErrorMessage(result.error.message ?? \"Failed to save payment method.\");\n return;\n }\n if (!result.setupIntent.id) {\n setErrorMessage(\"No setup intent returned from Stripe.\");\n return;\n }\n await props.onSetupIntentSucceeded(result.setupIntent.id);\n }}\n >\n Save payment method\n </Button>\n </div>\n );\n}\n\nexport function PaymentsPanel(props: {\n title?: string,\n customer?: CustomerLike,\n customerType?: \"user\" | \"team\",\n mockMode?: boolean,\n}) {\n if (props.mockMode) {\n return <MockPaymentsPanel title={props.title} />;\n }\n if (!props.customer) {\n return null;\n }\n return <RealPaymentsPanel title={props.title} customer={props.customer} customerType={props.customerType ?? \"user\"} />;\n}\n\nfunction MockPaymentsPanel(props: { title?: string }) {\n const { t } = useTranslation();\n const defaultPaymentMethod: PaymentMethodSummary = {\n id: \"pm_mock\",\n brand: \"visa\",\n last4: \"4242\",\n exp_month: 12,\n exp_year: 2030,\n };\n\n return (\n <div className=\"space-y-4\">\n {props.title && <Typography className=\"font-medium\">{props.title}</Typography>}\n <Section\n title={t(\"Payment method\")}\n description={t(\"Manage the default payment method used for subscriptions and invoices.\")}\n >\n <Typography>{formatPaymentMethod(defaultPaymentMethod)}</Typography>\n <Button disabled>\n {t(\"Update payment method\")}\n </Button>\n </Section>\n\n <Section\n title={t(\"Active plans\")}\n description={t(\"View your active plans and purchases.\")}\n >\n <div className=\"space-y-3\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{t(\"Pro\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"Renews on\")} Jan 1, 2030</Typography>\n </div>\n <Button disabled variant=\"secondary\" color=\"neutral\">\n {t(\"Cancel subscription\")}\n </Button>\n </div>\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{t(\"Credits pack\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"One-time purchase\")}</Typography>\n </div>\n </div>\n </div>\n </Section>\n </div>\n );\n}\n\nfunction RealPaymentsPanel(props: { title?: string, customer: CustomerLike, customerType: \"user\" | \"team\" }) {\n const { t } = useTranslation();\n const stackApp = useStackApp();\n const billing = props.customer.useBilling();\n const defaultPaymentMethod = billing.defaultPaymentMethod;\n const products = props.customer.useProducts();\n const invoices = props.customer.useInvoices({ limit: 10 });\n const productsForCustomerType = products.filter(product => product.customerType === props.customerType);\n\n const [paymentDialogOpen, setPaymentDialogOpen] = useState(false);\n const [setupIntentClientSecret, setSetupIntentClientSecret] = useState<string | null>(null);\n const [setupIntentStripeAccountId, setSetupIntentStripeAccountId] = useState<string | null>(null);\n const [cancelTarget, setCancelTarget] = useState<{ productId: string, subscriptionId?: string } | null>(null);\n const [switchFromProductId, setSwitchFromProductId] = useState<string | null>(null);\n const [switchToProductId, setSwitchToProductId] = useState<string | null>(null);\n\n const stripePromise = useMemo(() => {\n if (!setupIntentStripeAccountId) return null;\n const publishableKey = process.env.NEXT_PUBLIC_STACK_STRIPE_PUBLISHABLE_KEY;\n if (!publishableKey) return null;\n return loadStripe(publishableKey, { stripeAccount: setupIntentStripeAccountId });\n }, [setupIntentStripeAccountId]);\n\n const handleAsyncError = (error: unknown) => {\n if (error instanceof KnownErrors.DefaultPaymentMethodRequired) {\n toast({\n title: t(\"No default payment method\"),\n description: t(\"Add a payment method before switching plans.\"),\n variant: \"destructive\",\n });\n return;\n }\n alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === \"development\" ? \"check the browser console for the full error.\" : \"report this to the developer.\"}\\n\\n${error}`);\n };\n\n const openPaymentDialog = () => {\n runAsynchronously(async () => {\n setPaymentDialogOpen(true);\n const res = await props.customer.createPaymentMethodSetupIntent();\n setSetupIntentClientSecret(res.clientSecret);\n setSetupIntentStripeAccountId(res.stripeAccountId);\n }, { onError: handleAsyncError });\n };\n\n const closePaymentDialog = () => {\n setPaymentDialogOpen(false);\n setSetupIntentClientSecret(null);\n setSetupIntentStripeAccountId(null);\n };\n\n const openSwitchDialog = (productId: string, firstOptionId: string | null) => {\n setSwitchFromProductId(productId);\n setSwitchToProductId(firstOptionId);\n };\n\n const closeSwitchDialog = () => {\n setSwitchFromProductId(null);\n setSwitchToProductId(null);\n };\n\n const switchSourceProduct = switchFromProductId\n ? productsForCustomerType.find((product) => product.id === switchFromProductId) ?? null\n : null;\n const switchOptions = switchSourceProduct?.switchOptions ?? [];\n const selectedSwitchOption = switchOptions.find((option) => option.productId === switchToProductId) ?? null;\n const selectedPriceId = selectedSwitchOption ? (Object.keys(selectedSwitchOption.prices)[0] ?? null) : null;\n\n return (\n <div className=\"space-y-4\">\n {props.title && <Typography className=\"font-medium\">{props.title}</Typography>}\n\n {defaultPaymentMethod && (\n <Section\n title={t(\"Payment method\")}\n description={t(\"Manage the default payment method used for subscriptions and invoices.\")}\n >\n <Typography>{formatPaymentMethod(defaultPaymentMethod)}</Typography>\n\n <Button onClick={openPaymentDialog}>\n {t(\"Update payment method\")}\n </Button>\n\n <ActionDialog\n open={paymentDialogOpen}\n onOpenChange={(open) => {\n if (!open) {\n closePaymentDialog();\n } else {\n setPaymentDialogOpen(true);\n }\n }}\n title={t(\"Update payment method\")}\n >\n {!setupIntentClientSecret || !setupIntentStripeAccountId || !stripePromise ? (\n <Skeleton className=\"h-10 w-full\" />\n ) : (\n <Elements\n stripe={stripePromise}\n options={{\n clientSecret: setupIntentClientSecret,\n }}\n >\n <SetDefaultPaymentMethodForm\n clientSecret={setupIntentClientSecret}\n onSetupIntentSucceeded={async (setupIntentId) => {\n await props.customer.setDefaultPaymentMethodFromSetupIntent(setupIntentId);\n closePaymentDialog();\n }}\n />\n </Elements>\n )}\n </ActionDialog>\n </Section>\n )}\n\n {productsForCustomerType.length > 0 && (\n <Section\n title={t(\"Active plans\")}\n description={t(\"View your active plans and purchases.\")}\n >\n <div className=\"space-y-3\">\n {productsForCustomerType.map((product, index) => {\n const quantitySuffix = product.quantity !== 1 ? ` ×${product.quantity}` : \"\";\n const isSubscription = product.type === \"subscription\";\n const isCancelable = isSubscription && !!product.subscription?.isCancelable;\n const canSwitchPlans = isSubscription && defaultPaymentMethod && !!product.id && (product.switchOptions?.length ?? 0) > 0;\n const renewsAt = isSubscription ? (product.subscription?.currentPeriodEnd ?? null) : null;\n const subtitle =\n product.type === \"one_time\"\n ? t(\"One-time purchase\")\n : renewsAt\n ? `${t(\"Renews on\")} ${new Intl.DateTimeFormat(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(renewsAt)}`\n : t(\"Subscription\");\n\n return (\n <div key={product.id ?? `${product.displayName}-${index}`} className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <Typography className=\"truncate\">{product.displayName}{quantitySuffix}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{subtitle}</Typography>\n </div>\n\n <div className=\"flex flex-col items-end gap-2\">\n {canSwitchPlans && (\n <Button\n variant=\"secondary\"\n color=\"neutral\"\n onClick={() => openSwitchDialog(product.id!, product.switchOptions?.[0]?.productId ?? null)}\n >\n {t(\"Change plan\")}\n </Button>\n )}\n {isCancelable && (\n <Button\n variant=\"secondary\"\n color=\"neutral\"\n onClick={() => setCancelTarget({ productId: product.id ?? \"_inline\", subscriptionId: product.subscription?.subscriptionId ?? undefined })}\n >\n {t(\"Cancel subscription\")}\n </Button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n\n <ActionDialog\n open={cancelTarget !== null}\n onOpenChange={(open) => {\n if (!open) setCancelTarget(null);\n }}\n title={t(\"Cancel subscription\")}\n description={t(\"Canceling will stop future renewals for this subscription.\")}\n danger\n cancelButton\n okButton={{\n label: t(\"Cancel subscription\"),\n onClick: async () => {\n if (!cancelTarget) return;\n const { productId, subscriptionId } = cancelTarget;\n if (props.customerType === \"team\") {\n await stackApp.cancelSubscription({ teamId: props.customer.id, productId, subscriptionId });\n } else {\n await stackApp.cancelSubscription({ productId, subscriptionId });\n }\n setCancelTarget(null);\n },\n }}\n />\n\n <ActionDialog\n open={switchFromProductId !== null}\n onOpenChange={(open) => {\n if (!open) closeSwitchDialog();\n }}\n title={t(\"Change plan\")}\n description={t(\"Select a new plan from the same product line.\")}\n cancelButton\n okButton={{\n label: t(\"Switch plan\"),\n onClick: async () => {\n const fromProductId = switchFromProductId;\n const toProductId = switchToProductId;\n if (!fromProductId || !toProductId) return;\n if (!selectedPriceId) return;\n const result = await Result.fromThrowingAsync(() => props.customer.switchSubscription({\n fromProductId,\n toProductId,\n priceId: selectedPriceId,\n }));\n if (result.status === \"error\") {\n handleAsyncError(result.error);\n return \"prevent-close\";\n }\n closeSwitchDialog();\n },\n props: {\n disabled: !switchFromProductId || !switchToProductId || !selectedPriceId,\n },\n }}\n >\n <div className=\"space-y-2\">\n {switchOptions.length === 0 ? (\n <Typography variant=\"secondary\" type=\"footnote\">\n {t(\"No other plans available for this subscription.\")}\n </Typography>\n ) : (\n <>\n <Typography type=\"footnote\">{t(\"Choose a plan\")}</Typography>\n <Select\n value={switchToProductId ?? undefined}\n onValueChange={(value) => setSwitchToProductId(value || null)}\n >\n <SelectTrigger className=\"w-full\">\n <SelectValue placeholder={t(\"Choose a plan\")} />\n </SelectTrigger>\n <SelectContent>\n {switchOptions.map((option: NonNullable<typeof switchOptions>[number]) => (\n <SelectItem key={option.productId} value={option.productId}>\n {option.displayName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </>\n )}\n </div>\n </ActionDialog>\n </Section>\n )\n }\n {invoices.length > 0 && (\n <>\n <Separator />\n <div className=\"space-y-2\">\n <div className=\"space-y-1\">\n <Typography className=\"font-medium\">{t(\"Invoices\")}</Typography>\n <Typography variant=\"secondary\" type=\"footnote\">{t(\"Review past invoices and receipts.\")}</Typography>\n </div>\n <div className=\"border rounded-md\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[140px]\">{t(\"Date\")}</TableHead>\n <TableHead className=\"w-[120px]\">{t(\"Status\")}</TableHead>\n <TableHead className=\"w-[120px]\">{t(\"Amount\")}</TableHead>\n <TableHead className=\"w-[120px] text-right\">{t(\"Invoice\")}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {invoices.map((invoice, index) => {\n const createdAtTime = invoice.createdAt.getTime();\n const invoiceKey = Number.isNaN(createdAtTime) ? `invoice-${index}` : `invoice-${createdAtTime}-${index}`;\n return (\n <TableRow key={invoiceKey}>\n <TableCell>\n <Typography>{formatInvoiceDate(invoice.createdAt, t)}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{formatInvoiceStatus(invoice.status, t)}</Typography>\n </TableCell>\n <TableCell>\n <Typography>{formatInvoiceAmount(invoice.amountTotal, t)}</Typography>\n </TableCell>\n <TableCell align=\"right\">\n {invoice.hostedInvoiceUrl ? (\n <Button asChild variant=\"secondary\" color=\"neutral\" size=\"sm\">\n <a href={invoice.hostedInvoiceUrl} target=\"_blank\" rel=\"noreferrer\">\n {t(\"View\")}\n </a>\n </Button>\n ) : (\n <Typography variant=\"secondary\" type=\"footnote\">\n {t(\"Unavailable\")}\n </Typography>\n )}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n </div>\n </>\n )}\n </div >\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nexport * from './lib/stack-app';\n\nexport { getConvexProvidersConfig } from \"./integrations/convex\";\n\nexport { default as StackHandler } from \"./components-page/stack-handler\";\nexport { useStackApp, useUser } from \"./lib/hooks\";\nexport { default as StackProvider } from \"./providers/stack-provider\";\nexport { StackTheme } from './providers/theme-provider';\n\nexport { AccountSettings } from \"./components-page/account-settings\";\nexport { AuthPage } from \"./components-page/auth-page\";\nexport { CliAuthConfirmation } from \"./components-page/cli-auth-confirm\";\nexport { EmailVerification } from \"./components-page/email-verification\";\nexport { ForgotPassword } from \"./components-page/forgot-password\";\nexport { PasswordReset } from \"./components-page/password-reset\";\nexport { SignIn } from \"./components-page/sign-in\";\nexport { SignUp } from \"./components-page/sign-up\";\nexport { CredentialSignIn as CredentialSignIn } from \"./components/credential-sign-in\";\nexport { CredentialSignUp as CredentialSignUp } from \"./components/credential-sign-up\";\nexport { UserAvatar } from \"./components/elements/user-avatar\";\nexport { MagicLinkSignIn as MagicLinkSignIn } from \"./components/magic-link-sign-in\";\nexport { MessageCard } from \"./components/message-cards/message-card\";\nexport { OAuthButton } from \"./components/oauth-button\";\nexport { OAuthButtonGroup } from \"./components/oauth-button-group\";\nexport { SelectedTeamSwitcher } from \"./components/selected-team-switcher\";\nexport { TeamSwitcher } from \"./components/team-switcher\";\nexport { UserButton } from \"./components/user-button\";\n"],"mappings":";AAIA,cAAc;AAEd,SAAS,gCAAgC;AAEzC,SAAoB,WAAXA,gBAA+B;AACxC,SAAS,aAAa,eAAe;AACrC,SAAoB,WAAXA,gBAAgC;AACzC,SAAS,kBAAkB;AAE3B,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AACzB,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAA6B,wBAAwB;AACrD,SAA6B,wBAAwB;AACrD,SAAS,kBAAkB;AAC3B,SAA4B,uBAAuB;AACnD,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AACjC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;","names":["default"]}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY, INSTEAD EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nexport * from './lib/stack-app';\nexport { getConvexProvidersConfig } from \"./integrations/convex\";\n\nexport type { AnalyticsOptions, AnalyticsReplayOptions } from \"./lib/stack-app/apps/implementations/session-replay\";\nexport { default as StackHandler } from \"./components-page/stack-handler\";\nexport { useStackApp, useUser } from \"./lib/hooks\";\nexport { default as StackProvider } from \"./providers/stack-provider\";\nexport { StackTheme } from './providers/theme-provider';\n\nexport { AccountSettings } from \"./components-page/account-settings\";\nexport { AuthPage } from \"./components-page/auth-page\";\nexport { CliAuthConfirmation } from \"./components-page/cli-auth-confirm\";\nexport { EmailVerification } from \"./components-page/email-verification\";\nexport { ForgotPassword } from \"./components-page/forgot-password\";\nexport { PasswordReset } from \"./components-page/password-reset\";\nexport { SignIn } from \"./components-page/sign-in\";\nexport { SignUp } from \"./components-page/sign-up\";\nexport { CredentialSignIn as CredentialSignIn } from \"./components/credential-sign-in\";\nexport { CredentialSignUp as CredentialSignUp } from \"./components/credential-sign-up\";\nexport { UserAvatar } from \"./components/elements/user-avatar\";\nexport { MagicLinkSignIn as MagicLinkSignIn } from \"./components/magic-link-sign-in\";\nexport { MessageCard } from \"./components/message-cards/message-card\";\nexport { OAuthButton } from \"./components/oauth-button\";\nexport { OAuthButtonGroup } from \"./components/oauth-button-group\";\nexport { SelectedTeamSwitcher } from \"./components/selected-team-switcher\";\nexport { TeamSwitcher } from \"./components/team-switcher\";\nexport { UserButton } from \"./components/user-button\";\n"],"mappings":";AAIA,cAAc;AACd,SAAS,gCAAgC;AAGzC,SAAoB,WAAXA,gBAA+B;AACxC,SAAS,aAAa,eAAe;AACrC,SAAoB,WAAXA,gBAAgC;AACzC,SAAS,kBAAkB;AAE3B,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AACzB,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAA6B,wBAAwB;AACrD,SAA6B,wBAAwB;AACrD,SAAS,kBAAkB;AAC3B,SAA4B,uBAAuB;AACnD,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AACjC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;","names":["default"]}