@burdenoff/microfe-billing 2026.526.1 → 2026.528.1

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 (145) hide show
  1. package/dist/billing/BillingAdminRoutes.js +1 -1
  2. package/dist/billing/BillingAdminRoutes.js.map +1 -1
  3. package/dist/billing/BillingUserRoutes.js +1 -1
  4. package/dist/billing/BillingUserRoutes.js.map +1 -1
  5. package/dist/billing/modules/addons/components/FloatingCartDrawer.js +15 -8
  6. package/dist/billing/modules/addons/components/FloatingCartDrawer.js.map +1 -1
  7. package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js +13 -6
  8. package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js.map +1 -1
  9. package/dist/billing/modules/addons/pages/AddonCreatePage.js +1 -1
  10. package/dist/billing/modules/addons/pages/AddonCreatePage.js.map +1 -1
  11. package/dist/billing/modules/addons/pages/AddonDetailPage.js +8 -4
  12. package/dist/billing/modules/addons/pages/AddonDetailPage.js.map +1 -1
  13. package/dist/billing/modules/addons/pages/AddonEditPage.js +3 -2
  14. package/dist/billing/modules/addons/pages/AddonEditPage.js.map +1 -1
  15. package/dist/billing/modules/addons/pages/AddonsBrowsePage.js +44 -23
  16. package/dist/billing/modules/addons/pages/AddonsBrowsePage.js.map +1 -1
  17. package/dist/billing/modules/addons/pages/AddonsListPage.js +60 -31
  18. package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
  19. package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js +9 -9
  20. package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js.map +1 -1
  21. package/dist/billing/modules/analytics/pages/AnalyticsPage.js +8 -8
  22. package/dist/billing/modules/analytics/pages/AnalyticsPage.js.map +1 -1
  23. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +16 -10
  24. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
  25. package/dist/billing/modules/billing/pages/InvoicesListPage.js +24 -16
  26. package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
  27. package/dist/billing/modules/billing/pages/PaymentMethodsPage.js +5 -1
  28. package/dist/billing/modules/billing/pages/PaymentMethodsPage.js.map +1 -1
  29. package/dist/billing/modules/billing/pages/RefundsPage.js +46 -29
  30. package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
  31. package/dist/billing/modules/billing/pages/TransactionsPage.js +34 -22
  32. package/dist/billing/modules/billing/pages/TransactionsPage.js.map +1 -1
  33. package/dist/billing/modules/checkout/components/BillingAccountSelector.js +10 -10
  34. package/dist/billing/modules/checkout/components/BillingAccountSelector.js.map +1 -1
  35. package/dist/billing/modules/checkout/components/CreditsAmountInput.js +3 -3
  36. package/dist/billing/modules/checkout/components/CreditsAmountInput.js.map +1 -1
  37. package/dist/billing/modules/checkout/components/NativeCheckoutView.js +7 -0
  38. package/dist/billing/modules/checkout/components/NativeCheckoutView.js.map +1 -1
  39. package/dist/billing/modules/checkout/components/OrderSummary.js +13 -13
  40. package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
  41. package/dist/billing/modules/checkout/components/PromoCodeInput.js +5 -5
  42. package/dist/billing/modules/checkout/components/PromoCodeInput.js.map +1 -1
  43. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js +5 -5
  44. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js.map +1 -1
  45. package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js +4 -4
  46. package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js.map +1 -1
  47. package/dist/billing/modules/checkout/components/StripePaymentForm.js +11 -11
  48. package/dist/billing/modules/checkout/components/StripePaymentForm.js.map +1 -1
  49. package/dist/billing/modules/checkout/components/SubscriptionSelector.js +3 -3
  50. package/dist/billing/modules/checkout/components/SubscriptionSelector.js.map +1 -1
  51. package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js +8 -8
  52. package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js.map +1 -1
  53. package/dist/billing/modules/checkout/pages/CheckoutPage.js +61 -52
  54. package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
  55. package/dist/billing/modules/coupons/pages/CouponDetailPage.js +22 -15
  56. package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
  57. package/dist/billing/modules/coupons/pages/CouponsListPage.js +30 -21
  58. package/dist/billing/modules/coupons/pages/CouponsListPage.js.map +1 -1
  59. package/dist/billing/modules/coupons/pages/CreateCouponPage.js +9 -8
  60. package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
  61. package/dist/billing/modules/coupons/pages/EditCouponPage.js +11 -8
  62. package/dist/billing/modules/coupons/pages/EditCouponPage.js.map +1 -1
  63. package/dist/billing/modules/credits/pages/AdminCreditsPage.js +1 -1
  64. package/dist/billing/modules/credits/pages/AdminCreditsPage.js.map +1 -1
  65. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +22 -17
  66. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
  67. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +15 -8
  68. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
  69. package/dist/billing/modules/credits/pages/CreditsPage.js +17 -11
  70. package/dist/billing/modules/credits/pages/CreditsPage.js.map +1 -1
  71. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js +15 -11
  72. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js.map +1 -1
  73. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +21 -17
  74. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
  75. package/dist/billing/modules/dashboard/components/BillingAccountCard.js +14 -11
  76. package/dist/billing/modules/dashboard/components/BillingAccountCard.js.map +1 -1
  77. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js +32 -26
  78. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js.map +1 -1
  79. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js +14 -10
  80. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js.map +1 -1
  81. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +18 -11
  82. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
  83. package/dist/billing/modules/dashboard/pages/OverviewPage.js +44 -32
  84. package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
  85. package/dist/billing/modules/discounts/pages/DiscountsListPage.js +35 -26
  86. package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
  87. package/dist/billing/modules/earnings/pages/EarningsPage.js +15 -15
  88. package/dist/billing/modules/earnings/pages/EarningsPage.js.map +1 -1
  89. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +11 -11
  90. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
  91. package/dist/billing/modules/earnings/pages/PayoutsPage.js +5 -5
  92. package/dist/billing/modules/earnings/pages/PayoutsPage.js.map +1 -1
  93. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js +9 -4
  94. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js.map +1 -1
  95. package/dist/billing/modules/plans/pages/PlanCreatePage.js +1 -1
  96. package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
  97. package/dist/billing/modules/plans/pages/PlanDetailPage.js +13 -8
  98. package/dist/billing/modules/plans/pages/PlanDetailPage.js.map +1 -1
  99. package/dist/billing/modules/plans/pages/PlanEditPage.js +3 -2
  100. package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
  101. package/dist/billing/modules/plans/pages/PlansBrowsePage.js +14 -7
  102. package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
  103. package/dist/billing/modules/plans/pages/PlansListPage.js +23 -9
  104. package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
  105. package/dist/billing/modules/quota/pages/QuotaPage.js +11 -7
  106. package/dist/billing/modules/quota/pages/QuotaPage.js.map +1 -1
  107. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +3 -3
  108. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
  109. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js +6 -2
  110. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js.map +1 -1
  111. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +5 -4
  112. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
  113. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +26 -12
  114. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
  115. package/dist/billing/modules/settings/pages/SettingsPage.js +356 -349
  116. package/dist/billing/modules/settings/pages/SettingsPage.js.map +1 -1
  117. package/dist/billing/modules/settings/pages/TeamPermissionsPage.js +157 -123
  118. package/dist/billing/modules/settings/pages/TeamPermissionsPage.js.map +1 -1
  119. package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js +13 -8
  120. package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js.map +1 -1
  121. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +15 -7
  122. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
  123. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +30 -20
  124. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
  125. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +25 -16
  126. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
  127. package/dist/billing/modules/usage/pages/UsagePage.js +50 -34
  128. package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
  129. package/dist/billing/shared/components/AccessDenied.js +2 -2
  130. package/dist/billing/shared/components/AccessDenied.js.map +1 -1
  131. package/dist/billing/shared/components/ActorIdentity.js +67 -0
  132. package/dist/billing/shared/components/ActorIdentity.js.map +1 -0
  133. package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js +6 -2
  134. package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js.map +1 -1
  135. package/dist/billing/shared/components/EmptyState.js +7 -21
  136. package/dist/billing/shared/components/EmptyState.js.map +1 -1
  137. package/dist/billing/shared/components/PageHeader.js +7 -19
  138. package/dist/billing/shared/components/PageHeader.js.map +1 -1
  139. package/dist/billing/shared/components/ServerError.js +5 -4
  140. package/dist/billing/shared/components/ServerError.js.map +1 -1
  141. package/dist/billing/shared/components/index.js +1 -0
  142. package/dist/billing/shared/hooks/index.js +1 -0
  143. package/dist/billing/shared/hooks/useActorProfiles.js +113 -0
  144. package/dist/billing/shared/hooks/useActorProfiles.js.map +1 -0
  145. package/package.json +2 -2
@@ -47,9 +47,9 @@ var S = () => {
47
47
  className: "text-center space-y-2",
48
48
  children: [
49
49
  /* @__PURE__ */ _("div", {
50
- className: "w-12 h-12 mx-auto rounded-full bg-muted flex items-center justify-center",
50
+ className: "size-12 mx-auto rounded-full bg-muted flex items-center justify-center",
51
51
  children: /* @__PURE__ */ _("svg", {
52
- className: "w-6 h-6 text-muted-foreground",
52
+ className: "size-6 text-muted-foreground",
53
53
  fill: "none",
54
54
  viewBox: "0 0 24 24",
55
55
  stroke: "currentColor",
@@ -113,9 +113,9 @@ var S = () => {
113
113
  className: "text-center space-y-4",
114
114
  children: [
115
115
  /* @__PURE__ */ _("div", {
116
- className: "w-12 h-12 mx-auto rounded-full bg-destructive/10 flex items-center justify-center",
116
+ className: "size-12 mx-auto rounded-full bg-destructive/10 flex items-center justify-center",
117
117
  children: /* @__PURE__ */ _("svg", {
118
- className: "w-6 h-6 text-destructive",
118
+ className: "size-6 text-destructive",
119
119
  fill: "none",
120
120
  viewBox: "0 0 24 24",
121
121
  stroke: "currentColor",
@@ -136,6 +136,7 @@ var S = () => {
136
136
  children: p.message
137
137
  }),
138
138
  /* @__PURE__ */ _("button", {
139
+ type: "button",
139
140
  onClick: () => m(),
140
141
  className: "px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors",
141
142
  children: "Try Again"
@@ -154,10 +155,11 @@ var S = () => {
154
155
  className: "text-sm text-muted-foreground mt-1",
155
156
  children: t("billing.addons.subtitle", "Enhance your subscription with additional features")
156
157
  })] }), l.canManageAddons && /* @__PURE__ */ v("button", {
158
+ type: "button",
157
159
  onClick: () => n("/addons/new"),
158
160
  className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors",
159
161
  children: [/* @__PURE__ */ _("svg", {
160
- className: "w-4 h-4",
162
+ className: "size-4",
161
163
  fill: "none",
162
164
  viewBox: "0 0 24 24",
163
165
  stroke: "currentColor",
@@ -177,16 +179,19 @@ var S = () => {
177
179
  className: "inline-flex rounded-lg border border-border p-1 bg-muted/50",
178
180
  children: [
179
181
  /* @__PURE__ */ _("button", {
182
+ type: "button",
180
183
  onClick: () => N("all"),
181
184
  className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${M === "all" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
182
185
  children: "All"
183
186
  }),
184
187
  /* @__PURE__ */ _("button", {
188
+ type: "button",
185
189
  onClick: () => N("monthly"),
186
190
  className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${M === "monthly" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
187
191
  children: "Monthly"
188
192
  }),
189
193
  /* @__PURE__ */ _("button", {
194
+ type: "button",
190
195
  onClick: () => N("yearly"),
191
196
  className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${M === "yearly" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
192
197
  children: "Yearly"
@@ -199,7 +204,7 @@ var S = () => {
199
204
  type: "checkbox",
200
205
  checked: A,
201
206
  onChange: (e) => j(e.target.checked),
202
- className: "w-4 h-4 rounded border-border text-primary focus:ring-primary"
207
+ className: "size-4 rounded border-border text-primary focus:ring-primary"
203
208
  }), /* @__PURE__ */ _("span", {
204
209
  className: "text-muted-foreground",
205
210
  children: t("billing.addons.showInactive", "Show inactive addons")
@@ -208,11 +213,12 @@ var S = () => {
208
213
  /* @__PURE__ */ v("div", {
209
214
  className: "ml-auto inline-flex rounded-lg border border-border p-1 bg-muted/50",
210
215
  children: [/* @__PURE__ */ _("button", {
216
+ type: "button",
211
217
  onClick: () => k("grid"),
212
218
  className: `p-1.5 rounded-md transition-colors ${O === "grid" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
213
219
  title: "Grid view",
214
220
  children: /* @__PURE__ */ _("svg", {
215
- className: "w-4 h-4",
221
+ className: "size-4",
216
222
  fill: "none",
217
223
  viewBox: "0 0 24 24",
218
224
  stroke: "currentColor",
@@ -224,11 +230,12 @@ var S = () => {
224
230
  })
225
231
  })
226
232
  }), /* @__PURE__ */ _("button", {
233
+ type: "button",
227
234
  onClick: () => k("list"),
228
235
  className: `p-1.5 rounded-md transition-colors ${O === "list" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
229
236
  title: "List view",
230
237
  children: /* @__PURE__ */ _("svg", {
231
- className: "w-4 h-4",
238
+ className: "size-4",
232
239
  fill: "none",
233
240
  viewBox: "0 0 24 24",
234
241
  stroke: "currentColor",
@@ -247,9 +254,9 @@ var S = () => {
247
254
  className: "flex flex-col items-center justify-center py-12 border border-dashed border-border rounded-lg",
248
255
  children: [
249
256
  /* @__PURE__ */ _("div", {
250
- className: "w-12 h-12 rounded-full bg-muted flex items-center justify-center mb-4",
257
+ className: "size-12 rounded-full bg-muted flex items-center justify-center mb-4",
251
258
  children: /* @__PURE__ */ _("svg", {
252
- className: "w-6 h-6 text-muted-foreground",
259
+ className: "size-6 text-muted-foreground",
253
260
  fill: "none",
254
261
  viewBox: "0 0 24 24",
255
262
  stroke: "currentColor",
@@ -270,6 +277,7 @@ var S = () => {
270
277
  children: A ? t("billing.addons.noAddonsFiltered", "No addons match your current filters.") : t("billing.addons.noActiveAddons", "There are no active addons available.")
271
278
  }),
272
279
  l.canManageAddons && /* @__PURE__ */ _("button", {
280
+ type: "button",
273
281
  onClick: () => n("/addons/new"),
274
282
  className: "mt-4 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors",
275
283
  children: t("billing.addons.createFirstAddon", "Create your first addon")
@@ -335,9 +343,9 @@ var S = () => {
335
343
  ]
336
344
  }),
337
345
  /* @__PURE__ */ _("div", {
338
- className: "w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center mb-4",
346
+ className: "size-10 rounded-lg bg-primary/10 flex items-center justify-center mb-4",
339
347
  children: /* @__PURE__ */ _("svg", {
340
- className: "w-5 h-5 text-primary",
348
+ className: "size-5 text-primary",
341
349
  fill: "none",
342
350
  viewBox: "0 0 24 24",
343
351
  stroke: "currentColor",
@@ -379,7 +387,7 @@ var S = () => {
379
387
  children: [/* @__PURE__ */ v("div", {
380
388
  className: "flex items-center gap-2",
381
389
  children: [/* @__PURE__ */ _("svg", {
382
- className: "w-4 h-4 text-status-success-text shrink-0",
390
+ className: "size-4 text-status-success-text shrink-0",
383
391
  fill: "none",
384
392
  viewBox: "0 0 24 24",
385
393
  stroke: "currentColor",
@@ -415,32 +423,37 @@ var S = () => {
415
423
  className: "flex items-center gap-1",
416
424
  children: [
417
425
  /* @__PURE__ */ _("button", {
426
+ type: "button",
418
427
  onClick: () => S(r.id, g - 1),
419
428
  className: "p-1.5 rounded border border-border hover:bg-muted transition-colors",
420
- children: /* @__PURE__ */ _(d, { className: "w-4 h-4" })
429
+ children: /* @__PURE__ */ _(d, { className: "size-4" })
421
430
  }),
422
431
  /* @__PURE__ */ _("span", {
423
432
  className: "w-10 text-center font-medium",
424
433
  children: g
425
434
  }),
426
435
  /* @__PURE__ */ _("button", {
436
+ type: "button",
427
437
  onClick: () => S(r.id, g + 1),
428
438
  className: "p-1.5 rounded border border-border hover:bg-muted transition-colors",
429
- children: /* @__PURE__ */ _(f, { className: "w-4 h-4" })
439
+ children: /* @__PURE__ */ _(f, { className: "size-4" })
430
440
  })
431
441
  ]
432
442
  }), /* @__PURE__ */ _("button", {
443
+ type: "button",
433
444
  onClick: () => C(r.id),
434
445
  className: "p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors",
435
446
  title: "Remove from cart",
436
- children: /* @__PURE__ */ _(m, { className: "w-4 h-4" })
447
+ children: /* @__PURE__ */ _(m, { className: "size-4" })
437
448
  })]
438
449
  }) : /* @__PURE__ */ v("button", {
450
+ type: "button",
439
451
  onClick: () => y(r),
440
452
  className: "w-full px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors flex items-center justify-center gap-2",
441
- children: [/* @__PURE__ */ _(p, { className: "w-4 h-4" }), "Add to Cart"]
453
+ children: [/* @__PURE__ */ _(p, { className: "size-4" }), "Add to Cart"]
442
454
  })),
443
455
  /* @__PURE__ */ _("button", {
456
+ type: "button",
444
457
  onClick: () => i(r),
445
458
  className: "w-full px-4 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors",
446
459
  children: "View Details"
@@ -448,10 +461,12 @@ var S = () => {
448
461
  s && /* @__PURE__ */ v("div", {
449
462
  className: "flex gap-2",
450
463
  children: [/* @__PURE__ */ _("button", {
464
+ type: "button",
451
465
  onClick: () => a(r),
452
466
  className: "flex-1 px-3 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors",
453
467
  children: "Edit"
454
468
  }), /* @__PURE__ */ _("button", {
469
+ type: "button",
455
470
  onClick: () => o(r),
456
471
  disabled: u,
457
472
  className: `px-3 py-2 text-sm font-medium border border-border rounded-md transition-colors ${r.isActive ? "text-destructive hover:bg-destructive/10" : "text-status-success-text hover:bg-status-success-bg-subtle"}`,
@@ -468,9 +483,9 @@ var S = () => {
468
483
  className: `flex items-center gap-4 p-4 border rounded-lg transition-all hover:shadow-sm ${n.isActive ? u ? "border-primary bg-primary/5" : "border-border bg-card" : "border-dashed border-muted-foreground/30 bg-muted/30"}`,
469
484
  children: [
470
485
  /* @__PURE__ */ _("div", {
471
- className: "w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0",
486
+ className: "size-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0",
472
487
  children: /* @__PURE__ */ _("svg", {
473
- className: "w-5 h-5 text-primary",
488
+ className: "size-5 text-primary",
474
489
  fill: "none",
475
490
  viewBox: "0 0 24 24",
476
491
  stroke: "currentColor",
@@ -530,42 +545,49 @@ var S = () => {
530
545
  className: "flex items-center gap-1",
531
546
  children: [
532
547
  /* @__PURE__ */ _("button", {
548
+ type: "button",
533
549
  onClick: () => S(n.id, h - 1),
534
550
  className: "p-1.5 rounded border border-border hover:bg-muted transition-colors",
535
- children: /* @__PURE__ */ _(d, { className: "w-4 h-4" })
551
+ children: /* @__PURE__ */ _(d, { className: "size-4" })
536
552
  }),
537
553
  /* @__PURE__ */ _("span", {
538
554
  className: "w-8 text-center font-medium",
539
555
  children: h
540
556
  }),
541
557
  /* @__PURE__ */ _("button", {
558
+ type: "button",
542
559
  onClick: () => S(n.id, h + 1),
543
560
  className: "p-1.5 rounded border border-border hover:bg-muted transition-colors",
544
- children: /* @__PURE__ */ _(f, { className: "w-4 h-4" })
561
+ children: /* @__PURE__ */ _(f, { className: "size-4" })
545
562
  }),
546
563
  /* @__PURE__ */ _("button", {
564
+ type: "button",
547
565
  onClick: () => C(n.id),
548
566
  className: "p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors ml-1",
549
567
  title: "Remove from cart",
550
- children: /* @__PURE__ */ _(m, { className: "w-4 h-4" })
568
+ children: /* @__PURE__ */ _(m, { className: "size-4" })
551
569
  })
552
570
  ]
553
571
  }) : /* @__PURE__ */ v("button", {
572
+ type: "button",
554
573
  onClick: () => y(n),
555
574
  className: "px-3 py-1.5 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors flex items-center gap-1.5",
556
- children: [/* @__PURE__ */ _(p, { className: "w-4 h-4" }), "Add"]
575
+ children: [/* @__PURE__ */ _(p, { className: "size-4" }), "Add"]
557
576
  })),
558
577
  /* @__PURE__ */ v("div", {
559
578
  className: "flex items-center gap-2",
560
579
  children: [/* @__PURE__ */ _("button", {
580
+ type: "button",
561
581
  onClick: () => r(n),
562
582
  className: "px-3 py-1.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors",
563
583
  children: "View"
564
584
  }), o && /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _("button", {
585
+ type: "button",
565
586
  onClick: () => i(n),
566
587
  className: "px-3 py-1.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors",
567
588
  children: "Edit"
568
589
  }), /* @__PURE__ */ _("button", {
590
+ type: "button",
569
591
  onClick: () => a(n),
570
592
  disabled: c,
571
593
  className: `px-3 py-1.5 text-sm font-medium border border-border rounded-md transition-colors ${n.isActive ? "text-destructive hover:bg-destructive/10" : "text-status-success-text hover:bg-status-success-bg-subtle"}`,
@@ -577,10 +599,11 @@ var S = () => {
577
599
  }, T = ({ displayCurrency: n }) => {
578
600
  let r = a(), { items: o, isCartOpen: s, toggleCart: c, closeCart: l, removeFromCart: u, updateQuantity: y, clearCart: b } = i(), S = o.reduce((e, t) => e + t.quantity, 0);
579
601
  return o.length === 0 && !s ? null : /* @__PURE__ */ v(g, { children: [!s && o.length > 0 && /* @__PURE__ */ v("button", {
602
+ type: "button",
580
603
  onClick: c,
581
604
  className: "fixed bottom-6 right-6 z-50 flex items-center gap-2 px-4 py-3 bg-primary text-primary-foreground rounded-full shadow-lg hover:bg-primary/90 transition-all",
582
605
  children: [
583
- /* @__PURE__ */ _(p, { className: "w-5 h-5" }),
606
+ /* @__PURE__ */ _(p, { className: "size-5" }),
584
607
  /* @__PURE__ */ v("span", {
585
608
  className: "font-medium",
586
609
  children: [
@@ -610,7 +633,7 @@ var S = () => {
610
633
  children: [/* @__PURE__ */ v("div", {
611
634
  className: "flex items-center gap-2",
612
635
  children: [
613
- /* @__PURE__ */ _(p, { className: "w-5 h-5 text-foreground" }),
636
+ /* @__PURE__ */ _(p, { className: "size-5 text-foreground" }),
614
637
  /* @__PURE__ */ _("h3", {
615
638
  className: "font-semibold text-foreground",
616
639
  children: "Your Cart"
@@ -625,9 +648,10 @@ var S = () => {
625
648
  })
626
649
  ]
627
650
  }), /* @__PURE__ */ _("button", {
651
+ type: "button",
628
652
  onClick: l,
629
653
  className: "p-1.5 rounded hover:bg-muted transition-colors",
630
- children: /* @__PURE__ */ _(h, { className: "w-5 h-5" })
654
+ children: /* @__PURE__ */ _(h, { className: "size-5" })
631
655
  })]
632
656
  }),
633
657
  /* @__PURE__ */ _("div", {
@@ -636,9 +660,9 @@ var S = () => {
636
660
  className: "p-4 flex items-center gap-3",
637
661
  children: [
638
662
  /* @__PURE__ */ _("div", {
639
- className: "w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0",
663
+ className: "size-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0",
640
664
  children: /* @__PURE__ */ _("svg", {
641
- className: "w-5 h-5 text-primary",
665
+ className: "size-5 text-primary",
642
666
  fill: "none",
643
667
  viewBox: "0 0 24 24",
644
668
  stroke: "currentColor",
@@ -672,18 +696,20 @@ var S = () => {
672
696
  className: "flex items-center gap-1",
673
697
  children: [
674
698
  /* @__PURE__ */ _("button", {
699
+ type: "button",
675
700
  onClick: () => y(r.id, i - 1),
676
701
  className: "p-1 rounded border border-border hover:bg-muted transition-colors",
677
- children: /* @__PURE__ */ _(d, { className: "w-3 h-3" })
702
+ children: /* @__PURE__ */ _(d, { className: "size-3" })
678
703
  }),
679
704
  /* @__PURE__ */ _("span", {
680
705
  className: "w-6 text-center text-sm font-medium",
681
706
  children: i
682
707
  }),
683
708
  /* @__PURE__ */ _("button", {
709
+ type: "button",
684
710
  onClick: () => y(r.id, i + 1),
685
711
  className: "p-1 rounded border border-border hover:bg-muted transition-colors",
686
- children: /* @__PURE__ */ _(f, { className: "w-3 h-3" })
712
+ children: /* @__PURE__ */ _(f, { className: "size-3" })
687
713
  })
688
714
  ]
689
715
  }),
@@ -698,9 +724,10 @@ var S = () => {
698
724
  })
699
725
  }),
700
726
  /* @__PURE__ */ _("button", {
727
+ type: "button",
701
728
  onClick: () => u(r.id),
702
729
  className: "p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors",
703
- children: /* @__PURE__ */ _(m, { className: "w-4 h-4" })
730
+ children: /* @__PURE__ */ _(m, { className: "size-4" })
704
731
  })
705
732
  ]
706
733
  }, r.id))
@@ -722,10 +749,12 @@ var S = () => {
722
749
  }), /* @__PURE__ */ v("div", {
723
750
  className: "flex gap-2",
724
751
  children: [/* @__PURE__ */ _("button", {
752
+ type: "button",
725
753
  onClick: b,
726
754
  className: "flex-1 px-4 py-2.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors",
727
755
  children: "Clear Cart"
728
756
  }), /* @__PURE__ */ _("button", {
757
+ type: "button",
729
758
  onClick: () => {
730
759
  l(), r("/checkout/addons");
731
760
  },
@@ -1 +1 @@
1
- {"version":3,"file":"AddonsListPage.js","names":[],"sources":["../../../../../src/billing/modules/addons/pages/AddonsListPage.tsx"],"sourcesContent":["/**\n * Addons Module - Addons List Page\n * Displays all available addons with cart functionality\n */\n\nimport { useState, useMemo, type FC } from 'react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { ShoppingCart, Plus, Minus, Trash2, X } from 'lucide-react';\nimport { useAddons, useAddonMutations } from '../hooks';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { useAddonCartStore } from '../store/addonCartStore';\nimport {\n formatCurrency,\n formatPlanDuration,\n formatPlanDurationLabel,\n} from '../../../shared/utils/format';\nimport type { Addon, PlanDuration, SubscriptionFeatures } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useDefaultBillingCurrency } from '../../../hooks/useDefaultBillingCurrency';\n\ntype ViewMode = 'grid' | 'list';\n\n/**\n * Combined quota info for display\n */\ninterface CombinedQuota {\n quotaId: string;\n name: string;\n totalValue: number;\n}\n\n/**\n * Combines duplicate quotas by quota ID and aggregates their values\n */\nfunction combineQuotas(features: SubscriptionFeatures[]): CombinedQuota[] {\n const quotaMap = new Map<string, CombinedQuota>();\n\n for (const feature of features) {\n if (!feature.quota) continue;\n\n const quotaId = feature.quota.id;\n const limits = feature.quota.limits as { value?: number } | null;\n const limitValue = limits?.value ?? 0;\n\n const existing = quotaMap.get(quotaId);\n if (existing) {\n existing.totalValue += limitValue;\n } else {\n quotaMap.set(quotaId, {\n quotaId,\n name: feature.quota.name ?? 'Unknown Quota',\n totalValue: limitValue,\n });\n }\n }\n\n return Array.from(quotaMap.values());\n}\n\n/**\n * Get the display price and currency for an addon\n * Uses currencyPrices if available, otherwise falls back to base price\n */\nfunction getAddonDisplayPrice(\n addon: Addon,\n displayCurrency: string = 'USD'\n): { price: number; currency: string } {\n // If currencyPrices exists and has the requested currency, use it\n if (addon.currencyPrices && typeof addon.currencyPrices === 'object') {\n const currencyPricesObj = addon.currencyPrices as Record<string, number>;\n if (currencyPricesObj[displayCurrency]) {\n return {\n price: currencyPricesObj[displayCurrency],\n currency: displayCurrency,\n };\n }\n }\n\n // Fallback to base USD price\n return {\n price: addon.price,\n currency: addon.currency || 'USD',\n };\n}\n\nexport const AddonsListPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const navigateTo = useBillingNavigate();\n const permissions = useBillingPermissions();\n const { addons, isLoading, error, refetch } = useAddons();\n const { toggleAddon, isToggling } = useAddonMutations();\n const { addToCart, removeFromCart, updateQuantity, isInCart, getCartItem } = useAddonCartStore();\n\n const [viewMode, setViewMode] = useState<ViewMode>('grid');\n const [showInactive, setShowInactive] = useState(false);\n const [billingInterval, setBillingInterval] = useState<PlanDuration | 'all'>('all');\n const displayCurrency = useDefaultBillingCurrency();\n\n // Permission check\n if (!permissions.canViewAddons) {\n return (\n <div className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <div className=\"w-12 h-12 mx-auto rounded-full bg-muted flex items-center justify-center\">\n <svg\n className=\"w-6 h-6 text-muted-foreground\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n </div>\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('billing.accessDenied.title', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-muted-foreground max-w-sm\">\n {tr('billing.addons.noViewPermission', \"You don't have permission to view addons.\")}\n </p>\n </div>\n </div>\n );\n }\n\n // Filter addons\n const filteredAddons = addons.filter((addon) => {\n if (!showInactive && !addon.isActive) return false;\n if (billingInterval !== 'all' && addon.duration !== billingInterval) return false;\n return true;\n });\n\n const handleToggleAddon = async (addon: Addon) => {\n if (!permissions.canManageAddons) return;\n try {\n await toggleAddon(addon.id, !addon.isActive);\n await refetch();\n } catch (err) {\n console.error('Failed to toggle addon:', err);\n }\n };\n\n const handleViewAddon = (addon: Addon) => {\n navigateTo(`/addons/${addon.id}`);\n };\n\n const handleEditAddon = (addon: Addon) => {\n navigateTo(`/addons/${addon.id}/edit`);\n };\n\n // Loading state\n if (isLoading && addons.length === 0) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-muted animate-pulse rounded\" />\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"border border-border rounded-lg p-6 space-y-4\">\n <div className=\"h-6 w-24 bg-muted animate-pulse rounded\" />\n <div className=\"h-8 w-32 bg-muted animate-pulse rounded\" />\n <div className=\"space-y-2\">\n {[1, 2, 3].map((j) => (\n <div key={j} className=\"h-4 w-full bg-muted animate-pulse rounded\" />\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-4\">\n <div className=\"w-12 h-12 mx-auto rounded-full bg-destructive/10 flex items-center justify-center\">\n <svg\n className=\"w-6 h-6 text-destructive\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('billing.addons.failedToLoad', 'Failed to load addons')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">{error.message}</p>\n <button\n onClick={() => refetch()}\n className=\"px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n Try Again\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">\n {tr('billing.addons.title', 'Addons')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {tr('billing.addons.subtitle', 'Enhance your subscription with additional features')}\n </p>\n </div>\n\n {permissions.canManageAddons && (\n <button\n onClick={() => navigateTo('/addons/new')}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n Create Addon\n </button>\n )}\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-wrap items-center gap-4 pb-4 border-b border-border\">\n {/* Billing Interval Toggle */}\n <div className=\"inline-flex rounded-lg border border-border p-1 bg-muted/50\">\n <button\n onClick={() => setBillingInterval('all')}\n className={`px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${\n billingInterval === 'all'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n All\n </button>\n <button\n onClick={() => setBillingInterval('monthly' as PlanDuration)}\n className={`px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${\n billingInterval === 'monthly'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n Monthly\n </button>\n <button\n onClick={() => setBillingInterval('yearly' as PlanDuration)}\n className={`px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${\n billingInterval === 'yearly'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n Yearly\n </button>\n </div>\n\n {/* Show Inactive Toggle */}\n {permissions.canManageAddons && (\n <label className=\"flex items-center gap-2 text-sm cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={showInactive}\n onChange={(e) => setShowInactive(e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-primary focus:ring-primary\"\n />\n <span className=\"text-muted-foreground\">\n {tr('billing.addons.showInactive', 'Show inactive addons')}\n </span>\n </label>\n )}\n\n {/* View Mode Toggle */}\n <div className=\"ml-auto inline-flex rounded-lg border border-border p-1 bg-muted/50\">\n <button\n onClick={() => setViewMode('grid')}\n className={`p-1.5 rounded-md transition-colors ${\n viewMode === 'grid'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n title=\"Grid view\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z\"\n />\n </svg>\n </button>\n <button\n onClick={() => setViewMode('list')}\n className={`p-1.5 rounded-md transition-colors ${\n viewMode === 'list'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n title=\"List view\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 12h16M4 18h16\"\n />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Addons Grid/List */}\n {filteredAddons.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 border border-dashed border-border rounded-lg\">\n <div className=\"w-12 h-12 rounded-full bg-muted flex items-center justify-center mb-4\">\n <svg\n className=\"w-6 h-6 text-muted-foreground\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n </div>\n <h3 className=\"text-lg font-medium text-foreground\">\n {tr('billing.addons.noAddonsFound', 'No addons found')}\n </h3>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {showInactive\n ? tr('billing.addons.noAddonsFiltered', 'No addons match your current filters.')\n : tr('billing.addons.noActiveAddons', 'There are no active addons available.')}\n </p>\n {permissions.canManageAddons && (\n <button\n onClick={() => navigateTo('/addons/new')}\n className=\"mt-4 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n {tr('billing.addons.createFirstAddon', 'Create your first addon')}\n </button>\n )}\n </div>\n ) : viewMode === 'grid' ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {filteredAddons.map((addon) => {\n const cartItem = getCartItem(addon.id);\n return (\n <AddonCard\n key={addon.id}\n addon={addon}\n onView={handleViewAddon}\n onEdit={handleEditAddon}\n onToggle={handleToggleAddon}\n canManage={permissions.canManageAddons}\n isToggling={isToggling}\n isInCart={isInCart(addon.id)}\n cartQuantity={cartItem?.quantity || 0}\n onAddToCart={addToCart}\n onUpdateQuantity={updateQuantity}\n onRemoveFromCart={removeFromCart}\n displayCurrency={displayCurrency}\n />\n );\n })}\n </div>\n ) : (\n <div className=\"space-y-3\">\n {filteredAddons.map((addon) => {\n const cartItem = getCartItem(addon.id);\n return (\n <AddonRow\n key={addon.id}\n addon={addon}\n onView={handleViewAddon}\n onEdit={handleEditAddon}\n onToggle={handleToggleAddon}\n canManage={permissions.canManageAddons}\n isToggling={isToggling}\n isInCart={isInCart(addon.id)}\n cartQuantity={cartItem?.quantity || 0}\n onAddToCart={addToCart}\n onUpdateQuantity={updateQuantity}\n onRemoveFromCart={removeFromCart}\n displayCurrency={displayCurrency}\n />\n );\n })}\n </div>\n )}\n\n {/* Floating Cart Drawer */}\n <FloatingCartDrawer displayCurrency={displayCurrency} />\n </div>\n );\n};\n\n// ============================================================================\n// Addon Card Component\n// ============================================================================\n\ninterface AddonCardProps {\n addon: Addon;\n onView: (addon: Addon) => void;\n onEdit: (addon: Addon) => void;\n onToggle: (addon: Addon) => void;\n canManage: boolean;\n isToggling: boolean;\n isInCart: boolean;\n cartQuantity: number;\n onAddToCart: (addon: Addon) => void;\n onUpdateQuantity: (addonId: string, quantity: number) => void;\n onRemoveFromCart: (addonId: string) => void;\n displayCurrency: string;\n}\n\nconst AddonCard: FC<AddonCardProps> = ({\n addon,\n onView,\n onEdit,\n onToggle,\n canManage,\n displayCurrency,\n isToggling,\n isInCart,\n cartQuantity,\n onAddToCart,\n onUpdateQuantity,\n onRemoveFromCart,\n}) => {\n const combinedQuotas = useMemo(() => {\n const features = addon.features || [];\n return combineQuotas(features);\n }, [addon.features]);\n\n return (\n <div\n className={`relative border rounded-lg p-6 transition-all hover:shadow-md flex flex-col h-full ${\n addon.isActive\n ? isInCart\n ? 'border-primary bg-primary/5'\n : 'border-border bg-card'\n : 'border-dashed border-muted-foreground/30 bg-muted/30'\n }`}\n >\n {/* Status Badge */}\n {!addon.isActive && (\n <span className=\"absolute top-4 right-4 px-2 py-1 text-xs font-medium bg-muted text-muted-foreground rounded\">\n Inactive\n </span>\n )}\n\n {/* In Cart Badge */}\n {isInCart && addon.isActive && (\n <span className=\"absolute top-4 right-4 px-2 py-1 text-xs font-medium bg-primary text-primary-foreground rounded\">\n In Cart ({cartQuantity})\n </span>\n )}\n\n {/* Addon Icon */}\n <div className=\"w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center mb-4\">\n <svg className=\"w-5 h-5 text-primary\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n </div>\n\n {/* Addon Name */}\n <div className=\"mb-4\">\n <h3 className=\"text-lg font-bold text-foreground\">{addon.name}</h3>\n <span className=\"text-sm text-muted-foreground\">\n {formatPlanDurationLabel(addon.duration)}\n </span>\n </div>\n\n {/* Price */}\n <div className=\"flex items-baseline gap-1 mb-4\">\n <span className=\"text-2xl font-bold text-foreground\">\n {(() => {\n const { price, currency } = getAddonDisplayPrice(addon, displayCurrency);\n return formatCurrency(price, currency);\n })()}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n / {formatPlanDuration(addon.duration)}\n </span>\n </div>\n\n {/* Combined Quotas */}\n {combinedQuotas.length > 0 && (\n <ul className=\"space-y-2 mb-4\">\n {combinedQuotas.slice(0, 4).map((quota) => (\n <li key={quota.quotaId} className=\"flex items-center justify-between text-sm\">\n <div className=\"flex items-center gap-2\">\n <svg\n className=\"w-4 h-4 text-status-success-text shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n <span className=\"text-foreground\">{quota.name}</span>\n </div>\n <span className=\"font-medium text-foreground\">\n {quota.totalValue.toLocaleString()}\n </span>\n </li>\n ))}\n {combinedQuotas.length > 4 && (\n <li className=\"text-sm text-muted-foreground pl-6\">\n +{combinedQuotas.length - 4} more quotas\n </li>\n )}\n </ul>\n )}\n\n {/* Actions - pushed to bottom with mt-auto */}\n <div className=\"space-y-2 pt-4 border-t border-border mt-auto\">\n {/* Add to Cart / Quantity Controls */}\n {addon.isActive &&\n (isInCart ? (\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-1\">\n <button\n onClick={() => onUpdateQuantity(addon.id, cartQuantity - 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Minus className=\"w-4 h-4\" />\n </button>\n <span className=\"w-10 text-center font-medium\">{cartQuantity}</span>\n <button\n onClick={() => onUpdateQuantity(addon.id, cartQuantity + 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Plus className=\"w-4 h-4\" />\n </button>\n </div>\n <button\n onClick={() => onRemoveFromCart(addon.id)}\n className=\"p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors\"\n title=\"Remove from cart\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n ) : (\n <button\n onClick={() => onAddToCart(addon)}\n className=\"w-full px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors flex items-center justify-center gap-2\"\n >\n <ShoppingCart className=\"w-4 h-4\" />\n Add to Cart\n </button>\n ))}\n\n <button\n onClick={() => onView(addon)}\n className=\"w-full px-4 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n View Details\n </button>\n\n {canManage && (\n <div className=\"flex gap-2\">\n <button\n onClick={() => onEdit(addon)}\n className=\"flex-1 px-3 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Edit\n </button>\n <button\n onClick={() => onToggle(addon)}\n disabled={isToggling}\n className={`px-3 py-2 text-sm font-medium border border-border rounded-md transition-colors ${\n addon.isActive\n ? 'text-destructive hover:bg-destructive/10'\n : 'text-status-success-text hover:bg-status-success-bg-subtle'\n }`}\n >\n {addon.isActive ? 'Deactivate' : 'Activate'}\n </button>\n </div>\n )}\n </div>\n </div>\n );\n};\n\n// ============================================================================\n// Addon Row Component (List View)\n// ============================================================================\n\ninterface AddonRowProps {\n addon: Addon;\n onView: (addon: Addon) => void;\n onEdit: (addon: Addon) => void;\n onToggle: (addon: Addon) => void;\n canManage: boolean;\n isToggling: boolean;\n isInCart: boolean;\n cartQuantity: number;\n onAddToCart: (addon: Addon) => void;\n onUpdateQuantity: (addonId: string, quantity: number) => void;\n onRemoveFromCart: (addonId: string) => void;\n displayCurrency: string;\n}\n\nconst AddonRow: FC<AddonRowProps> = ({\n addon,\n onView,\n onEdit,\n onToggle,\n canManage,\n displayCurrency,\n isToggling,\n isInCart,\n cartQuantity,\n onAddToCart,\n onUpdateQuantity,\n onRemoveFromCart,\n}) => {\n const combinedQuotas = useMemo(() => {\n const features = addon.features || [];\n return combineQuotas(features);\n }, [addon.features]);\n\n return (\n <div\n className={`flex items-center gap-4 p-4 border rounded-lg transition-all hover:shadow-sm ${\n addon.isActive\n ? isInCart\n ? 'border-primary bg-primary/5'\n : 'border-border bg-card'\n : 'border-dashed border-muted-foreground/30 bg-muted/30'\n }`}\n >\n {/* Addon Icon */}\n <div className=\"w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0\">\n <svg className=\"w-5 h-5 text-primary\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n </div>\n\n {/* Addon Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-semibold text-foreground truncate\">{addon.name}</h3>\n {!addon.isActive && (\n <span className=\"px-2 py-0.5 text-xs font-medium bg-muted text-muted-foreground rounded\">\n Inactive\n </span>\n )}\n {isInCart && addon.isActive && (\n <span className=\"px-2 py-0.5 text-xs font-medium bg-primary text-primary-foreground rounded\">\n In Cart ({cartQuantity})\n </span>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {combinedQuotas.length} quota{combinedQuotas.length !== 1 ? 's' : ''}\n </p>\n </div>\n\n {/* Price */}\n <div className=\"text-right\">\n <div className=\"font-semibold text-foreground\">\n {(() => {\n const { price, currency } = getAddonDisplayPrice(addon, displayCurrency);\n return formatCurrency(price, currency);\n })()}\n </div>\n <div className=\"text-sm text-muted-foreground\">\n per {formatPlanDuration(addon.duration)}\n </div>\n </div>\n\n {/* Cart Actions */}\n {addon.isActive &&\n (isInCart ? (\n <div className=\"flex items-center gap-1\">\n <button\n onClick={() => onUpdateQuantity(addon.id, cartQuantity - 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Minus className=\"w-4 h-4\" />\n </button>\n <span className=\"w-8 text-center font-medium\">{cartQuantity}</span>\n <button\n onClick={() => onUpdateQuantity(addon.id, cartQuantity + 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Plus className=\"w-4 h-4\" />\n </button>\n <button\n onClick={() => onRemoveFromCart(addon.id)}\n className=\"p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors ml-1\"\n title=\"Remove from cart\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n ) : (\n <button\n onClick={() => onAddToCart(addon)}\n className=\"px-3 py-1.5 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors flex items-center gap-1.5\"\n >\n <ShoppingCart className=\"w-4 h-4\" />\n Add\n </button>\n ))}\n\n {/* Actions */}\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => onView(addon)}\n className=\"px-3 py-1.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n View\n </button>\n {canManage && (\n <>\n <button\n onClick={() => onEdit(addon)}\n className=\"px-3 py-1.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Edit\n </button>\n <button\n onClick={() => onToggle(addon)}\n disabled={isToggling}\n className={`px-3 py-1.5 text-sm font-medium border border-border rounded-md transition-colors ${\n addon.isActive\n ? 'text-destructive hover:bg-destructive/10'\n : 'text-status-success-text hover:bg-status-success-bg-subtle'\n }`}\n >\n {addon.isActive ? 'Deactivate' : 'Activate'}\n </button>\n </>\n )}\n </div>\n </div>\n );\n};\n\n// ============================================================================\n// Floating Cart Drawer\n// ============================================================================\n\ninterface FloatingCartDrawerProps {\n displayCurrency: string;\n}\n\nconst FloatingCartDrawer: FC<FloatingCartDrawerProps> = ({ displayCurrency }) => {\n const navigateTo = useBillingNavigate();\n const { items, isCartOpen, toggleCart, closeCart, removeFromCart, updateQuantity, clearCart } =\n useAddonCartStore();\n\n const itemCount = items.reduce((sum, item) => sum + item.quantity, 0);\n\n if (items.length === 0 && !isCartOpen) return null;\n\n return (\n <>\n {/* Floating Cart Button */}\n {!isCartOpen && items.length > 0 && (\n <button\n onClick={toggleCart}\n className=\"fixed bottom-6 right-6 z-50 flex items-center gap-2 px-4 py-3 bg-primary text-primary-foreground rounded-full shadow-lg hover:bg-primary/90 transition-all\"\n >\n <ShoppingCart className=\"w-5 h-5\" />\n <span className=\"font-medium\">\n {itemCount} item{itemCount !== 1 ? 's' : ''}\n </span>\n <span className=\"px-2 py-0.5 bg-primary-foreground/20 rounded-full text-sm\">\n {(() => {\n // Calculate cart total using display currency prices\n const total = items.reduce((sum, { addon, quantity }) => {\n const { price } = getAddonDisplayPrice(addon, displayCurrency);\n return sum + price * quantity;\n }, 0);\n return formatCurrency(total, displayCurrency);\n })()}\n </span>\n </button>\n )}\n\n {/* Cart Drawer */}\n {isCartOpen && (\n <div className=\"fixed inset-0 z-50 flex items-end sm:items-center justify-center\">\n {/* Backdrop */}\n <div className=\"absolute inset-0 bg-overlay-scrim\" onClick={closeCart} />\n\n {/* Drawer */}\n <div className=\"relative w-full max-w-md max-h-[80vh] bg-card border border-border rounded-t-xl sm:rounded-xl shadow-xl overflow-hidden\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border bg-muted/30\">\n <div className=\"flex items-center gap-2\">\n <ShoppingCart className=\"w-5 h-5 text-foreground\" />\n <h3 className=\"font-semibold text-foreground\">Your Cart</h3>\n <span className=\"px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full\">\n {itemCount} item{itemCount !== 1 ? 's' : ''}\n </span>\n </div>\n <button\n onClick={closeCart}\n className=\"p-1.5 rounded hover:bg-muted transition-colors\"\n >\n <X className=\"w-5 h-5\" />\n </button>\n </div>\n\n {/* Cart Items */}\n <div className=\"overflow-y-auto max-h-[50vh] divide-y divide-border\">\n {items.map(({ addon, quantity }) => (\n <div key={addon.id} className=\"p-4 flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0\">\n <svg\n className=\"w-5 h-5 text-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n </div>\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"font-medium text-foreground truncate\">{addon.name}</h4>\n <p className=\"text-sm text-muted-foreground\">\n {(() => {\n const { price, currency } = getAddonDisplayPrice(addon, displayCurrency);\n return formatCurrency(price, currency);\n })()}{' '}\n / {formatPlanDuration(addon.duration)}\n </p>\n </div>\n <div className=\"flex items-center gap-1\">\n <button\n onClick={() => updateQuantity(addon.id, quantity - 1)}\n className=\"p-1 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Minus className=\"w-3 h-3\" />\n </button>\n <span className=\"w-6 text-center text-sm font-medium\">{quantity}</span>\n <button\n onClick={() => updateQuantity(addon.id, quantity + 1)}\n className=\"p-1 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Plus className=\"w-3 h-3\" />\n </button>\n </div>\n <div className=\"text-right\">\n <p className=\"font-medium text-foreground\">\n {(() => {\n const { price, currency } = getAddonDisplayPrice(addon, displayCurrency);\n return formatCurrency(price * quantity, currency);\n })()}\n </p>\n </div>\n <button\n onClick={() => removeFromCart(addon.id)}\n className=\"p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n ))}\n </div>\n\n {/* Footer */}\n <div className=\"border-t border-border p-4 space-y-3 bg-muted/20\">\n <div className=\"flex items-center justify-between text-lg font-semibold\">\n <span className=\"text-foreground\">Total</span>\n <span className=\"text-foreground\">\n {(() => {\n // Calculate cart total using display currency prices\n const total = items.reduce((sum, { addon, quantity }) => {\n const { price } = getAddonDisplayPrice(addon, displayCurrency);\n return sum + price * quantity;\n }, 0);\n return formatCurrency(total, displayCurrency);\n })()}\n </span>\n </div>\n <div className=\"flex gap-2\">\n <button\n onClick={clearCart}\n className=\"flex-1 px-4 py-2.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Clear Cart\n </button>\n <button\n onClick={() => {\n closeCart();\n navigateTo('/checkout/addons');\n }}\n className=\"flex-1 px-4 py-2.5 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n Checkout\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AddonsListPage.js","names":[],"sources":["../../../../../src/billing/modules/addons/pages/AddonsListPage.tsx"],"sourcesContent":["/**\n * Addons Module - Addons List Page\n * Displays all available addons with cart functionality\n */\n\nimport { useState, useMemo, type FC } from 'react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { ShoppingCart, Plus, Minus, Trash2, X } from 'lucide-react';\nimport { useAddons, useAddonMutations } from '../hooks';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { useAddonCartStore } from '../store/addonCartStore';\nimport {\n formatCurrency,\n formatPlanDuration,\n formatPlanDurationLabel,\n} from '../../../shared/utils/format';\nimport type { Addon, PlanDuration, SubscriptionFeatures } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useDefaultBillingCurrency } from '../../../hooks/useDefaultBillingCurrency';\n\ntype ViewMode = 'grid' | 'list';\n\n/**\n * Combined quota info for display\n */\ninterface CombinedQuota {\n quotaId: string;\n name: string;\n totalValue: number;\n}\n\n/**\n * Combines duplicate quotas by quota ID and aggregates their values\n */\nfunction combineQuotas(features: SubscriptionFeatures[]): CombinedQuota[] {\n const quotaMap = new Map<string, CombinedQuota>();\n\n for (const feature of features) {\n if (!feature.quota) continue;\n\n const quotaId = feature.quota.id;\n const limits = feature.quota.limits as { value?: number } | null;\n const limitValue = limits?.value ?? 0;\n\n const existing = quotaMap.get(quotaId);\n if (existing) {\n existing.totalValue += limitValue;\n } else {\n quotaMap.set(quotaId, {\n quotaId,\n name: feature.quota.name ?? 'Unknown Quota',\n totalValue: limitValue,\n });\n }\n }\n\n return Array.from(quotaMap.values());\n}\n\n/**\n * Get the display price and currency for an addon\n * Uses currencyPrices if available, otherwise falls back to base price\n */\nfunction getAddonDisplayPrice(\n addon: Addon,\n displayCurrency: string = 'USD'\n): { price: number; currency: string } {\n // If currencyPrices exists and has the requested currency, use it\n if (addon.currencyPrices && typeof addon.currencyPrices === 'object') {\n const currencyPricesObj = addon.currencyPrices as Record<string, number>;\n if (currencyPricesObj[displayCurrency]) {\n return {\n price: currencyPricesObj[displayCurrency],\n currency: displayCurrency,\n };\n }\n }\n\n // Fallback to base USD price\n return {\n price: addon.price,\n currency: addon.currency || 'USD',\n };\n}\n\nexport const AddonsListPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const navigateTo = useBillingNavigate();\n const permissions = useBillingPermissions();\n const { addons, isLoading, error, refetch } = useAddons();\n const { toggleAddon, isToggling } = useAddonMutations();\n const { addToCart, removeFromCart, updateQuantity, isInCart, getCartItem } = useAddonCartStore();\n\n const [viewMode, setViewMode] = useState<ViewMode>('grid');\n const [showInactive, setShowInactive] = useState(false);\n const [billingInterval, setBillingInterval] = useState<PlanDuration | 'all'>('all');\n const displayCurrency = useDefaultBillingCurrency();\n\n // Permission check\n if (!permissions.canViewAddons) {\n return (\n <div className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <div className=\"size-12 mx-auto rounded-full bg-muted flex items-center justify-center\">\n <svg\n className=\"size-6 text-muted-foreground\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n </div>\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('billing.accessDenied.title', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-muted-foreground max-w-sm\">\n {tr('billing.addons.noViewPermission', \"You don't have permission to view addons.\")}\n </p>\n </div>\n </div>\n );\n }\n\n // Filter addons\n const filteredAddons = addons.filter((addon) => {\n if (!showInactive && !addon.isActive) return false;\n if (billingInterval !== 'all' && addon.duration !== billingInterval) return false;\n return true;\n });\n\n const handleToggleAddon = async (addon: Addon) => {\n if (!permissions.canManageAddons) return;\n try {\n await toggleAddon(addon.id, !addon.isActive);\n await refetch();\n } catch (err) {\n console.error('Failed to toggle addon:', err);\n }\n };\n\n const handleViewAddon = (addon: Addon) => {\n navigateTo(`/addons/${addon.id}`);\n };\n\n const handleEditAddon = (addon: Addon) => {\n navigateTo(`/addons/${addon.id}/edit`);\n };\n\n // Loading state\n if (isLoading && addons.length === 0) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-muted animate-pulse rounded\" />\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"border border-border rounded-lg p-6 space-y-4\">\n <div className=\"h-6 w-24 bg-muted animate-pulse rounded\" />\n <div className=\"h-8 w-32 bg-muted animate-pulse rounded\" />\n <div className=\"space-y-2\">\n {[1, 2, 3].map((j) => (\n <div key={j} className=\"h-4 w-full bg-muted animate-pulse rounded\" />\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-4\">\n <div className=\"size-12 mx-auto rounded-full bg-destructive/10 flex items-center justify-center\">\n <svg\n className=\"size-6 text-destructive\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('billing.addons.failedToLoad', 'Failed to load addons')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">{error.message}</p>\n <button\n type=\"button\"\n onClick={() => refetch()}\n className=\"px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n Try Again\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-foreground\">\n {tr('billing.addons.title', 'Addons')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {tr('billing.addons.subtitle', 'Enhance your subscription with additional features')}\n </p>\n </div>\n\n {permissions.canManageAddons && (\n <button\n type=\"button\"\n onClick={() => navigateTo('/addons/new')}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n <svg className=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n Create Addon\n </button>\n )}\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-wrap items-center gap-4 pb-4 border-b border-border\">\n {/* Billing Interval Toggle */}\n <div className=\"inline-flex rounded-lg border border-border p-1 bg-muted/50\">\n <button\n type=\"button\"\n onClick={() => setBillingInterval('all')}\n className={`px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${\n billingInterval === 'all'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n All\n </button>\n <button\n type=\"button\"\n onClick={() => setBillingInterval('monthly' as PlanDuration)}\n className={`px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${\n billingInterval === 'monthly'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n Monthly\n </button>\n <button\n type=\"button\"\n onClick={() => setBillingInterval('yearly' as PlanDuration)}\n className={`px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${\n billingInterval === 'yearly'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n Yearly\n </button>\n </div>\n\n {/* Show Inactive Toggle */}\n {permissions.canManageAddons && (\n <label className=\"flex items-center gap-2 text-sm cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={showInactive}\n onChange={(e) => setShowInactive(e.target.checked)}\n className=\"size-4 rounded border-border text-primary focus:ring-primary\"\n />\n <span className=\"text-muted-foreground\">\n {tr('billing.addons.showInactive', 'Show inactive addons')}\n </span>\n </label>\n )}\n\n {/* View Mode Toggle */}\n <div className=\"ml-auto inline-flex rounded-lg border border-border p-1 bg-muted/50\">\n <button\n type=\"button\"\n onClick={() => setViewMode('grid')}\n className={`p-1.5 rounded-md transition-colors ${\n viewMode === 'grid'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n title=\"Grid view\"\n >\n <svg className=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode('list')}\n className={`p-1.5 rounded-md transition-colors ${\n viewMode === 'list'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n }`}\n title=\"List view\"\n >\n <svg className=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 12h16M4 18h16\"\n />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Addons Grid/List */}\n {filteredAddons.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 border border-dashed border-border rounded-lg\">\n <div className=\"size-12 rounded-full bg-muted flex items-center justify-center mb-4\">\n <svg\n className=\"size-6 text-muted-foreground\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n </div>\n <h3 className=\"text-lg font-medium text-foreground\">\n {tr('billing.addons.noAddonsFound', 'No addons found')}\n </h3>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {showInactive\n ? tr('billing.addons.noAddonsFiltered', 'No addons match your current filters.')\n : tr('billing.addons.noActiveAddons', 'There are no active addons available.')}\n </p>\n {permissions.canManageAddons && (\n <button\n type=\"button\"\n onClick={() => navigateTo('/addons/new')}\n className=\"mt-4 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n {tr('billing.addons.createFirstAddon', 'Create your first addon')}\n </button>\n )}\n </div>\n ) : viewMode === 'grid' ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {filteredAddons.map((addon) => {\n const cartItem = getCartItem(addon.id);\n return (\n <AddonCard\n key={addon.id}\n addon={addon}\n onView={handleViewAddon}\n onEdit={handleEditAddon}\n onToggle={handleToggleAddon}\n canManage={permissions.canManageAddons}\n isToggling={isToggling}\n isInCart={isInCart(addon.id)}\n cartQuantity={cartItem?.quantity || 0}\n onAddToCart={addToCart}\n onUpdateQuantity={updateQuantity}\n onRemoveFromCart={removeFromCart}\n displayCurrency={displayCurrency}\n />\n );\n })}\n </div>\n ) : (\n <div className=\"space-y-3\">\n {filteredAddons.map((addon) => {\n const cartItem = getCartItem(addon.id);\n return (\n <AddonRow\n key={addon.id}\n addon={addon}\n onView={handleViewAddon}\n onEdit={handleEditAddon}\n onToggle={handleToggleAddon}\n canManage={permissions.canManageAddons}\n isToggling={isToggling}\n isInCart={isInCart(addon.id)}\n cartQuantity={cartItem?.quantity || 0}\n onAddToCart={addToCart}\n onUpdateQuantity={updateQuantity}\n onRemoveFromCart={removeFromCart}\n displayCurrency={displayCurrency}\n />\n );\n })}\n </div>\n )}\n\n {/* Floating Cart Drawer */}\n <FloatingCartDrawer displayCurrency={displayCurrency} />\n </div>\n );\n};\n\n// ============================================================================\n// Addon Card Component\n// ============================================================================\n\ninterface AddonCardProps {\n addon: Addon;\n onView: (addon: Addon) => void;\n onEdit: (addon: Addon) => void;\n onToggle: (addon: Addon) => void;\n canManage: boolean;\n isToggling: boolean;\n isInCart: boolean;\n cartQuantity: number;\n onAddToCart: (addon: Addon) => void;\n onUpdateQuantity: (addonId: string, quantity: number) => void;\n onRemoveFromCart: (addonId: string) => void;\n displayCurrency: string;\n}\n\nconst AddonCard: FC<AddonCardProps> = ({\n addon,\n onView,\n onEdit,\n onToggle,\n canManage,\n displayCurrency,\n isToggling,\n isInCart,\n cartQuantity,\n onAddToCart,\n onUpdateQuantity,\n onRemoveFromCart,\n}) => {\n const combinedQuotas = useMemo(() => {\n const features = addon.features || [];\n return combineQuotas(features);\n }, [addon.features]);\n\n return (\n <div\n className={`relative border rounded-lg p-6 transition-all hover:shadow-md flex flex-col h-full ${\n addon.isActive\n ? isInCart\n ? 'border-primary bg-primary/5'\n : 'border-border bg-card'\n : 'border-dashed border-muted-foreground/30 bg-muted/30'\n }`}\n >\n {/* Status Badge */}\n {!addon.isActive && (\n <span className=\"absolute top-4 right-4 px-2 py-1 text-xs font-medium bg-muted text-muted-foreground rounded\">\n Inactive\n </span>\n )}\n\n {/* In Cart Badge */}\n {isInCart && addon.isActive && (\n <span className=\"absolute top-4 right-4 px-2 py-1 text-xs font-medium bg-primary text-primary-foreground rounded\">\n In Cart ({cartQuantity})\n </span>\n )}\n\n {/* Addon Icon */}\n <div className=\"size-10 rounded-lg bg-primary/10 flex items-center justify-center mb-4\">\n <svg className=\"size-5 text-primary\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n </div>\n\n {/* Addon Name */}\n <div className=\"mb-4\">\n <h3 className=\"text-lg font-bold text-foreground\">{addon.name}</h3>\n <span className=\"text-sm text-muted-foreground\">\n {formatPlanDurationLabel(addon.duration)}\n </span>\n </div>\n\n {/* Price */}\n <div className=\"flex items-baseline gap-1 mb-4\">\n <span className=\"text-2xl font-bold text-foreground\">\n {(() => {\n const { price, currency } = getAddonDisplayPrice(addon, displayCurrency);\n return formatCurrency(price, currency);\n })()}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n / {formatPlanDuration(addon.duration)}\n </span>\n </div>\n\n {/* Combined Quotas */}\n {combinedQuotas.length > 0 && (\n <ul className=\"space-y-2 mb-4\">\n {combinedQuotas.slice(0, 4).map((quota) => (\n <li key={quota.quotaId} className=\"flex items-center justify-between text-sm\">\n <div className=\"flex items-center gap-2\">\n <svg\n className=\"size-4 text-status-success-text shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n <span className=\"text-foreground\">{quota.name}</span>\n </div>\n <span className=\"font-medium text-foreground\">\n {quota.totalValue.toLocaleString()}\n </span>\n </li>\n ))}\n {combinedQuotas.length > 4 && (\n <li className=\"text-sm text-muted-foreground pl-6\">\n +{combinedQuotas.length - 4} more quotas\n </li>\n )}\n </ul>\n )}\n\n {/* Actions - pushed to bottom with mt-auto */}\n <div className=\"space-y-2 pt-4 border-t border-border mt-auto\">\n {/* Add to Cart / Quantity Controls */}\n {addon.isActive &&\n (isInCart ? (\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => onUpdateQuantity(addon.id, cartQuantity - 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Minus className=\"size-4\" />\n </button>\n <span className=\"w-10 text-center font-medium\">{cartQuantity}</span>\n <button\n type=\"button\"\n onClick={() => onUpdateQuantity(addon.id, cartQuantity + 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Plus className=\"size-4\" />\n </button>\n </div>\n <button\n type=\"button\"\n onClick={() => onRemoveFromCart(addon.id)}\n className=\"p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors\"\n title=\"Remove from cart\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => onAddToCart(addon)}\n className=\"w-full px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors flex items-center justify-center gap-2\"\n >\n <ShoppingCart className=\"size-4\" />\n Add to Cart\n </button>\n ))}\n\n <button\n type=\"button\"\n onClick={() => onView(addon)}\n className=\"w-full px-4 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n View Details\n </button>\n\n {canManage && (\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => onEdit(addon)}\n className=\"flex-1 px-3 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Edit\n </button>\n <button\n type=\"button\"\n onClick={() => onToggle(addon)}\n disabled={isToggling}\n className={`px-3 py-2 text-sm font-medium border border-border rounded-md transition-colors ${\n addon.isActive\n ? 'text-destructive hover:bg-destructive/10'\n : 'text-status-success-text hover:bg-status-success-bg-subtle'\n }`}\n >\n {addon.isActive ? 'Deactivate' : 'Activate'}\n </button>\n </div>\n )}\n </div>\n </div>\n );\n};\n\n// ============================================================================\n// Addon Row Component (List View)\n// ============================================================================\n\ninterface AddonRowProps {\n addon: Addon;\n onView: (addon: Addon) => void;\n onEdit: (addon: Addon) => void;\n onToggle: (addon: Addon) => void;\n canManage: boolean;\n isToggling: boolean;\n isInCart: boolean;\n cartQuantity: number;\n onAddToCart: (addon: Addon) => void;\n onUpdateQuantity: (addonId: string, quantity: number) => void;\n onRemoveFromCart: (addonId: string) => void;\n displayCurrency: string;\n}\n\nconst AddonRow: FC<AddonRowProps> = ({\n addon,\n onView,\n onEdit,\n onToggle,\n canManage,\n displayCurrency,\n isToggling,\n isInCart,\n cartQuantity,\n onAddToCart,\n onUpdateQuantity,\n onRemoveFromCart,\n}) => {\n const combinedQuotas = useMemo(() => {\n const features = addon.features || [];\n return combineQuotas(features);\n }, [addon.features]);\n\n return (\n <div\n className={`flex items-center gap-4 p-4 border rounded-lg transition-all hover:shadow-sm ${\n addon.isActive\n ? isInCart\n ? 'border-primary bg-primary/5'\n : 'border-border bg-card'\n : 'border-dashed border-muted-foreground/30 bg-muted/30'\n }`}\n >\n {/* Addon Icon */}\n <div className=\"size-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0\">\n <svg className=\"size-5 text-primary\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n </div>\n\n {/* Addon Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-semibold text-foreground truncate\">{addon.name}</h3>\n {!addon.isActive && (\n <span className=\"px-2 py-0.5 text-xs font-medium bg-muted text-muted-foreground rounded\">\n Inactive\n </span>\n )}\n {isInCart && addon.isActive && (\n <span className=\"px-2 py-0.5 text-xs font-medium bg-primary text-primary-foreground rounded\">\n In Cart ({cartQuantity})\n </span>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {combinedQuotas.length} quota{combinedQuotas.length !== 1 ? 's' : ''}\n </p>\n </div>\n\n {/* Price */}\n <div className=\"text-right\">\n <div className=\"font-semibold text-foreground\">\n {(() => {\n const { price, currency } = getAddonDisplayPrice(addon, displayCurrency);\n return formatCurrency(price, currency);\n })()}\n </div>\n <div className=\"text-sm text-muted-foreground\">\n per {formatPlanDuration(addon.duration)}\n </div>\n </div>\n\n {/* Cart Actions */}\n {addon.isActive &&\n (isInCart ? (\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => onUpdateQuantity(addon.id, cartQuantity - 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Minus className=\"size-4\" />\n </button>\n <span className=\"w-8 text-center font-medium\">{cartQuantity}</span>\n <button\n type=\"button\"\n onClick={() => onUpdateQuantity(addon.id, cartQuantity + 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Plus className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onRemoveFromCart(addon.id)}\n className=\"p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors ml-1\"\n title=\"Remove from cart\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => onAddToCart(addon)}\n className=\"px-3 py-1.5 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors flex items-center gap-1.5\"\n >\n <ShoppingCart className=\"size-4\" />\n Add\n </button>\n ))}\n\n {/* Actions */}\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => onView(addon)}\n className=\"px-3 py-1.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n View\n </button>\n {canManage && (\n <>\n <button\n type=\"button\"\n onClick={() => onEdit(addon)}\n className=\"px-3 py-1.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Edit\n </button>\n <button\n type=\"button\"\n onClick={() => onToggle(addon)}\n disabled={isToggling}\n className={`px-3 py-1.5 text-sm font-medium border border-border rounded-md transition-colors ${\n addon.isActive\n ? 'text-destructive hover:bg-destructive/10'\n : 'text-status-success-text hover:bg-status-success-bg-subtle'\n }`}\n >\n {addon.isActive ? 'Deactivate' : 'Activate'}\n </button>\n </>\n )}\n </div>\n </div>\n );\n};\n\n// ============================================================================\n// Floating Cart Drawer\n// ============================================================================\n\ninterface FloatingCartDrawerProps {\n displayCurrency: string;\n}\n\nconst FloatingCartDrawer: FC<FloatingCartDrawerProps> = ({ displayCurrency }) => {\n const navigateTo = useBillingNavigate();\n const { items, isCartOpen, toggleCart, closeCart, removeFromCart, updateQuantity, clearCart } =\n useAddonCartStore();\n\n const itemCount = items.reduce((sum, item) => sum + item.quantity, 0);\n\n if (items.length === 0 && !isCartOpen) return null;\n\n return (\n <>\n {/* Floating Cart Button */}\n {!isCartOpen && items.length > 0 && (\n <button\n type=\"button\"\n onClick={toggleCart}\n className=\"fixed bottom-6 right-6 z-50 flex items-center gap-2 px-4 py-3 bg-primary text-primary-foreground rounded-full shadow-lg hover:bg-primary/90 transition-all\"\n >\n <ShoppingCart className=\"size-5\" />\n <span className=\"font-medium\">\n {itemCount} item{itemCount !== 1 ? 's' : ''}\n </span>\n <span className=\"px-2 py-0.5 bg-primary-foreground/20 rounded-full text-sm\">\n {(() => {\n // Calculate cart total using display currency prices\n const total = items.reduce((sum, { addon, quantity }) => {\n const { price } = getAddonDisplayPrice(addon, displayCurrency);\n return sum + price * quantity;\n }, 0);\n return formatCurrency(total, displayCurrency);\n })()}\n </span>\n </button>\n )}\n\n {/* Cart Drawer */}\n {isCartOpen && (\n <div className=\"fixed inset-0 z-50 flex items-end sm:items-center justify-center\">\n {/* Backdrop */}\n <div className=\"absolute inset-0 bg-overlay-scrim\" onClick={closeCart} />\n\n {/* Drawer */}\n <div className=\"relative w-full max-w-md max-h-[80vh] bg-card border border-border rounded-t-xl sm:rounded-xl shadow-xl overflow-hidden\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border bg-muted/30\">\n <div className=\"flex items-center gap-2\">\n <ShoppingCart className=\"size-5 text-foreground\" />\n <h3 className=\"font-semibold text-foreground\">Your Cart</h3>\n <span className=\"px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full\">\n {itemCount} item{itemCount !== 1 ? 's' : ''}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={closeCart}\n className=\"p-1.5 rounded hover:bg-muted transition-colors\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Cart Items */}\n <div className=\"overflow-y-auto max-h-[50vh] divide-y divide-border\">\n {items.map(({ addon, quantity }) => (\n <div key={addon.id} className=\"p-4 flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0\">\n <svg\n className=\"size-5 text-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4\"\n />\n </svg>\n </div>\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"font-medium text-foreground truncate\">{addon.name}</h4>\n <p className=\"text-sm text-muted-foreground\">\n {(() => {\n const { price, currency } = getAddonDisplayPrice(addon, displayCurrency);\n return formatCurrency(price, currency);\n })()}{' '}\n / {formatPlanDuration(addon.duration)}\n </p>\n </div>\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(addon.id, quantity - 1)}\n className=\"p-1 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Minus className=\"size-3\" />\n </button>\n <span className=\"w-6 text-center text-sm font-medium\">{quantity}</span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(addon.id, quantity + 1)}\n className=\"p-1 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Plus className=\"size-3\" />\n </button>\n </div>\n <div className=\"text-right\">\n <p className=\"font-medium text-foreground\">\n {(() => {\n const { price, currency } = getAddonDisplayPrice(addon, displayCurrency);\n return formatCurrency(price * quantity, currency);\n })()}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => removeFromCart(addon.id)}\n className=\"p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n ))}\n </div>\n\n {/* Footer */}\n <div className=\"border-t border-border p-4 space-y-3 bg-muted/20\">\n <div className=\"flex items-center justify-between text-lg font-semibold\">\n <span className=\"text-foreground\">Total</span>\n <span className=\"text-foreground\">\n {(() => {\n // Calculate cart total using display currency prices\n const total = items.reduce((sum, { addon, quantity }) => {\n const { price } = getAddonDisplayPrice(addon, displayCurrency);\n return sum + price * quantity;\n }, 0);\n return formatCurrency(total, displayCurrency);\n })()}\n </span>\n </div>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={clearCart}\n className=\"flex-1 px-4 py-2.5 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Clear Cart\n </button>\n <button\n type=\"button\"\n onClick={() => {\n closeCart();\n navigateTo('/checkout/addons');\n }}\n className=\"flex-1 px-4 py-2.5 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n Checkout\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </>\n );\n};\n"],"mappings":"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"}