@openrails/billing-ui 0.242.0 → 0.244.0
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.
- package/CHANGELOG.md +27 -11
- package/README.md +41 -8
- package/dist/admin/billing-admin.d.ts +3 -0
- package/dist/admin/components/app-sidebar.d.ts +1 -0
- package/dist/admin/components/confirm.d.ts +4 -0
- package/dist/admin/components/cursor-pager.d.ts +8 -0
- package/dist/admin/components/data-table.d.ts +14 -0
- package/dist/admin/components/fact-card.d.ts +5 -0
- package/dist/admin/components/form-field-errors.d.ts +3 -0
- package/dist/admin/components/linked-table-row.d.ts +5 -0
- package/dist/admin/components/logo.d.ts +3 -0
- package/dist/admin/components/no-access.d.ts +3 -0
- package/dist/admin/components/no-merchants.d.ts +1 -0
- package/dist/admin/components/notification-bell.d.ts +2 -0
- package/dist/admin/components/route-error.d.ts +3 -0
- package/dist/admin/components/site-header.d.ts +9 -0
- package/dist/admin/components/status-badge.d.ts +3 -0
- package/dist/admin/components/typed-confirm-dialog.d.ts +11 -0
- package/dist/admin/components/ui/alert-dialog.d.ts +18 -0
- package/dist/admin/components/ui/avatar.d.ts +11 -0
- package/dist/admin/components/ui/badge.d.ts +7 -0
- package/dist/admin/components/ui/breadcrumb.d.ts +10 -0
- package/dist/admin/components/ui/button.d.ts +8 -0
- package/dist/admin/components/ui/card.d.ts +11 -0
- package/dist/admin/components/ui/chart.d.ts +44 -0
- package/dist/admin/components/ui/dialog.d.ts +17 -0
- package/dist/admin/components/ui/dropdown-menu.d.ts +29 -0
- package/dist/admin/components/ui/input.d.ts +3 -0
- package/dist/admin/components/ui/label.d.ts +3 -0
- package/dist/admin/components/ui/select.d.ts +15 -0
- package/dist/admin/components/ui/separator.d.ts +3 -0
- package/dist/admin/components/ui/sheet.d.ts +14 -0
- package/dist/admin/components/ui/sidebar.d.ts +63 -0
- package/dist/admin/components/ui/skeleton.d.ts +2 -0
- package/dist/admin/components/ui/sonner.d.ts +3 -0
- package/dist/admin/components/ui/switch.d.ts +5 -0
- package/dist/admin/components/ui/table.d.ts +10 -0
- package/dist/admin/components/ui/tabs.d.ts +10 -0
- package/dist/admin/components/ui/textarea.d.ts +3 -0
- package/dist/admin/components/ui/tooltip.d.ts +6 -0
- package/dist/admin/context.d.ts +1193 -0
- package/dist/admin/hooks/use-mobile.d.ts +1 -0
- package/dist/admin/index.d.ts +5 -0
- package/dist/admin/layouts/app-layout.d.ts +4 -0
- package/dist/admin/lib/api/client.d.ts +64 -0
- package/dist/admin/lib/api/copilot.d.ts +6 -0
- package/dist/admin/lib/api/credit-endpoints.d.ts +8 -0
- package/dist/admin/lib/api/credit-types.d.ts +9 -0
- package/dist/admin/lib/api/endpoints.d.ts +133 -0
- package/dist/admin/lib/api/index.d.ts +89 -0
- package/dist/admin/lib/api/invoice-profile-endpoints.d.ts +6 -0
- package/dist/admin/lib/api/metrics.d.ts +68 -0
- package/dist/admin/lib/api/order-endpoints.d.ts +21 -0
- package/dist/admin/lib/api/types.d.ts +122 -0
- package/dist/admin/lib/auth.d.ts +6 -0
- package/dist/admin/lib/capabilities.d.ts +13 -0
- package/dist/admin/lib/chunk-error.d.ts +1 -0
- package/dist/admin/lib/confirm.d.ts +11 -0
- package/dist/admin/lib/credit-queries.d.ts +23 -0
- package/dist/admin/lib/csv.d.ts +3 -0
- package/dist/admin/lib/cursor-pages.d.ts +13 -0
- package/dist/admin/lib/dialog-width.d.ts +6 -0
- package/dist/admin/lib/dom.d.ts +1 -0
- package/dist/admin/lib/duration.d.ts +3 -0
- package/dist/admin/lib/format.d.ts +23 -0
- package/dist/admin/lib/mount.d.ts +6 -0
- package/dist/admin/lib/mutations.d.ts +125 -0
- package/dist/admin/lib/order-queries.d.ts +29 -0
- package/dist/admin/lib/queries.d.ts +369 -0
- package/dist/admin/lib/query-client.d.ts +3 -0
- package/dist/admin/lib/toast.d.ts +10 -0
- package/dist/admin/lib/utils.d.ts +2 -0
- package/dist/admin/messages.d.ts +670 -0
- package/dist/admin/navigation.d.ts +14 -0
- package/dist/admin/pages/catalog/application-dialog.d.ts +2 -0
- package/dist/admin/pages/catalog/copilot-panel.d.ts +4 -0
- package/dist/admin/pages/catalog/index.d.ts +4 -0
- package/dist/admin/pages/catalog/meter-form.d.ts +6 -0
- package/dist/admin/pages/catalog/metering-model.d.ts +67 -0
- package/dist/admin/pages/catalog/metering.d.ts +3 -0
- package/dist/admin/pages/catalog/price-detail.d.ts +2 -0
- package/dist/admin/pages/catalog/price-format.d.ts +3 -0
- package/dist/admin/pages/catalog/price-wizard-logic.d.ts +20 -0
- package/dist/admin/pages/catalog/price-wizard.d.ts +10 -0
- package/dist/admin/pages/catalog/psp-links.d.ts +10 -0
- package/dist/admin/pages/catalog/rate-card-editor.d.ts +10 -0
- package/dist/admin/pages/customers/credit-form.d.ts +14 -0
- package/dist/admin/pages/customers/credits.d.ts +5 -0
- package/dist/admin/pages/customers/default-card-badges.d.ts +3 -0
- package/dist/admin/pages/customers/detail.d.ts +5 -0
- package/dist/admin/pages/customers/grant-duration.d.ts +32 -0
- package/dist/admin/pages/customers/index.d.ts +2 -0
- package/dist/admin/pages/customers/invoice-profile-model.d.ts +18 -0
- package/dist/admin/pages/customers/invoice-profile.d.ts +9 -0
- package/dist/admin/pages/dashboard/index.d.ts +2 -0
- package/dist/admin/pages/dashboard/lib.d.ts +48 -0
- package/dist/admin/pages/dashboard/range-picker.d.ts +1 -0
- package/dist/admin/pages/dashboard/range.d.ts +34 -0
- package/dist/admin/pages/dashboard/reports-model.d.ts +29 -0
- package/dist/admin/pages/dashboard/reports.d.ts +2 -0
- package/dist/admin/pages/dashboard/use-range.d.ts +5 -0
- package/dist/admin/pages/dashboard/widget-editor.d.ts +8 -0
- package/dist/admin/pages/dashboard/widget-tile.d.ts +9 -0
- package/dist/admin/pages/dashboard/widget-viz.d.ts +12 -0
- package/dist/admin/pages/ops/index.d.ts +2 -0
- package/dist/admin/pages/orders/detail.d.ts +5 -0
- package/dist/admin/pages/orders/index.d.ts +1 -0
- package/dist/admin/pages/orders/model.d.ts +7 -0
- package/dist/admin/pages/payments/attempts.d.ts +7 -0
- package/dist/admin/pages/payments/detail.d.ts +2 -0
- package/dist/admin/pages/payments/health-model.d.ts +149 -0
- package/dist/admin/pages/payments/health.d.ts +2 -0
- package/dist/admin/pages/payments/index.d.ts +2 -0
- package/dist/admin/pages/settings/configuration-edit.d.ts +9 -0
- package/dist/admin/pages/settings/index.d.ts +9 -0
- package/dist/admin/pages/settings/notifications.d.ts +2 -0
- package/dist/admin/pages/settings/setting-fields.d.ts +20 -0
- package/dist/admin/pages/subscriptions/change-subscription-dialog.d.ts +16 -0
- package/dist/admin/pages/subscriptions/detail.d.ts +2 -0
- package/dist/admin/pages/subscriptions/dunning.d.ts +2 -0
- package/dist/admin/pages/subscriptions/index.d.ts +2 -0
- package/dist/admin/pages/subscriptions/subscription-change-options.d.ts +23 -0
- package/dist/admin/pages/subscriptions/views.d.ts +15 -0
- package/dist/admin/router.d.ts +32 -0
- package/dist/admin/routes.d.ts +5 -0
- package/dist/admin/summary.d.ts +27 -0
- package/dist/admin/theme.d.ts +2 -0
- package/dist/admin/types.d.ts +56 -0
- package/dist/admin/ui-context.d.ts +14 -0
- package/dist/admin-attempts-lAoW-Urd.js +419 -0
- package/dist/admin-attempts-lAoW-Urd.js.map +1 -0
- package/dist/admin-auth-DQGHtt0j.js +14 -0
- package/dist/admin-auth-DQGHtt0j.js.map +1 -0
- package/dist/admin-badge-DR5-1qd8.js +31 -0
- package/dist/admin-badge-DR5-1qd8.js.map +1 -0
- package/dist/admin-button-CTL3DgOt.js +46 -0
- package/dist/admin-button-CTL3DgOt.js.map +1 -0
- package/dist/admin-capabilities-BuigAgtm.js +59 -0
- package/dist/admin-capabilities-BuigAgtm.js.map +1 -0
- package/dist/admin-card-bzAks3-3.js +51 -0
- package/dist/admin-card-bzAks3-3.js.map +1 -0
- package/dist/admin-catalog-CK6CM9I2.js +1199 -0
- package/dist/admin-catalog-CK6CM9I2.js.map +1 -0
- package/dist/admin-confirm-katGq0Qo.js +12 -0
- package/dist/admin-confirm-katGq0Qo.js.map +1 -0
- package/dist/admin-csv-CPoNZj2D.js +16 -0
- package/dist/admin-csv-CPoNZj2D.js.map +1 -0
- package/dist/admin-customers-D8u5gq3M.js +160 -0
- package/dist/admin-customers-D8u5gq3M.js.map +1 -0
- package/dist/admin-dashboard-DqqFjOzq.js +420 -0
- package/dist/admin-dashboard-DqqFjOzq.js.map +1 -0
- package/dist/admin-data-table-qfXLOFmN.js +96 -0
- package/dist/admin-data-table-qfXLOFmN.js.map +1 -0
- package/dist/admin-detail-5aNNvrc0.js +324 -0
- package/dist/admin-detail-5aNNvrc0.js.map +1 -0
- package/dist/admin-detail-7p684Uyc.js +342 -0
- package/dist/admin-detail-7p684Uyc.js.map +1 -0
- package/dist/admin-detail-CGOyqs7s.js +1312 -0
- package/dist/admin-detail-CGOyqs7s.js.map +1 -0
- package/dist/admin-detail-DUAJQg8G.js +710 -0
- package/dist/admin-detail-DUAJQg8G.js.map +1 -0
- package/dist/admin-dialog-BjuKI5Hp.js +88 -0
- package/dist/admin-dialog-BjuKI5Hp.js.map +1 -0
- package/dist/admin-dialog-width-BPrgdYlj.js +6 -0
- package/dist/admin-dialog-width-BPrgdYlj.js.map +1 -0
- package/dist/admin-dom-uMmZzRvU.js +149 -0
- package/dist/admin-dom-uMmZzRvU.js.map +1 -0
- package/dist/admin-dropdown-menu-BW1D_h6s.js +69 -0
- package/dist/admin-dropdown-menu-BW1D_h6s.js.map +1 -0
- package/dist/admin-dunning-B2zgtrOo.js +10 -0
- package/dist/admin-dunning-B2zgtrOo.js.map +1 -0
- package/dist/admin-fact-card-DO_fHosg.js +20 -0
- package/dist/admin-fact-card-DO_fHosg.js.map +1 -0
- package/dist/admin-form-field-errors-hbUMIriS.js +14 -0
- package/dist/admin-form-field-errors-hbUMIriS.js.map +1 -0
- package/dist/admin-format-DoohJ7Fg.js +136 -0
- package/dist/admin-format-DoohJ7Fg.js.map +1 -0
- package/dist/admin-health-B4jN2LwR.js +983 -0
- package/dist/admin-health-B4jN2LwR.js.map +1 -0
- package/dist/admin-input-CcfQfJFN.js +17 -0
- package/dist/admin-input-CcfQfJFN.js.map +1 -0
- package/dist/admin-invoice-profile-model-Cgjy3zV8.js +53 -0
- package/dist/admin-invoice-profile-model-Cgjy3zV8.js.map +1 -0
- package/dist/admin-label-BiEN5cjb.js +15 -0
- package/dist/admin-label-BiEN5cjb.js.map +1 -0
- package/dist/admin-linked-table-row-BsaUruCN.js +26 -0
- package/dist/admin-linked-table-row-BsaUruCN.js.map +1 -0
- package/dist/admin-metering-COFcSPQy.js +1721 -0
- package/dist/admin-metering-COFcSPQy.js.map +1 -0
- package/dist/admin-ops-B3mcr76u.js +217 -0
- package/dist/admin-ops-B3mcr76u.js.map +1 -0
- package/dist/admin-orders-dxC99Idl.js +192 -0
- package/dist/admin-orders-dxC99Idl.js.map +1 -0
- package/dist/admin-payments-Bs7HSfP0.js +246 -0
- package/dist/admin-payments-Bs7HSfP0.js.map +1 -0
- package/dist/admin-price-detail-DRquxpA9.js +482 -0
- package/dist/admin-price-detail-DRquxpA9.js.map +1 -0
- package/dist/admin-price-format-DM1qORWI.js +44 -0
- package/dist/admin-price-format-DM1qORWI.js.map +1 -0
- package/dist/admin-price-wizard-CI7K-2Nz.js +357 -0
- package/dist/admin-price-wizard-CI7K-2Nz.js.map +1 -0
- package/dist/admin-range-picker-Dr2M1EZr.js +192 -0
- package/dist/admin-range-picker-Dr2M1EZr.js.map +1 -0
- package/dist/admin-reports-CywKLiSA.js +320 -0
- package/dist/admin-reports-CywKLiSA.js.map +1 -0
- package/dist/admin-select-DBgprVW6.js +81 -0
- package/dist/admin-select-DBgprVW6.js.map +1 -0
- package/dist/admin-settings-Bmoy95uO.js +1434 -0
- package/dist/admin-settings-Bmoy95uO.js.map +1 -0
- package/dist/admin-skeleton-DsM7crYi.js +14 -0
- package/dist/admin-skeleton-DsM7crYi.js.map +1 -0
- package/dist/admin-status-badge-BFPgo71d.js +38 -0
- package/dist/admin-status-badge-BFPgo71d.js.map +1 -0
- package/dist/admin-subscriptions-CLYc_HEV.js +301 -0
- package/dist/admin-subscriptions-CLYc_HEV.js.map +1 -0
- package/dist/admin-switch-BJUxLCsa.js +20 -0
- package/dist/admin-switch-BJUxLCsa.js.map +1 -0
- package/dist/admin-table-CH9TrXJf.js +61 -0
- package/dist/admin-table-CH9TrXJf.js.map +1 -0
- package/dist/admin-tabs-528FJMjt.js +46 -0
- package/dist/admin-tabs-528FJMjt.js.map +1 -0
- package/dist/admin-textarea-DEz38RaI.js +15 -0
- package/dist/admin-textarea-DEz38RaI.js.map +1 -0
- package/dist/admin-typed-confirm-dialog-DU7m9-O7.js +66 -0
- package/dist/admin-typed-confirm-dialog-DU7m9-O7.js.map +1 -0
- package/dist/admin-utils-BK4Vh1o_.js +1809 -0
- package/dist/admin-utils-BK4Vh1o_.js.map +1 -0
- package/dist/admin-widget-viz-Da48c-Zf.js +581 -0
- package/dist/admin-widget-viz-Da48c-Zf.js.map +1 -0
- package/dist/admin.css +3 -0
- package/dist/admin.js +2164 -0
- package/dist/admin.js.map +1 -0
- package/dist/appearance.d.ts +1 -1
- package/dist/client/client.d.ts +13 -6
- package/dist/client/generated/error-codes.d.ts +1 -1
- package/dist/client/generated/routes.d.ts +2173 -178
- package/dist/client/generated/wire.d.ts +1287 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/types.d.ts +14 -2
- package/dist/{client-PjivPHmE.js → client-D5Af726I.js} +8 -7
- package/dist/client-D5Af726I.js.map +1 -0
- package/dist/client.js +1 -1
- package/dist/{hooks-Uiw-zW3H.js → hooks-CYjlHS28.js} +8 -8
- package/dist/hooks-CYjlHS28.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/lib/{offer-label.d.ts → price-label.d.ts} +1 -1
- package/dist/locales/de.js +1 -1
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/en.d.ts +1 -1
- package/dist/locales/en.js +1 -1
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +1 -1
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/ja.js +1 -1
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +1 -1
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +1 -1
- package/dist/locales/zh.js.map +1 -1
- package/dist/{offers.d.ts → product-list.d.ts} +5 -5
- package/dist/react.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +28 -6
- package/dist/client-PjivPHmE.js.map +0 -1
- package/dist/hooks-Uiw-zW3H.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-detail-DUAJQg8G.js","names":[],"sources":["../src/admin/pages/subscriptions/subscription-change-options.ts","../src/admin/pages/subscriptions/change-subscription-dialog.tsx","../src/admin/pages/subscriptions/detail.tsx"],"sourcesContent":["import type { Rail, SubscriptionStatus } from \"#orck/admin/lib/api/types\"\nimport type {\n Price,\n Product,\n ScheduledChange,\n} from \"#orck/client/generated/wire\"\nimport { formatNativeAmount } from \"#orck/admin/lib/format\"\nimport { priceIntervalLabel } from \"#orck/admin/pages/catalog/price-format\"\n\nexport interface SubscriptionChangeOption {\n direction: \"current\" | \"upgrade\" | \"downgrade\"\n price: Price\n product: Product\n}\n\nexport function subscriptionChangeOptionLabel(\n option: SubscriptionChangeOption\n): string {\n const price = option.price\n const amount = `${formatNativeAmount(price.unit_amount, price.currency)}${price.quantity ? \" per seat\" : \"\"}`\n return [\n option.product.display_name,\n option.direction,\n `${amount} ${priceIntervalLabel(price)}`,\n price.key,\n ].join(\" · \")\n}\n\n// The seats a change starts from: the subscription's when the price allows\n// them, otherwise the price's minimum.\nexport function initialSeats(\n price: Price,\n current: number | null\n): number | null {\n const bounds = price.quantity\n if (!bounds) return null\n if (current !== null && current >= bounds.min && current <= bounds.max) {\n return current\n }\n return bounds.min\n}\n\nexport function adminSubscriptionChangeBlockReason({\n rail,\n status,\n collectionPolicy,\n scheduledChange,\n}: {\n rail: Rail\n status: SubscriptionStatus\n collectionPolicy?: string\n scheduledChange?: Pick<ScheduledChange, \"source\"> | null\n}): string | undefined {\n if (status !== \"active\" && status !== \"past_due\") {\n return \"Only active or past-due subscriptions can change\"\n }\n // OpenRails changes back only the scheduled change it bills itself.\n if (scheduledChange && collectionPolicy !== \"engine\") {\n return \"Its provider already bills a scheduled change\"\n }\n if (rail === \"ccbill\") return \"CCBill changes require customer self-service\"\n if (rail === \"solana\") {\n return \"Solana changes require the customer's wallet signature\"\n }\n return undefined\n}\n\n// The changes the console offers: the current price, for its seats or to\n// change back from a scheduled change, then, unless a price migration is\n// pending, live recurring prices of the tier group in the same currency.\nexport function subscriptionChangeOptions({\n currentProduct,\n currentPrice,\n currentCurrency,\n products,\n prices,\n scheduledChange,\n}: {\n currentProduct?: Product\n currentPrice?: Price\n currentCurrency?: string\n products: Product[]\n prices: Price[]\n scheduledChange?: Pick<ScheduledChange, \"source\"> | null\n}): SubscriptionChangeOption[] {\n const current: SubscriptionChangeOption[] =\n currentProduct && currentPrice && (currentPrice.quantity || scheduledChange)\n ? [{ direction: \"current\", price: currentPrice, product: currentProduct }]\n : []\n const tierGroup = currentProduct?.tier_group?.trim()\n const currency = currentCurrency?.trim().toLowerCase()\n if (\n !currentProduct ||\n !tierGroup ||\n !currency ||\n scheduledChange?.source === \"migration\"\n ) {\n return current\n }\n\n const productsByID = new Map(\n products\n .filter(\n (product) =>\n !product.archived &&\n product.id !== currentProduct.id &&\n product.tier_group?.trim() === tierGroup\n )\n .map((product) => [product.id, product])\n )\n\n return current.concat(\n prices\n .flatMap((price): SubscriptionChangeOption[] => {\n const product = productsByID.get(price.product_id)\n if (\n !product ||\n price.archived ||\n !price.billing_interval_hours ||\n price.currency.trim().toLowerCase() !== currency\n ) {\n return []\n }\n return [\n {\n direction:\n product.tier_rank < currentProduct.tier_rank\n ? \"downgrade\"\n : \"upgrade\",\n price,\n product,\n },\n ]\n })\n .sort(\n (left, right) =>\n left.product.tier_rank - right.product.tier_rank ||\n left.product.display_name.localeCompare(right.product.display_name) ||\n left.price.id.localeCompare(right.price.id)\n )\n )\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport * as React from \"react\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"#orck/admin/components/ui/dialog\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"#orck/admin/components/ui/select\"\nimport type {\n ChangeSubscriptionParams,\n Rail,\n ScheduledChange,\n SubscriptionStatus,\n} from \"#orck/admin/lib/api/types\"\nimport { ApiError } from \"#orck/admin/lib/api/client\"\nimport { DIALOG_WIDE } from \"#orck/admin/lib/dialog-width\"\nimport { formatDate, formatNativeAmount } from \"#orck/admin/lib/format\"\n\nimport {\n adminSubscriptionChangeBlockReason,\n initialSeats,\n subscriptionChangeOptionLabel,\n subscriptionChangeOptions,\n} from \"#orck/admin/pages/subscriptions/subscription-change-options\"\n\ninterface ChangeSubscriptionDialogProps {\n subscriptionId: string\n customerId?: string\n productId: string\n priceId: string\n quantity: number | null\n currency?: string\n collectionPolicy?: string\n scheduledChange?: ScheduledChange | null\n rail: Rail\n status: SubscriptionStatus\n}\n\nexport function ChangeSubscriptionDialog(props: ChangeSubscriptionDialogProps) {\n const { selectedMerchant } = useAdminServices()\n\n return (\n <ChangeSubscriptionForm\n key={`${selectedMerchant() ?? \"\"}:${props.subscriptionId}`}\n {...props}\n />\n )\n}\n\nfunction ChangeSubscriptionForm({\n subscriptionId,\n customerId,\n productId,\n priceId,\n quantity,\n currency,\n collectionPolicy,\n scheduledChange,\n rail,\n status,\n}: ChangeSubscriptionDialogProps) {\n const { toast, toastApiError, adminMutations, adminQueries } =\n useAdminServices()\n\n const { id: adminId, text: adminText } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const [selectedPriceId, setSelectedPriceId] = React.useState(\"\")\n const [seats, setSeats] = React.useState(\"\")\n const [reason, setReason] = React.useState(\"\")\n const [reviewedKey, setReviewedKey] = React.useState(\"\")\n // A dismissed dialog or another preview cannot establish non-execution.\n // Retain each submitted request's key until its outcome is definitive.\n const attempts = React.useRef(new Map<string, string>())\n const view = React.useRef(0)\n React.useEffect(\n () => () => {\n view.current++\n },\n []\n )\n const queryClient = useQueryClient()\n const preview = useMutation(\n adminMutations.previewSubscriptionChange(subscriptionId)\n )\n const change = useMutation(\n adminMutations.changeSubscription(queryClient, subscriptionId, customerId)\n )\n const productsQuery = useQuery({\n ...adminQueries.allProducts({ errorAction: \"Load subscription plans\" }),\n enabled: open,\n })\n const pricesQuery = useQuery({\n ...adminQueries.allPrices({ errorAction: \"Load subscription prices\" }),\n enabled: open,\n })\n\n const products = productsQuery.data?.data ?? []\n const prices = pricesQuery.data?.data ?? []\n const currentProduct = products.find((product) => product.id === productId)\n const currentPrice = prices.find((price) => price.id === priceId)\n const options = subscriptionChangeOptions({\n currentProduct,\n currentPrice,\n currentCurrency: currency ?? currentPrice?.currency,\n products,\n prices,\n scheduledChange,\n })\n const selected = options.find((option) => option.price.id === selectedPriceId)\n const bounds = selected?.price.quantity\n const seatCount = Number(seats)\n const seatsValid =\n !bounds ||\n (Number.isInteger(seatCount) &&\n seatCount >= bounds.min &&\n seatCount <= bounds.max)\n // The current price with its seats changes back from a scheduled change.\n const request: ChangeSubscriptionParams | undefined =\n selected && seatsValid\n ? {\n price_id: selected.price.id,\n ...(bounds ? { quantity: seatCount } : {}),\n }\n : undefined\n const unchanged =\n selected?.direction === \"current\" &&\n !scheduledChange &&\n (!bounds || seatCount === quantity)\n const requestKey = request ? JSON.stringify(request) : \"\"\n const reviewed =\n requestKey && reviewedKey === requestKey ? preview.data : undefined\n const blockReason = adminSubscriptionChangeBlockReason({\n rail,\n status,\n collectionPolicy,\n scheduledChange,\n })\n\n const handleOpenChange = (next: boolean) => {\n view.current++\n setOpen(next)\n }\n\n const handleSelect = (value: string | null) => {\n view.current++\n const price = options.find((option) => option.price.id === value)?.price\n setSelectedPriceId(value ?? \"\")\n setSeats(String(price ? (initialSeats(price, quantity) ?? \"\") : \"\"))\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n\n const handleSeats = (value: string) => {\n view.current++\n setSeats(value)\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n\n const previewError =\n preview.error instanceof Error ? preview.error.message : \"\"\n const changeError = change.error instanceof Error ? change.error.message : \"\"\n const responseMessage = change.data?.message\n const responseURL = change.data?.next_action?.url ?? undefined\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogTrigger\n render={\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={Boolean(blockReason) && !change.variables}\n title={blockReason}\n >\n <AdminMessage id={\"Change subscription\"} />\n </Button>\n }\n />\n <DialogContent className={DIALOG_WIDE}>\n <DialogHeader>\n <DialogTitle>\n <AdminMessage id={\"Change subscription\"} />\n </DialogTitle>\n <DialogDescription>\n <AdminMessage\n id={\"Schedule the customer's plan or seats for the next renewal. No card is charged now. Choosing the current plan and seats clears a pending change. The customer is told.\"}\n />\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"grid gap-5\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-tier\")}>\n <AdminMessage id={\"New plan\"} />\n </Label>\n <Select value={selectedPriceId} onValueChange={handleSelect}>\n <SelectTrigger\n id={adminId(\"subscription-tier\")}\n className=\"w-full\"\n disabled={productsQuery.isPending || pricesQuery.isPending}\n >\n <SelectValue\n placeholder={\n productsQuery.isPending || pricesQuery.isPending\n ? \"Loading plans…\"\n : \"Choose a plan\"\n }\n />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.price.id} value={option.price.id}>\n {subscriptionChangeOptionLabel(option)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {!productsQuery.isPending &&\n !pricesQuery.isPending &&\n !productsQuery.isError &&\n !pricesQuery.isError &&\n options.length === 0 && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n \"No eligible recurring plans share this tier group and currency.\"\n }\n />\n </p>\n )}\n {(productsQuery.isError || pricesQuery.isError) && (\n <p className=\"text-xs text-destructive\" role=\"alert\">\n <AdminMessage id={\"Could not load the available plans.\"} />\n </p>\n )}\n </div>\n\n {bounds && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-seats\")}>\n <AdminMessage id={\"Seats\"} />\n </Label>\n <Input\n id={adminId(\"subscription-seats\")}\n type=\"number\"\n inputMode=\"numeric\"\n min={bounds.min}\n max={bounds.max}\n value={seats}\n onChange={(event) => handleSeats(event.target.value)}\n />\n <p className=\"text-xs text-muted-foreground\">\n {bounds.min}\n <AdminMessage id={\" to \"} />\n {bounds.max}\n <AdminMessage id={\" seats.\"} />\n </p>\n </div>\n )}\n\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-change-reason\")}>\n <AdminMessage id={\"Reason\"} />\n </Label>\n <Input\n id={adminId(\"subscription-change-reason\")}\n value={reason}\n maxLength={500}\n placeholder={adminText(\"What the customer asked for\")}\n onChange={(event) => setReason(event.target.value)}\n />\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Kept with the scheduled change.\"} />\n </p>\n </div>\n\n {reviewed && selected && (\n <div className=\"grid gap-3\" aria-live=\"polite\">\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-sm font-medium\">\n <AdminMessage id={\"Review\"} />\n </span>\n <Badge variant=\"secondary\">\n {reviewed.effective === \"now\" ? \"Immediate\" : \"At renewal\"}\n </Badge>\n </div>\n <dl className=\"grid grid-cols-2 gap-x-8 gap-y-3 border-y py-4 text-sm\">\n {reviewed.quantity !== null && (\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Seats\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {reviewed.quantity}\n </dd>\n </div>\n )}\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Due now\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatNativeAmount(\n reviewed.amount_due_now,\n reviewed.currency\n )}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Next charge\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatNativeAmount(\n reviewed.next_charge_amount,\n reviewed.currency\n )}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Effective\"} />\n </dt>\n <dd className=\"font-medium\">\n {reviewed.effective === \"now\"\n ? \"Immediately\"\n : formatDate(reviewed.next_charge_date)}\n </dd>\n </div>\n <div className=\"grid gap-1\">\n <dt className=\"text-xs text-muted-foreground\">\n <AdminMessage id={\"Next billing date\"} />\n </dt>\n <dd className=\"font-medium tabular-nums\">\n {formatDate(reviewed.next_charge_date)}\n </dd>\n </div>\n </dl>\n {reviewed.is_estimate && (\n <p className=\"text-xs text-muted-foreground\">\n <AdminMessage\n id={\n \"The payment provider calculates the final prorated amount.\"\n }\n />\n </p>\n )}\n </div>\n )}\n\n {(previewError || changeError) && (\n <p className=\"text-sm text-destructive\" role=\"alert\">\n {changeError || previewError}\n </p>\n )}\n\n {change.data && change.data.status !== \"succeeded\" && (\n <div\n className=\"grid gap-2 rounded-lg bg-muted px-3 py-2.5 text-sm\"\n aria-live=\"polite\"\n >\n <p>{responseMessage ?? \"This change needs another step.\"}</p>\n {responseURL && (\n <a\n href={responseURL}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"w-fit font-medium text-primary underline underline-offset-4\"\n >\n <AdminMessage id={\"Continue with payment provider\"} />\n </a>\n )}\n </div>\n )}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => handleOpenChange(false)}\n >\n <AdminMessage id={\"Cancel\"} />\n </Button>\n {!reviewed ? (\n <Button\n type=\"button\"\n disabled={!request || unchanged || preview.isPending}\n onClick={async () => {\n if (!request) return\n const currentView = view.current\n try {\n await preview.mutateAsync(request)\n if (view.current !== currentView) return\n setReviewedKey(requestKey)\n } catch (error) {\n if (view.current === currentView) {\n toastApiError(error, \"Preview subscription change\")\n }\n }\n }}\n >\n {preview.isPending ? \"Reviewing…\" : \"Review change\"}\n </Button>\n ) : (\n <Button\n type=\"button\"\n disabled={\n change.isPending ||\n !reason.trim() ||\n (Boolean(change.data) && change.data?.status !== \"processing\")\n }\n onClick={async () => {\n if (!request) return\n const currentView = view.current\n const changeKey =\n attempts.current.get(requestKey) ?? crypto.randomUUID()\n attempts.current.set(requestKey, changeKey)\n const completeAttempt = () => {\n if (attempts.current.get(requestKey) === changeKey) {\n attempts.current.delete(requestKey)\n }\n }\n try {\n const result = await change.mutateAsync({\n change: { ...request, reason: reason.trim() },\n idempotencyKey: changeKey,\n })\n if (\n result.status === \"succeeded\" ||\n result.status === \"blocked\"\n ) {\n completeAttempt()\n }\n if (view.current !== currentView) return\n if (result.status === \"succeeded\") {\n toast.success(\n result.effective === \"now\"\n ? \"Subscription changed\"\n : \"Change scheduled for the next renewal\"\n )\n handleOpenChange(false)\n setSelectedPriceId(\"\")\n setSeats(\"\")\n setReason(\"\")\n setReviewedKey(\"\")\n preview.reset()\n change.reset()\n }\n if (result.status === \"processing\") {\n toast.info(\n \"The provider is still confirming this change. Check again to read the result.\"\n )\n }\n } catch (error) {\n // 402 is a final provider refusal regardless of its code.\n // Other refusals can reject a readback of an already accepted\n // operation, so retire only explicitly terminal outcomes.\n if (\n error instanceof ApiError &&\n (error.status === 402 ||\n (error.status === 409 &&\n (error.code === \"subscription_change_refused\" ||\n error.code ===\n \"subscription_change_idempotency_conflict\")))\n ) {\n completeAttempt()\n }\n if (view.current === currentView) {\n toastApiError(error, \"Change subscription\")\n }\n }\n }}\n >\n {change.isPending\n ? \"Applying…\"\n : change.data\n ? change.data.status === \"processing\"\n ? \"Check result\"\n : change.data.status === \"blocked\"\n ? \"Change blocked\"\n : \"Action required\"\n : \"Confirm change\"}\n </Button>\n )}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\nimport { useAdminServices } from \"#orck/admin/context\"\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport { ArrowLeft01Icon } from \"@hugeicons/core-free-icons\"\nimport * as React from \"react\"\nimport { Link, useNavigate, useParams } from \"#orck/admin/router\"\n\nimport { useForm } from \"@tanstack/react-form\"\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\n\nimport { Fact } from \"#orck/admin/components/fact-card\"\nimport { FormFieldErrors } from \"#orck/admin/components/form-field-errors\"\nimport { StatusBadge } from \"#orck/admin/components/status-badge\"\nimport { TypedConfirmDialog } from \"#orck/admin/components/typed-confirm-dialog\"\nimport { Badge } from \"#orck/admin/components/ui/badge\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"#orck/admin/components/ui/dialog\"\nimport { Input } from \"#orck/admin/components/ui/input\"\nimport { Label } from \"#orck/admin/components/ui/label\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"#orck/admin/components/ui/select\"\nimport { Switch } from \"#orck/admin/components/ui/switch\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"#orck/admin/components/ui/table\"\nimport type { ScheduledChange } from \"#orck/admin/lib/api/types\"\nimport { DIALOG_FORM } from \"#orck/admin/lib/dialog-width\"\nimport {\n formatCard,\n formatDate,\n formatNativeAmount,\n shortId,\n} from \"#orck/admin/lib/format\"\n\nimport { ChangeSubscriptionDialog } from \"#orck/admin/pages/subscriptions/change-subscription-dialog\"\nimport { dunningSummary } from \"#orck/admin/pages/subscriptions/dunning\"\nimport { useAdminUpdates } from \"#orck/admin/lib/capabilities\"\n\nexport function SubscriptionDetailPage() {\n const { text: adminText } = useAdminUI()\n\n const { adminQueries } = useAdminServices()\n\n const canUpdate = useAdminUpdates()\n const { id = \"\" } = useParams()\n const navigate = useNavigate()\n const { data: sub, isPending: loading } = useQuery(\n adminQueries.subscription(id)\n )\n const { data: paymentPage } = useQuery(\n adminQueries.payments({ subscription_id: id }, 20)\n )\n const payments = paymentPage?.data ?? []\n if (loading)\n return (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"Loading…\"} />\n </p>\n )\n if (!sub)\n return (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"Subscription not found.\"} />\n </p>\n )\n\n const cancellable =\n sub.status === \"active\" ||\n sub.status === \"past_due\" ||\n sub.status === \"awaiting_method\" ||\n sub.status === \"unverified\"\n const resumable = sub.status === \"canceled\" || sub.status === \"past_due\"\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => navigate(-1)}\n aria-label={adminText(\"Back\")}\n >\n <HugeiconsIcon icon={ArrowLeft01Icon} className=\"size-4\" />\n </Button>\n <div>\n <h2 className=\"flex items-center gap-2 text-sm\">\n {sub.id} <StatusBadge status={sub.status} />\n </h2>\n <p className=\"text-xs text-muted-foreground\">\n {sub.rail} · {sub.rail_subscription_id || \"no rail id\"}\n </p>\n </div>\n <div className=\"ml-auto flex gap-2\">\n {canUpdate && resumable && (\n <ResumeButton id={sub.id} customerId={sub.customer_id} />\n )}\n {canUpdate && (\n <ChangeSubscriptionDialog\n subscriptionId={sub.id}\n customerId={sub.customer_id}\n productId={sub.product_id}\n priceId={sub.price_id}\n quantity={sub.quantity}\n currency={sub.price?.currency}\n collectionPolicy={sub.collection_policy}\n scheduledChange={sub.scheduled_change}\n rail={sub.rail}\n status={sub.status}\n />\n )}\n {canUpdate && (\n <ChangePaymentMethodDialog\n subscriptionId={sub.id}\n customerId={sub.customer_id}\n rail={sub.rail}\n collectionPolicy={sub.collection_policy}\n />\n )}\n {canUpdate && cancellable && (\n <CancelDialog id={sub.id} customerId={sub.customer_id} />\n )}\n </div>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <Fact label={adminText(\"Customer\")}>\n {sub.customer_id ? (\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/customers/${sub.customer_id}`}\n >\n {shortId(sub.customer_id, 13)}\n </Link>\n ) : (\n \"—\"\n )}\n </Fact>\n <Fact label={adminText(\"Started\")}>{formatDate(sub.started_at)}</Fact>\n <Fact label={adminText(\"Current period\")}>\n {formatDate(sub.current_period_starts_at)} →{\" \"}\n {formatDate(sub.current_period_ends_at)}\n </Fact>\n <Fact label={adminText(\"Price\")}>\n <div className=\"flex flex-col gap-1\">\n <span className=\"flex items-center gap-2\">\n {sub.price?.unit_amount !== undefined && sub.price?.currency ? (\n <Link\n className=\"underline-offset-2 hover:underline\"\n to={`/catalog/prices/${encodeURIComponent(sub.price_id)}`}\n >\n {formatNativeAmount(\n sub.price.unit_amount,\n sub.price.currency\n )}\n </Link>\n ) : (\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/catalog/prices/${encodeURIComponent(sub.price_id)}`}\n >\n {shortId(sub.price_id ?? \"—\", 13)}\n </Link>\n )}\n {sub.price?.archived && (\n <Badge\n variant=\"secondary\"\n title={adminText(\"Pinned to an archived (prior) version\")}\n >\n <AdminMessage id={\"prior version\"} />\n </Badge>\n )}\n </span>\n {sub.price?.key && (\n <span className=\"text-xs text-muted-foreground\">\n {sub.price.key}\n </span>\n )}\n {sub.scheduled_change && (\n <ScheduledChangeBadge change={sub.scheduled_change} />\n )}\n </div>\n </Fact>\n {sub.quantity !== null && (\n <Fact label={adminText(\"Seats\")}>\n {sub.quantity}\n {sub.scheduled_change?.quantity != null &&\n ` → ${sub.scheduled_change.quantity} at renewal`}\n </Fact>\n )}\n <Fact label={adminText(\"Dunning\")}>\n {sub.dunning ? dunningSummary(sub.dunning) : \"—\"}\n </Fact>\n <Fact\n label={\n sub.dunning?.waiting_for_new_card ? \"Card deadline\" : \"Final retry\"\n }\n >\n {formatDate(sub.dunning?.final_retry_at)}\n </Fact>\n <Fact label={adminText(\"Last decline\")}>\n {sub.dunning?.last_failure_reason ?? \"—\"}\n </Fact>\n <Fact label={adminText(\"Canceled\")}>\n {sub.canceled_at\n ? `${formatDate(sub.canceled_at)} (${sub.cancel_type ?? \"?\"})`\n : \"—\"}\n </Fact>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">\n <AdminMessage id={\"Payments\"} />\n </CardTitle>\n </CardHeader>\n <CardContent>\n {!payments.length ? (\n <p className=\"text-sm text-muted-foreground\">\n <AdminMessage id={\"No payments recorded.\"} />\n </p>\n ) : (\n <Table>\n <TableHeader>\n <TableRow className=\"hover:bg-transparent\">\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Payment\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Status\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Kind\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Amount\"} />\n </TableHead>\n <TableHead className=\"text-muted-foreground\">\n <AdminMessage id={\"Created\"} />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {payments.map((p) => (\n <TableRow key={p.id}>\n <TableCell>\n <Link\n className=\"text-xs underline-offset-2 hover:underline\"\n to={`/payments/${p.id}`}\n >\n {shortId(p.id, 13)}\n </Link>\n </TableCell>\n <TableCell>\n <StatusBadge status={p.status} />\n </TableCell>\n <TableCell>{p.kind}</TableCell>\n <TableCell>\n {formatNativeAmount(p.amount, p.currency)}\n </TableCell>\n <TableCell>{formatDate(p.created_at)}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n </CardContent>\n </Card>\n </div>\n )\n}\n\nfunction CancelDialog({ id, customerId }: { id: string; customerId?: string }) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const { text: adminText, id: adminId } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const queryClient = useQueryClient()\n const cancel = useMutation(\n adminMutations.cancelSubscription(queryClient, id, customerId)\n )\n const form = useForm({\n defaultValues: { reason: \"\", revokeAccess: false },\n })\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next)\n if (!next) {\n form.reset()\n cancel.reset()\n }\n }\n\n return (\n <>\n <Button variant=\"destructive\" size=\"sm\" onClick={() => setOpen(true)}>\n <AdminMessage id={\"Cancel subscription\"} />\n </Button>\n <TypedConfirmDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={adminText(\"Cancel subscription\")}\n description={adminText(\n \"Terminal cancellation at the payment rail. This is a last resort. Dunning parks subscriptions as past_due without losing entitlements.\"\n )}\n confirmationWord=\"CANCEL\"\n actionLabel=\"Cancel subscription\"\n onConfirm={async () => {\n try {\n await cancel.mutateAsync(form.state.values)\n toast.success(\"Subscription canceled\")\n } catch (err) {\n toastApiError(err, \"Cancel subscription\")\n throw err\n }\n }}\n >\n <div className=\"grid gap-3\">\n <form.Field name=\"reason\">\n {(field) => (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"cancel-reason\")}>\n <AdminMessage id={\"Reason\"} />\n </Label>\n <Input\n id={adminId(\"cancel-reason\")}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(event) => field.handleChange(event.target.value)}\n placeholder={adminText(\"why is this being canceled?\")}\n />\n </div>\n )}\n </form.Field>\n <form.Field name=\"revokeAccess\">\n {(field) => (\n <div className=\"flex items-center gap-2\">\n <Switch\n id={adminId(\"cancel-revoke\")}\n checked={field.state.value}\n onCheckedChange={field.handleChange}\n />\n <Label htmlFor={adminId(\"cancel-revoke\")}>\n <AdminMessage id={\"Also revoke access immediately\"} />\n </Label>\n </div>\n )}\n </form.Field>\n </div>\n </TypedConfirmDialog>\n </>\n )\n}\n\nfunction ResumeButton({ id, customerId }: { id: string; customerId?: string }) {\n const { toast, toastApiError, adminMutations } = useAdminServices()\n\n const queryClient = useQueryClient()\n const resume = useMutation(\n adminMutations.resumeSubscription(queryClient, id, customerId)\n )\n return (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={resume.isPending}\n onClick={async () => {\n try {\n await resume.mutateAsync()\n toast.success(\"Resume queued\")\n } catch (err) {\n toastApiError(err, \"Resume subscription\")\n }\n }}\n >\n {resume.isPending ? \"Queuing…\" : \"Resume\"}\n </Button>\n )\n}\n\n// The choice that makes the subscription follow the customer's default card.\nconst FOLLOW_DEFAULT = \"default\"\n\nfunction ChangePaymentMethodDialog({\n subscriptionId,\n customerId,\n rail,\n collectionPolicy,\n}: {\n subscriptionId: string\n customerId?: string\n rail: string\n collectionPolicy?: string\n}) {\n const { toast, toastApiError, adminMutations, adminQueries } =\n useAdminServices()\n\n const { id: adminId, text: adminText } = useAdminUI()\n\n const [open, setOpen] = React.useState(false)\n const queryClient = useQueryClient()\n const changePaymentMethod = useMutation(\n adminMutations.changeSubscriptionPaymentMethod(\n queryClient,\n subscriptionId,\n customerId\n )\n )\n const { data: pms } = useQuery(\n adminQueries.customerPaymentMethods(open ? customerId : undefined)\n )\n const form = useForm({\n defaultValues: { paymentMethodId: \"\" },\n onSubmit: async ({ value }) => {\n try {\n await changePaymentMethod.mutateAsync(\n value.paymentMethodId === FOLLOW_DEFAULT\n ? null\n : value.paymentMethodId\n )\n toast.success(\"Payment method updated\")\n handleOpenChange(false)\n } catch (err) {\n toastApiError(err, \"Change payment method\")\n }\n },\n })\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next)\n if (!next) {\n form.reset()\n changePaymentMethod.reset()\n }\n }\n\n // A card subscription OpenRails collects, or an NMI schedule; a provider\n // that keeps the card (Stripe-owned, CCBill) or a wallet has none to change.\n const supported =\n rail !== \"solana\" &&\n (collectionPolicy === \"engine\" || collectionPolicy === \"nmi_schedule\")\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogTrigger\n render={\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={!supported}\n title={\n supported\n ? undefined\n : `Payment-method change is not supported on ${rail}`\n }\n >\n <AdminMessage id={\"Change payment method\"} />\n </Button>\n }\n />\n <DialogContent className={DIALOG_FORM}>\n <DialogHeader>\n <DialogTitle>\n <AdminMessage id={\"Change payment method\"} />\n </DialogTitle>\n <DialogDescription>\n <AdminMessage\n id={\n \"Points future renewals of this subscription at another of the customer's stored cards (same rail), or back at their default card for its currency.\"\n }\n />\n </DialogDescription>\n </DialogHeader>\n <form\n onSubmit={(event) => {\n event.preventDefault()\n event.stopPropagation()\n void form.handleSubmit()\n }}\n className=\"grid gap-4\"\n >\n <form.Field\n name=\"paymentMethodId\"\n validators={{\n onChange: ({ value }) =>\n value ? undefined : \"Pick a stored payment method\",\n }}\n >\n {(field) => (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={adminId(\"subscription-payment-method\")}>\n <AdminMessage id={\"Payment method\"} />\n </Label>\n <Select\n value={field.state.value}\n onValueChange={(value) => field.handleChange(value ?? \"\")}\n >\n <SelectTrigger\n className=\"w-full\"\n id={adminId(\"subscription-payment-method\")}\n aria-invalid={field.state.meta.errors.length > 0}\n >\n <SelectValue\n placeholder={adminText(\"Pick a stored payment method\")}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={FOLLOW_DEFAULT}>\n <AdminMessage id={\"The customer's default card\"} />\n </SelectItem>\n {(pms ?? [])\n .filter((pm) => pm.rail === rail)\n .map((pm) => (\n <SelectItem key={pm.id} value={pm.id}>\n {formatCard(pm.card)} ({pm.rail})\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <FormFieldErrors errors={field.state.meta.errors} />\n </div>\n )}\n </form.Field>\n <DialogFooter>\n <form.Subscribe\n selector={(state) =>\n [\n state.values.paymentMethodId,\n state.canSubmit,\n state.isSubmitting,\n ] as const\n }\n >\n {([paymentMethodId, canSubmit, isSubmitting]) => (\n <Button\n type=\"submit\"\n disabled={!paymentMethodId || !canSubmit || isSubmitting}\n >\n {isSubmitting ? \"Updating…\" : \"Update\"}\n </Button>\n )}\n </form.Subscribe>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n\n// ScheduledChangeBadge shows the change waiting for the next renewal: a price\n// migration's move or a scheduled downgrade. A change back to the current\n// price clears it.\nfunction ScheduledChangeBadge({ change }: { change: ScheduledChange }) {\n const { adminQueries } = useAdminServices()\n\n const { data: toPrice } = useQuery(adminQueries.price(change.price_id))\n return (\n <Badge className=\"bg-held-surface text-held\">\n {change.source === \"migration\" ? \"migrates\" : \"changes\"}\n <AdminMessage id={\" to\"} />{\" \"}\n {toPrice\n ? formatNativeAmount(toPrice.unit_amount, toPrice.currency)\n : shortId(change.price_id, 9)}{\" \"}\n <AdminMessage id={\"at the first renewal from \"} />\n {formatDate(change.effective_at)}\n </Badge>\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { f as e, t, w as n } from "./admin-utils-BK4Vh1o_.js";
|
|
2
|
+
import { t as r } from "./admin-button-CTL3DgOt.js";
|
|
3
|
+
import "react";
|
|
4
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
5
|
+
import { XIcon as o } from "lucide-react";
|
|
6
|
+
import { Dialog as s } from "@base-ui/react/dialog";
|
|
7
|
+
//#region src/admin/components/ui/dialog.tsx
|
|
8
|
+
function c({ ...e }) {
|
|
9
|
+
return /* @__PURE__ */ i(s.Root, {
|
|
10
|
+
"data-slot": "dialog",
|
|
11
|
+
...e
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function l({ ...e }) {
|
|
15
|
+
return /* @__PURE__ */ i(s.Trigger, {
|
|
16
|
+
"data-slot": "dialog-trigger",
|
|
17
|
+
...e
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function u({ ...t }) {
|
|
21
|
+
return /* @__PURE__ */ i(s.Portal, {
|
|
22
|
+
container: e().portal,
|
|
23
|
+
"data-slot": "dialog-portal",
|
|
24
|
+
...t
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function d({ className: e, ...n }) {
|
|
28
|
+
return /* @__PURE__ */ i(s.Backdrop, {
|
|
29
|
+
"data-slot": "dialog-overlay",
|
|
30
|
+
className: t("fixed inset-0 isolate z-50 bg-black/10 duration-100 data-closed:animate-out data-closed:fade-out-0 data-open:animate-in data-open:fade-in-0 supports-backdrop-filter:backdrop-blur-xs", e),
|
|
31
|
+
...n
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function f({ className: e, children: c, showCloseButton: l = !0, ...f }) {
|
|
35
|
+
return /* @__PURE__ */ a(u, { children: [/* @__PURE__ */ i(d, {}), /* @__PURE__ */ a(s.Popup, {
|
|
36
|
+
"data-slot": "dialog-content",
|
|
37
|
+
className: t("fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 sm:max-w-sm", e),
|
|
38
|
+
...f,
|
|
39
|
+
children: [c, l && /* @__PURE__ */ a(s.Close, {
|
|
40
|
+
"data-slot": "dialog-close",
|
|
41
|
+
render: /* @__PURE__ */ i(r, {
|
|
42
|
+
variant: "ghost",
|
|
43
|
+
className: "absolute top-2 right-2",
|
|
44
|
+
size: "icon-sm"
|
|
45
|
+
}),
|
|
46
|
+
children: [/* @__PURE__ */ i(o, {}), /* @__PURE__ */ i("span", {
|
|
47
|
+
className: "sr-only",
|
|
48
|
+
children: /* @__PURE__ */ i(n, { id: "Close" })
|
|
49
|
+
})]
|
|
50
|
+
})]
|
|
51
|
+
})] });
|
|
52
|
+
}
|
|
53
|
+
function p({ className: e, ...n }) {
|
|
54
|
+
return /* @__PURE__ */ i("div", {
|
|
55
|
+
"data-slot": "dialog-header",
|
|
56
|
+
className: t("flex flex-col gap-2", e),
|
|
57
|
+
...n
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function m({ className: e, showCloseButton: o = !1, children: c, ...l }) {
|
|
61
|
+
return /* @__PURE__ */ a("div", {
|
|
62
|
+
"data-slot": "dialog-footer",
|
|
63
|
+
className: t("-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end", e),
|
|
64
|
+
...l,
|
|
65
|
+
children: [c, o && /* @__PURE__ */ i(s.Close, {
|
|
66
|
+
render: /* @__PURE__ */ i(r, { variant: "outline" }),
|
|
67
|
+
children: /* @__PURE__ */ i(n, { id: "Close" })
|
|
68
|
+
})]
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function h({ className: e, ...n }) {
|
|
72
|
+
return /* @__PURE__ */ i(s.Title, {
|
|
73
|
+
"data-slot": "dialog-title",
|
|
74
|
+
className: t("font-heading text-base leading-none font-medium", e),
|
|
75
|
+
...n
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function g({ className: e, ...n }) {
|
|
79
|
+
return /* @__PURE__ */ i(s.Description, {
|
|
80
|
+
"data-slot": "dialog-description",
|
|
81
|
+
className: t("text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", e),
|
|
82
|
+
...n
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { p as a, m as i, f as n, h as o, g as r, l as s, c as t };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=admin-dialog-BjuKI5Hp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-dialog-BjuKI5Hp.js","names":[],"sources":["../src/admin/components/ui/dialog.tsx"],"sourcesContent":["\"use client\"\nimport { AdminMessage } from \"#orck/admin/ui-context\"\nimport { useAdminContext } from \"#orck/admin/context\"\n\nimport * as React from \"react\"\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\n\nimport { cn } from \"#orck/admin/lib/utils\"\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Dialog({ ...props }: DialogPrimitive.Root.Props) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {\n return (\n <DialogPrimitive.Portal\n container={useAdminContext().portal}\n data-slot=\"dialog-portal\"\n {...props}\n />\n )\n}\n\nfunction DialogClose({ ...props }: DialogPrimitive.Close.Props) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: DialogPrimitive.Backdrop.Props) {\n return (\n <DialogPrimitive.Backdrop\n data-slot=\"dialog-overlay\"\n className={cn(\n \"fixed inset-0 isolate z-50 bg-black/10 duration-100 data-closed:animate-out data-closed:fade-out-0 data-open:animate-in data-open:fade-in-0 supports-backdrop-filter:backdrop-blur-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: DialogPrimitive.Popup.Props & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Popup\n data-slot=\"dialog-content\"\n className={cn(\n \"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 sm:max-w-sm\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-2 right-2\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon />\n <span className=\"sr-only\">\n <AdminMessage id={\"Close\"} />\n </span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Popup>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showCloseButton?: boolean\n}) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close render={<Button variant=\"outline\" />}>\n <AdminMessage id={\"Close\"} />\n </DialogPrimitive.Close>\n )}\n </div>\n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\n \"font-heading text-base leading-none font-medium\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\n \"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n"],"mappings":";;;;;;;AAWA,SAAS,EAAO,EAAE,GAAG,KAAqC;CACxD,OAAO,kBAAC,EAAgB,MAAjB;EAAsB,aAAU;EAAS,GAAI;CAAQ,CAAA;AAC9D;AAEA,SAAS,EAAc,EAAE,GAAG,KAAwC;CAClE,OAAO,kBAAC,EAAgB,SAAjB;EAAyB,aAAU;EAAiB,GAAI;CAAQ,CAAA;AACzE;AAEA,SAAS,EAAa,EAAE,GAAG,KAAuC;CAChE,OACE,kBAAC,EAAgB,QAAjB;EACE,WAAW,EAAgB,CAAC,CAAC;EAC7B,aAAU;EACV,GAAI;CACL,CAAA;AAEL;AAMA,SAAS,EAAc,EACrB,cACA,GAAG,KAC8B;CACjC,OACE,kBAAC,EAAgB,UAAjB;EACE,aAAU;EACV,WAAW,EACT,yLACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAc,EACrB,cACA,aACA,qBAAkB,IAClB,GAAG,KAGF;CACD,OACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,CAAgB,CAAA,GAChB,kBAAC,EAAgB,OAAjB;EACE,aAAU;EACV,WAAW,EACT,0WACA,CACF;EACA,GAAI;EANN,UAAA,CAQG,GACA,KACC,kBAAC,EAAgB,OAAjB;GACE,aAAU;GACV,QACE,kBAAC,GAAD;IACE,SAAQ;IACR,WAAU;IACV,MAAK;GACN,CAAA;GAPL,UAAA,CAUE,kBAAC,GAAD,CAAQ,CAAA,GACR,kBAAC,QAAD;IAAM,WAAU;IACd,UAAA,kBAAC,GAAD,EAAc,IAAI,QAAU,CAAA;GACxB,CAAA,CACe;EAEJ,CAAA,CAAA;CACX,CAAA,CAAA,EAAA,CAAA;AAElB;AAEA,SAAS,EAAa,EAAE,cAAW,GAAG,KAAsC;CAC1E,OACE,kBAAC,OAAD;EACE,aAAU;EACV,WAAW,EAAG,uBAAuB,CAAS;EAC9C,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAa,EACpB,cACA,qBAAkB,IAClB,aACA,GAAG,KAGF;CACD,OACE,kBAAC,OAAD;EACE,aAAU;EACV,WAAW,EACT,4GACA,CACF;EACA,GAAI;EANN,UAAA,CAQG,GACA,KACC,kBAAC,EAAgB,OAAjB;GAAuB,QAAQ,kBAAC,GAAD,EAAQ,SAAQ,UAAW,CAAA;GACxD,UAAA,kBAAC,GAAD,EAAc,IAAI,QAAU,CAAA;EACP,CAAA,CAEtB;;AAET;AAEA,SAAS,EAAY,EAAE,cAAW,GAAG,KAAsC;CACzE,OACE,kBAAC,EAAgB,OAAjB;EACE,aAAU;EACV,WAAW,EACT,mDACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAkB,EACzB,cACA,GAAG,KACiC;CACpC,OACE,kBAAC,EAAgB,aAAjB;EACE,aAAU;EACV,WAAW,EACT,sGACA,CACF;EACA,GAAI;CACL,CAAA;AAEL"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-dialog-width-BPrgdYlj.js","names":[],"sources":["../src/admin/lib/dialog-width.ts"],"sourcesContent":["// One width scale for every dialog. Always prefix with `sm:`: a bare `max-w-*`\n// overrides the base `max-w-[calc(100%-2rem)]` cap and lets the dialog reach\n// the screen edge on a phone.\n\n/** Destructive confirmations: a sentence, sometimes a typed slug. */\nexport const DIALOG_CONFIRM = \"sm:max-w-md\"\n\n/** The default. Anything a merchant fills in: money, dates, references. */\nexport const DIALOG_FORM = \"sm:max-w-xl\"\n\n/** Forms carrying a live preview or a document alongside the fields. */\nexport const DIALOG_WIDE = \"sm:max-w-2xl\"\n"],"mappings":";AAKA,IAAa,IAAiB,eAGjB,IAAc,eAGd,IAAc"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { E as e, l as t, o as n, w as r } from "./admin-utils-BK4Vh1o_.js";
|
|
2
|
+
import { t as i } from "./admin-button-CTL3DgOt.js";
|
|
3
|
+
import { a, i as o, n as s, r as c, t as l } from "./admin-select-DBgprVW6.js";
|
|
4
|
+
import * as u from "react";
|
|
5
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
6
|
+
import { HugeiconsIcon as p } from "@hugeicons/react";
|
|
7
|
+
import { ArrowLeft01Icon as m, ArrowLeftDoubleIcon as h, ArrowRight01Icon as g } from "@hugeicons/core-free-icons";
|
|
8
|
+
//#region src/admin/lib/cursor-pages.ts
|
|
9
|
+
var _ = [
|
|
10
|
+
25,
|
|
11
|
+
50,
|
|
12
|
+
100
|
|
13
|
+
];
|
|
14
|
+
function v(e, t, n) {
|
|
15
|
+
if (n === 0) return "No rows";
|
|
16
|
+
let r = e * t + 1;
|
|
17
|
+
return `Showing ${r}–${r + n - 1}`;
|
|
18
|
+
}
|
|
19
|
+
function y(e, t = 50) {
|
|
20
|
+
let [n, r] = u.useState({
|
|
21
|
+
filter: e,
|
|
22
|
+
size: t,
|
|
23
|
+
stack: []
|
|
24
|
+
}), i = n.filter === e ? n.stack : [], { size: a } = n;
|
|
25
|
+
return {
|
|
26
|
+
cursor: i.at(-1) ?? "",
|
|
27
|
+
page: i.length,
|
|
28
|
+
size: a,
|
|
29
|
+
setSize: (t) => r({
|
|
30
|
+
filter: e,
|
|
31
|
+
size: t,
|
|
32
|
+
stack: []
|
|
33
|
+
}),
|
|
34
|
+
next: (t) => r({
|
|
35
|
+
filter: e,
|
|
36
|
+
size: a,
|
|
37
|
+
stack: [...i, t]
|
|
38
|
+
}),
|
|
39
|
+
previous: () => r({
|
|
40
|
+
filter: e,
|
|
41
|
+
size: a,
|
|
42
|
+
stack: i.slice(0, -1)
|
|
43
|
+
}),
|
|
44
|
+
first: () => r({
|
|
45
|
+
filter: e,
|
|
46
|
+
size: a,
|
|
47
|
+
stack: []
|
|
48
|
+
})
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function b(e = 50) {
|
|
52
|
+
let [r, i] = t(), a = n().state, o = r.get("cursor") ?? "", s = Number(r.get("limit")), c = _.includes(s) ? s : e, l = a?.cursors ?? [], u = (t, n, a = c) => {
|
|
53
|
+
let o = new URLSearchParams(r);
|
|
54
|
+
t ? o.set("cursor", t) : o.delete("cursor"), a === e ? o.delete("limit") : o.set("limit", String(a)), i(o, { state: { cursors: n } });
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
cursor: o,
|
|
58
|
+
page: o ? Math.max(l.length, 1) : 0,
|
|
59
|
+
size: c,
|
|
60
|
+
setSize: (e) => u("", [], e),
|
|
61
|
+
next: (e) => u(e, [...l, o]),
|
|
62
|
+
previous: () => u(l.at(-1) ?? "", l.slice(0, -1)),
|
|
63
|
+
first: () => u("", [])
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/admin/components/cursor-pager.tsx
|
|
68
|
+
function x({ pages: t, rows: n, nextCursor: u, busy: y, sizes: b = _ }) {
|
|
69
|
+
let { text: x } = e();
|
|
70
|
+
if (t.page === 0 && !u) return null;
|
|
71
|
+
let S = b.includes(t.size) ? b : [...b, t.size].sort((e, t) => e - t);
|
|
72
|
+
return /* @__PURE__ */ f("div", {
|
|
73
|
+
className: "flex flex-wrap items-center justify-between gap-x-6 gap-y-2 text-sm text-muted-foreground",
|
|
74
|
+
children: [/* @__PURE__ */ d("p", {
|
|
75
|
+
className: "tabular-nums",
|
|
76
|
+
"aria-live": "polite",
|
|
77
|
+
children: v(t.page, t.size, n)
|
|
78
|
+
}), /* @__PURE__ */ f("div", {
|
|
79
|
+
className: "flex flex-wrap items-center gap-x-4 gap-y-2",
|
|
80
|
+
children: [/* @__PURE__ */ f("div", {
|
|
81
|
+
className: "flex items-center gap-2",
|
|
82
|
+
children: [/* @__PURE__ */ d("span", { children: /* @__PURE__ */ d(r, { id: "Rows per page" }) }), /* @__PURE__ */ f(l, {
|
|
83
|
+
items: S.map((e) => ({
|
|
84
|
+
value: String(e),
|
|
85
|
+
label: String(e)
|
|
86
|
+
})),
|
|
87
|
+
value: String(t.size),
|
|
88
|
+
onValueChange: (e) => {
|
|
89
|
+
e && t.setSize(Number(e));
|
|
90
|
+
},
|
|
91
|
+
children: [/* @__PURE__ */ d(o, {
|
|
92
|
+
size: "sm",
|
|
93
|
+
"aria-label": x("Rows per page"),
|
|
94
|
+
children: /* @__PURE__ */ d(a, {})
|
|
95
|
+
}), /* @__PURE__ */ d(s, { children: S.map((e) => /* @__PURE__ */ d(c, {
|
|
96
|
+
value: String(e),
|
|
97
|
+
children: e
|
|
98
|
+
}, e)) })]
|
|
99
|
+
})]
|
|
100
|
+
}), /* @__PURE__ */ f("div", {
|
|
101
|
+
className: "flex gap-1",
|
|
102
|
+
children: [
|
|
103
|
+
/* @__PURE__ */ d(i, {
|
|
104
|
+
variant: "ghost",
|
|
105
|
+
size: "icon",
|
|
106
|
+
"aria-label": x("First page"),
|
|
107
|
+
disabled: t.page === 0 || y,
|
|
108
|
+
onClick: t.first,
|
|
109
|
+
children: /* @__PURE__ */ d(p, {
|
|
110
|
+
icon: h,
|
|
111
|
+
className: "size-4"
|
|
112
|
+
})
|
|
113
|
+
}),
|
|
114
|
+
/* @__PURE__ */ d(i, {
|
|
115
|
+
variant: "ghost",
|
|
116
|
+
size: "icon",
|
|
117
|
+
"aria-label": x("Previous page"),
|
|
118
|
+
disabled: t.page === 0 || y,
|
|
119
|
+
onClick: t.previous,
|
|
120
|
+
children: /* @__PURE__ */ d(p, {
|
|
121
|
+
icon: m,
|
|
122
|
+
className: "size-4"
|
|
123
|
+
})
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ d(i, {
|
|
126
|
+
variant: "ghost",
|
|
127
|
+
size: "icon",
|
|
128
|
+
"aria-label": x("Next page"),
|
|
129
|
+
disabled: !u || y,
|
|
130
|
+
onClick: () => u && t.next(u),
|
|
131
|
+
children: /* @__PURE__ */ d(p, {
|
|
132
|
+
icon: g,
|
|
133
|
+
className: "size-4"
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
]
|
|
137
|
+
})]
|
|
138
|
+
})]
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/admin/lib/dom.ts
|
|
143
|
+
function S(e) {
|
|
144
|
+
return !!(e instanceof Element && e.closest("a,button,input,select,textarea,[role='menuitem']"));
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
export { b as i, x as n, y as r, S as t };
|
|
148
|
+
|
|
149
|
+
//# sourceMappingURL=admin-dom-uMmZzRvU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-dom-uMmZzRvU.js","names":[],"sources":["../src/admin/lib/cursor-pages.ts","../src/admin/components/cursor-pager.tsx","../src/admin/lib/dom.ts"],"sourcesContent":["// Paging state for a cursor list: the cursor of the page on screen, the page\n// number, the rows per page, and moves. A cursor list has no total, so the\n// pager offers first, previous and next, never a last page.\nimport * as React from \"react\"\nimport { useLocation, useSearchParams } from \"#orck/admin/router\"\n\nexport interface CursorPages {\n // cursor of the page on screen; \"\" is the first page.\n cursor: string\n // page is 0 on the first page.\n page: number\n size: number\n setSize: (size: number) => void\n next: (cursor: string) => void\n previous: () => void\n first: () => void\n}\n\nexport const PAGE_SIZES = [25, 50, 100]\n\n// shownRange is the \"Showing 51–100\" line for the rows on screen.\nexport function shownRange(page: number, size: number, rows: number): string {\n if (rows === 0) return \"No rows\"\n const start = page * size + 1\n return `Showing ${start}–${start + rows - 1}`\n}\n\n// useCursorPages keeps the position in component state: a new filter key or\n// rows-per-page restarts at the first page.\nexport function useCursorPages(filter: string, defaultSize = 50): CursorPages {\n const [state, setState] = React.useState({\n filter,\n size: defaultSize,\n stack: [] as string[],\n })\n const stack = state.filter === filter ? state.stack : []\n const { size } = state\n return {\n cursor: stack.at(-1) ?? \"\",\n page: stack.length,\n size,\n setSize: (next) => setState({ filter, size: next, stack: [] }),\n next: (cursor) => setState({ filter, size, stack: [...stack, cursor] }),\n previous: () => setState({ filter, size, stack: stack.slice(0, -1) }),\n first: () => setState({ filter, size, stack: [] }),\n }\n}\n\n// useUrlCursor keeps the position in the URL: the page's cursor in `cursor`,\n// rows per page in `limit`, the earlier cursors in the history entry, so Back\n// and reload land on the same page. A link without that history goes\n// Previous to the first page. Dropping `cursor` (a filter change) starts over.\nexport function useUrlCursor(defaultSize = 50): CursorPages {\n const [params, setParams] = useSearchParams()\n const state = useLocation().state as { cursors?: string[] } | null\n const cursor = params.get(\"cursor\") ?? \"\"\n const limit = Number(params.get(\"limit\"))\n const size = PAGE_SIZES.includes(limit) ? limit : defaultSize\n const earlier = state?.cursors ?? []\n const go = (to: string, cursors: string[], nextSize = size) => {\n const p = new URLSearchParams(params)\n if (to) p.set(\"cursor\", to)\n else p.delete(\"cursor\")\n if (nextSize === defaultSize) p.delete(\"limit\")\n else p.set(\"limit\", String(nextSize))\n setParams(p, { state: { cursors } })\n }\n return {\n cursor,\n page: cursor ? Math.max(earlier.length, 1) : 0,\n size,\n setSize: (next) => go(\"\", [], next),\n next: (to) => go(to, [...earlier, cursor]),\n previous: () => go(earlier.at(-1) ?? \"\", earlier.slice(0, -1)),\n first: () => go(\"\", []),\n }\n}\n","import { AdminMessage, useAdminUI } from \"#orck/admin/ui-context\"\n// Pager for a cursor list: which rows are on screen (announced), rows per\n// page, and first, previous and next. A single page needs no pager.\nimport { HugeiconsIcon } from \"@hugeicons/react\"\nimport {\n ArrowLeft01Icon,\n ArrowLeftDoubleIcon,\n ArrowRight01Icon,\n} from \"@hugeicons/core-free-icons\"\n\nimport { Button } from \"#orck/admin/components/ui/button\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"#orck/admin/components/ui/select\"\nimport {\n PAGE_SIZES,\n shownRange,\n type CursorPages,\n} from \"#orck/admin/lib/cursor-pages\"\n\nexport function CursorPager({\n pages,\n rows,\n nextCursor,\n busy,\n sizes = PAGE_SIZES,\n}: {\n pages: CursorPages\n // rows is how many rows the page on screen holds.\n rows: number\n nextCursor: string | null | undefined\n busy?: boolean\n sizes?: number[]\n}) {\n const { text: adminText } = useAdminUI()\n\n if (pages.page === 0 && !nextCursor) return null\n const choices = sizes.includes(pages.size)\n ? sizes\n : [...sizes, pages.size].sort((a, b) => a - b)\n return (\n <div className=\"flex flex-wrap items-center justify-between gap-x-6 gap-y-2 text-sm text-muted-foreground\">\n <p className=\"tabular-nums\" aria-live=\"polite\">\n {shownRange(pages.page, pages.size, rows)}\n </p>\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n <div className=\"flex items-center gap-2\">\n <span>\n <AdminMessage id={\"Rows per page\"} />\n </span>\n <Select\n items={choices.map((n) => ({ value: String(n), label: String(n) }))}\n value={String(pages.size)}\n onValueChange={(value) => {\n if (value) pages.setSize(Number(value))\n }}\n >\n <SelectTrigger size=\"sm\" aria-label={adminText(\"Rows per page\")}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {choices.map((n) => (\n <SelectItem key={n} value={String(n)}>\n {n}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={adminText(\"First page\")}\n disabled={pages.page === 0 || busy}\n onClick={pages.first}\n >\n <HugeiconsIcon icon={ArrowLeftDoubleIcon} className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={adminText(\"Previous page\")}\n disabled={pages.page === 0 || busy}\n onClick={pages.previous}\n >\n <HugeiconsIcon icon={ArrowLeft01Icon} className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={adminText(\"Next page\")}\n disabled={!nextCursor || busy}\n onClick={() => nextCursor && pages.next(nextCursor)}\n >\n <HugeiconsIcon icon={ArrowRight01Icon} className=\"size-4\" />\n </Button>\n </div>\n </div>\n </div>\n )\n}\n","// Buttons, links and fields inside a clickable container own their own clicks;\n// the container must not act on a click that was meant for them.\nexport function isInteractiveTarget(target: EventTarget | null): boolean {\n return Boolean(\n target instanceof Element &&\n target.closest(\"a,button,input,select,textarea,[role='menuitem']\")\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { f as e, t } from "./admin-utils-BK4Vh1o_.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
4
|
+
import { Menu as r } from "@base-ui/react/menu";
|
|
5
|
+
import "lucide-react";
|
|
6
|
+
//#region src/admin/components/ui/dropdown-menu.tsx
|
|
7
|
+
function i({ ...e }) {
|
|
8
|
+
return /* @__PURE__ */ n(r.Root, {
|
|
9
|
+
"data-slot": "dropdown-menu",
|
|
10
|
+
...e
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function a({ ...e }) {
|
|
14
|
+
return /* @__PURE__ */ n(r.Trigger, {
|
|
15
|
+
"data-slot": "dropdown-menu-trigger",
|
|
16
|
+
...e
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function o({ align: i = "start", alignOffset: a = 0, side: o = "bottom", sideOffset: s = 4, className: c, ...l }) {
|
|
20
|
+
return /* @__PURE__ */ n(r.Portal, {
|
|
21
|
+
container: e().portal,
|
|
22
|
+
children: /* @__PURE__ */ n(r.Positioner, {
|
|
23
|
+
className: "isolate z-50 outline-none",
|
|
24
|
+
align: i,
|
|
25
|
+
alignOffset: a,
|
|
26
|
+
side: o,
|
|
27
|
+
sideOffset: s,
|
|
28
|
+
children: /* @__PURE__ */ n(r.Popup, {
|
|
29
|
+
"data-slot": "dropdown-menu-content",
|
|
30
|
+
className: t("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", c),
|
|
31
|
+
...l
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function s({ ...e }) {
|
|
37
|
+
return /* @__PURE__ */ n(r.Group, {
|
|
38
|
+
"data-slot": "dropdown-menu-group",
|
|
39
|
+
...e
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function c({ className: e, inset: i, ...a }) {
|
|
43
|
+
return /* @__PURE__ */ n(r.GroupLabel, {
|
|
44
|
+
"data-slot": "dropdown-menu-label",
|
|
45
|
+
"data-inset": i,
|
|
46
|
+
className: t("px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7", e),
|
|
47
|
+
...a
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function l({ className: e, inset: i, variant: a = "default", ...o }) {
|
|
51
|
+
return /* @__PURE__ */ n(r.Item, {
|
|
52
|
+
"data-slot": "dropdown-menu-item",
|
|
53
|
+
"data-inset": i,
|
|
54
|
+
"data-variant": a,
|
|
55
|
+
className: t("group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive", e),
|
|
56
|
+
...o
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function u({ className: e, ...i }) {
|
|
60
|
+
return /* @__PURE__ */ n(r.Separator, {
|
|
61
|
+
"data-slot": "dropdown-menu-separator",
|
|
62
|
+
className: t("-mx-1 my-1 h-px bg-border", e),
|
|
63
|
+
...i
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { c as a, l as i, o as n, u as o, s as r, a as s, i as t };
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=admin-dropdown-menu-BW1D_h6s.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-dropdown-menu-BW1D_h6s.js","names":[],"sources":["../src/admin/components/ui/dropdown-menu.tsx"],"sourcesContent":["\"use client\"\nimport { useAdminContext } from \"#orck/admin/context\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\n\nimport { cn } from \"#orck/admin/lib/utils\"\nimport { ChevronRightIcon, CheckIcon } from \"lucide-react\"\n\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n return (\n <MenuPrimitive.Portal\n container={useAdminContext().portal}\n data-slot=\"dropdown-menu-portal\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n className,\n ...props\n}: MenuPrimitive.Popup.Props &\n Pick<\n MenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <MenuPrimitive.Portal container={useAdminContext().portal}>\n <MenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\n \"z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: MenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: MenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.SubmenuTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground data-popup-open:bg-accent data-popup-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </MenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n align = \"start\",\n alignOffset = -3,\n side = \"right\",\n sideOffset = 0,\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n return (\n <DropdownMenuContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n inset,\n ...props\n}: MenuPrimitive.CheckboxItem.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n data-inset={inset}\n className={cn(\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-checkbox-item-indicator\"\n >\n <MenuPrimitive.CheckboxItemIndicator>\n <CheckIcon />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n )\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\n return (\n <MenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n inset,\n ...props\n}: MenuPrimitive.RadioItem.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n data-inset={inset}\n className={cn(\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-radio-item-indicator\"\n >\n <MenuPrimitive.RadioItemIndicator>\n <CheckIcon />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: MenuPrimitive.Separator.Props) {\n return (\n <MenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n"],"mappings":";;;;;;AASA,SAAS,EAAa,EAAE,GAAG,KAAmC;CAC5D,OAAO,kBAAC,EAAc,MAAf;EAAoB,aAAU;EAAgB,GAAI;CAAQ,CAAA;AACnE;AAYA,SAAS,EAAoB,EAAE,GAAG,KAAsC;CACtE,OAAO,kBAAC,EAAc,SAAf;EAAuB,aAAU;EAAwB,GAAI;CAAQ,CAAA;AAC9E;AAEA,SAAS,EAAoB,EAC3B,WAAQ,SACR,iBAAc,GACd,UAAO,UACP,gBAAa,GACb,cACA,GAAG,KAKA;CACH,OACE,kBAAC,EAAc,QAAf;EAAsB,WAAW,EAAgB,CAAC,CAAC;EACjD,UAAA,kBAAC,EAAc,YAAf;GACE,WAAU;GACH;GACM;GACP;GACM;GAEZ,UAAA,kBAAC,EAAc,OAAf;IACE,aAAU;IACV,WAAW,EACT,qoBACA,CACF;IACA,GAAI;GACL,CAAA;EACuB,CAAA;CACN,CAAA;AAE1B;AAEA,SAAS,EAAkB,EAAE,GAAG,KAAoC;CAClE,OAAO,kBAAC,EAAc,OAAf;EAAqB,aAAU;EAAsB,GAAI;CAAQ,CAAA;AAC1E;AAEA,SAAS,EAAkB,EACzB,cACA,UACA,GAAG,KAGF;CACD,OACE,kBAAC,EAAc,YAAf;EACE,aAAU;EACV,cAAY;EACZ,WAAW,EACT,yEACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAiB,EACxB,cACA,UACA,aAAU,WACV,GAAG,KAIF;CACD,OACE,kBAAC,EAAc,MAAf;EACE,aAAU;EACV,cAAY;EACZ,gBAAc;EACd,WAAW,EACT,8oBACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AA+HA,SAAS,EAAsB,EAC7B,cACA,GAAG,KAC6B;CAChC,OACE,kBAAC,EAAc,WAAf;EACE,aAAU;EACV,WAAW,EAAG,6BAA6B,CAAS;EACpD,GAAI;CACL,CAAA;AAEL"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { o as e } from "./admin-format-DoohJ7Fg.js";
|
|
2
|
+
//#region src/admin/pages/subscriptions/dunning.ts
|
|
3
|
+
function t(t) {
|
|
4
|
+
let n = `${t.attempts} declined`;
|
|
5
|
+
return t.waiting_for_new_card ? `${n} · needs a new card by ${e(t.final_retry_at)}` : `${n} · ${t.retries_left === null ? "provider retries" : `${t.retries_left} left`}${t.next_retry_at ? ` · next ${e(t.next_retry_at)}` : ""}`;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { t };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=admin-dunning-B2zgtrOo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-dunning-B2zgtrOo.js","names":[],"sources":["../src/admin/pages/subscriptions/dunning.ts"],"sourcesContent":["import type { SubscriptionDunning } from \"#orck/client/generated/wire\"\nimport { formatDate } from \"#orck/admin/lib/format\"\n\n// dunningSummary is one line for a dunning case: the declines so far and\n// what comes next.\nexport function dunningSummary(d: SubscriptionDunning): string {\n const declined = `${d.attempts} declined`\n if (d.waiting_for_new_card)\n return `${declined} · needs a new card by ${formatDate(d.final_retry_at)}`\n const left =\n d.retries_left === null ? \"provider retries\" : `${d.retries_left} left`\n const next = d.next_retry_at ? ` · next ${formatDate(d.next_retry_at)}` : \"\"\n return `${declined} · ${left}${next}`\n}\n"],"mappings":";;AAKA,SAAgB,EAAe,GAAgC;CAC7D,IAAM,IAAW,GAAG,EAAE,SAAS;CAM/B,OALI,EAAE,uBACG,GAAG,EAAS,yBAAyB,EAAW,EAAE,cAAc,MAIlE,GAAG,EAAS,KAFjB,EAAE,iBAAiB,OAAO,qBAAqB,GAAG,EAAE,aAAa,SACtD,EAAE,gBAAgB,WAAW,EAAW,EAAE,aAAa,MAAM;AAE5E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { a as e, o as t, r as n, t as r } from "./admin-card-bzAks3-3.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
|
+
//#region src/admin/components/fact-card.tsx
|
|
5
|
+
function o({ label: o, children: s }) {
|
|
6
|
+
return /* @__PURE__ */ a(r, { children: [/* @__PURE__ */ i(e, {
|
|
7
|
+
className: "pb-1",
|
|
8
|
+
children: /* @__PURE__ */ i(t, {
|
|
9
|
+
className: "text-xs font-normal text-muted-foreground uppercase",
|
|
10
|
+
children: o
|
|
11
|
+
})
|
|
12
|
+
}), /* @__PURE__ */ i(n, {
|
|
13
|
+
className: "text-sm",
|
|
14
|
+
children: s
|
|
15
|
+
})] });
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { o as t };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=admin-fact-card-DO_fHosg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-fact-card-DO_fHosg.js","names":[],"sources":["../src/admin/components/fact-card.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"#orck/admin/components/ui/card\"\n\n// Fact renders one labeled stat tile for a detail page's grid of facts.\nexport function Fact({\n label,\n children,\n}: {\n label: string\n children: React.ReactNode\n}) {\n return (\n <Card>\n <CardHeader className=\"pb-1\">\n <CardTitle className=\"text-xs font-normal text-muted-foreground uppercase\">\n {label}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"text-sm\">{children}</CardContent>\n </Card>\n )\n}\n"],"mappings":";;;;AAUA,SAAgB,EAAK,EACnB,UACA,eAIC;CACD,OACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EAAY,WAAU;EACpB,UAAA,kBAAC,GAAD;GAAW,WAAU;GAClB,UAAA;EACQ,CAAA;CACD,CAAA,GACZ,kBAAC,GAAD;EAAa,WAAU;EAAW;CAAsB,CAAA,CACpD,EAAA,CAAA;AAEV"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
+
//#region src/admin/components/form-field-errors.tsx
|
|
3
|
+
function t({ errors: t }) {
|
|
4
|
+
let n = t.find((e) => typeof e == "string");
|
|
5
|
+
return typeof n == "string" ? /* @__PURE__ */ e("p", {
|
|
6
|
+
role: "alert",
|
|
7
|
+
className: "text-xs text-destructive",
|
|
8
|
+
children: n
|
|
9
|
+
}) : null;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { t };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=admin-form-field-errors-hbUMIriS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-form-field-errors-hbUMIriS.js","names":[],"sources":["../src/admin/components/form-field-errors.tsx"],"sourcesContent":["export function FormFieldErrors({ errors }: { errors: readonly unknown[] }) {\n const message = errors.find((error) => typeof error === \"string\")\n\n return typeof message === \"string\" ? (\n <p role=\"alert\" className=\"text-xs text-destructive\">\n {message}\n </p>\n ) : null\n}\n"],"mappings":";;AAAA,SAAgB,EAAgB,EAAE,aAA0C;CAC1E,IAAM,IAAU,EAAO,MAAM,MAAU,OAAO,KAAU,QAAQ;CAEhE,OAAO,OAAO,KAAY,WACxB,kBAAC,KAAD;EAAG,MAAK;EAAQ,WAAU;EACvB,UAAA;CACA,CAAA,IACD;AACN"}
|