@withpotter/pages-admin 0.13.0-next.124 → 0.13.0-next.59

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 (260) hide show
  1. package/dist/admin/_money/cash-postings.js +3 -20
  2. package/dist/admin/_money/cash-postings.js.map +1 -1
  3. package/dist/admin/_money/cash.module.css +0 -10
  4. package/dist/admin/_money/finder-format.js +0 -1
  5. package/dist/admin/_money/finder-format.js.map +1 -1
  6. package/dist/admin/_money/format.js +0 -1
  7. package/dist/admin/_money/format.js.map +1 -1
  8. package/dist/admin/_overview/activation-panel.js +6 -6
  9. package/dist/admin/_overview/activation-panel.js.map +1 -1
  10. package/dist/admin/_overview/attention-groups.js +8 -8
  11. package/dist/admin/_overview/attention-groups.js.map +1 -1
  12. package/dist/admin/_overview/attention-panel.js +33 -37
  13. package/dist/admin/_overview/attention-panel.js.map +1 -1
  14. package/dist/admin/_overview/attention.module.css +3 -0
  15. package/dist/admin/_overview/control-room.js +13 -41
  16. package/dist/admin/_overview/control-room.js.map +1 -1
  17. package/dist/admin/_overview/kpi-row.js +7 -7
  18. package/dist/admin/_overview/kpi-row.js.map +1 -1
  19. package/dist/admin/_overview/leaders-panel.js +1 -1
  20. package/dist/admin/_overview/leaders-panel.js.map +1 -1
  21. package/dist/admin/_overview/overdue-outstanding.js +1 -2
  22. package/dist/admin/_overview/overdue-outstanding.js.map +1 -1
  23. package/dist/admin/_overview/portfolio-panel.js +5 -5
  24. package/dist/admin/_overview/portfolio-panel.js.map +1 -1
  25. package/dist/admin/_overview/position-panel.js +12 -8
  26. package/dist/admin/_overview/position-panel.js.map +1 -1
  27. package/dist/admin/_pos/pos-figures.js +5 -18
  28. package/dist/admin/_pos/pos-figures.js.map +1 -1
  29. package/dist/admin/_pos/pos-rules.js +0 -2
  30. package/dist/admin/_pos/pos-rules.js.map +1 -1
  31. package/dist/admin/_pos/pos-words.js +1 -6
  32. package/dist/admin/_pos/pos-words.js.map +1 -1
  33. package/dist/admin/_pos/use-pos.js +1 -70
  34. package/dist/admin/_pos/use-pos.js.map +1 -1
  35. package/dist/admin/_shell/nav-config.js +3 -3
  36. package/dist/admin/_shell/nav-config.js.map +1 -1
  37. package/dist/admin/_shell/nav-filter.js +2 -4
  38. package/dist/admin/_shell/nav-filter.js.map +1 -1
  39. package/dist/admin/_shell/nav-row.js +2 -5
  40. package/dist/admin/_shell/nav-row.js.map +1 -1
  41. package/dist/admin/_shell/sidebar-footer.js +0 -20
  42. package/dist/admin/_shell/sidebar-footer.js.map +1 -1
  43. package/dist/admin/_shell/sidebar-footer.module.css +0 -17
  44. package/dist/admin/_shell/sidebar.js +15 -25
  45. package/dist/admin/_shell/sidebar.js.map +1 -1
  46. package/dist/admin/_shell/sidebar.module.css +0 -69
  47. package/dist/admin/_shell/use-fluid-hover.js +6 -37
  48. package/dist/admin/_shell/use-fluid-hover.js.map +1 -1
  49. package/dist/admin/_ui/admin.css +0 -7
  50. package/dist/admin/_ui/data-table.js +1 -1
  51. package/dist/admin/_ui/data-table.js.map +1 -1
  52. package/dist/admin/_ui/list-card.js +1 -1
  53. package/dist/admin/_ui/list-card.js.map +1 -1
  54. package/dist/admin/_ui/list-card.module.css +16 -2
  55. package/dist/admin/_ui/money-view.js +0 -1
  56. package/dist/admin/_ui/money-view.js.map +1 -1
  57. package/dist/admin/_ui/page-header.js +4 -31
  58. package/dist/admin/_ui/page-header.js.map +1 -1
  59. package/dist/admin/_ui/panel.module.css +10 -0
  60. package/dist/admin/_ui/stat-card.js +2 -11
  61. package/dist/admin/_ui/stat-card.js.map +1 -1
  62. package/dist/admin/_ui/trend.js +2 -2
  63. package/dist/admin/_ui/trend.js.map +1 -1
  64. package/dist/admin/accounts/account-panel.js +6 -49
  65. package/dist/admin/accounts/account-panel.js.map +1 -1
  66. package/dist/admin/accounts/account-panel.module.css +0 -73
  67. package/dist/admin/accounts/account-row.js +2 -11
  68. package/dist/admin/accounts/account-row.js.map +1 -1
  69. package/dist/admin/accounts/account-vitals.js +13 -15
  70. package/dist/admin/accounts/account-vitals.js.map +1 -1
  71. package/dist/admin/accounts/accounts-table.js +8 -39
  72. package/dist/admin/accounts/accounts-table.js.map +1 -1
  73. package/dist/admin/accounts/accounts-workspace.js +2 -2
  74. package/dist/admin/accounts/accounts-workspace.js.map +1 -1
  75. package/dist/admin/accounts/owner-session.js +6 -0
  76. package/dist/admin/accounts/owner-session.js.map +1 -1
  77. package/dist/admin/accounts/rows.module.css +0 -17
  78. package/dist/admin/audit/status-pill.js +0 -6
  79. package/dist/admin/audit/status-pill.js.map +1 -1
  80. package/dist/admin/audit/status-pill.module.css +0 -4
  81. package/dist/admin/commerce/commerce-overview.js +2 -2
  82. package/dist/admin/commerce/commerce-overview.js.map +1 -1
  83. package/dist/admin/commerce/merchant-meta.js +0 -1
  84. package/dist/admin/commerce/merchant-meta.js.map +1 -1
  85. package/dist/admin/commerce/merchant-view.js +2 -2
  86. package/dist/admin/commerce/merchant-view.js.map +1 -1
  87. package/dist/admin/feedback/prompt-operations.module.css +2 -0
  88. package/dist/admin/feedback/prompt-preview.module.css +2 -0
  89. package/dist/admin/hooks.js +1 -57
  90. package/dist/admin/hooks.js.map +1 -1
  91. package/dist/admin/layout.js +2 -8
  92. package/dist/admin/layout.js.map +1 -1
  93. package/dist/admin/page.js +8 -28
  94. package/dist/admin/page.js.map +1 -1
  95. package/dist/admin/payout-tiers/_tier-dialog.js +21 -31
  96. package/dist/admin/payout-tiers/_tier-dialog.js.map +1 -1
  97. package/dist/admin/payout-tiers/tier-preview-result.js +9 -10
  98. package/dist/admin/payout-tiers/tier-preview-result.js.map +1 -1
  99. package/dist/admin/payout-tiers/tiers-table.js +7 -6
  100. package/dist/admin/payout-tiers/tiers-table.js.map +1 -1
  101. package/dist/admin/payout-tiers/tiers-workspace.js +2 -2
  102. package/dist/admin/payout-tiers/tiers-workspace.js.map +1 -1
  103. package/dist/admin/pos/pos-workspace.js +2 -6
  104. package/dist/admin/pos/pos-workspace.js.map +1 -1
  105. package/dist/admin/pos/shifts-tab.js +9 -16
  106. package/dist/admin/pos/shifts-tab.js.map +1 -1
  107. package/dist/admin/revenue/cohort-panel.js +6 -6
  108. package/dist/admin/revenue/cohort-panel.js.map +1 -1
  109. package/dist/admin/revenue/health-panel.js +21 -22
  110. package/dist/admin/revenue/health-panel.js.map +1 -1
  111. package/dist/admin/revenue/plan-mix-panel.js +3 -3
  112. package/dist/admin/revenue/plan-mix-panel.js.map +1 -1
  113. package/dist/admin/revenue/quality-panel.js +19 -19
  114. package/dist/admin/revenue/quality-panel.js.map +1 -1
  115. package/dist/admin/revenue/revenue-kpis.js +50 -111
  116. package/dist/admin/revenue/revenue-kpis.js.map +1 -1
  117. package/dist/admin/revenue/revenue-overview.js +46 -39
  118. package/dist/admin/revenue/revenue-overview.js.map +1 -1
  119. package/dist/admin/revenue/revenue-retention.js +13 -17
  120. package/dist/admin/revenue/revenue-retention.js.map +1 -1
  121. package/dist/admin/revenue/revenue-workspace.js +6 -53
  122. package/dist/admin/revenue/revenue-workspace.js.map +1 -1
  123. package/dist/admin/revenue/subscriptions-panel.js +14 -14
  124. package/dist/admin/revenue/subscriptions-panel.js.map +1 -1
  125. package/dist/admin/revenue/top-tenants-panel.js +4 -4
  126. package/dist/admin/revenue/top-tenants-panel.js.map +1 -1
  127. package/dist/admin/settings/account-tab.js +25 -1
  128. package/dist/admin/settings/account-tab.js.map +1 -1
  129. package/dist/admin/settings/general-tab.js +2 -2
  130. package/dist/admin/settings/general-tab.js.map +1 -1
  131. package/dist/admin/settings/system-status-card.js +30 -0
  132. package/dist/admin/settings/system-status-card.js.map +1 -0
  133. package/dist/admin/support/queue-card.module.css +4 -1
  134. package/dist/admin/tenants/[id]/commerce/format.js +1 -2
  135. package/dist/admin/tenants/[id]/commerce/format.js.map +1 -1
  136. package/dist/admin/tenants/[id]/commerce/recent-orders.js +1 -1
  137. package/dist/admin/tenants/[id]/commerce/recent-orders.js.map +1 -1
  138. package/dist/admin/tenants/[id]/page.js +10 -37
  139. package/dist/admin/tenants/[id]/page.js.map +1 -1
  140. package/dist/admin/tenants/[id]/tenant-layout.module.css +4 -1
  141. package/dist/admin/tenants/[id]/tenant-overview.js +2 -3
  142. package/dist/admin/tenants/[id]/tenant-overview.js.map +1 -1
  143. package/dist/admin/tenants/[id]/tenant-overview.module.css +1 -1
  144. package/dist/admin/tenants/[id]/tenant-pos.js +16 -64
  145. package/dist/admin/tenants/[id]/tenant-pos.js.map +1 -1
  146. package/dist/admin/tenants/[id]/tenant-wallet-card.js +2 -3
  147. package/dist/admin/tenants/[id]/tenant-wallet-card.js.map +1 -1
  148. package/dist/admin/tenants/[id]/verification/document-viewer.js +52 -3
  149. package/dist/admin/tenants/[id]/verification/document-viewer.js.map +1 -1
  150. package/dist/admin/tenants/[id]/verification/document-viewer.module.css +0 -51
  151. package/dist/admin/tenants/[id]/verification/tenant-verification.js +0 -10
  152. package/dist/admin/tenants/[id]/verification/tenant-verification.js.map +1 -1
  153. package/dist/admin/tenants/tenant-list-row.js +1 -2
  154. package/dist/admin/tenants/tenant-list-row.js.map +1 -1
  155. package/dist/admin/tenants/tenants-table.js +2 -3
  156. package/dist/admin/tenants/tenants-table.js.map +1 -1
  157. package/dist/admin/tenants/tenants-workspace.js +2 -2
  158. package/dist/admin/tenants/tenants-workspace.js.map +1 -1
  159. package/dist/admin/verification/verification-page.js +3 -19
  160. package/dist/admin/verification/verification-page.js.map +1 -1
  161. package/dist/admin/verification/verification.module.css +0 -10
  162. package/dist/admin/verification/waiting-case-actions.js +68 -0
  163. package/dist/admin/verification/waiting-case-actions.js.map +1 -0
  164. package/dist/admin/verification/waiting-cases.js +48 -66
  165. package/dist/admin/verification/waiting-cases.js.map +1 -1
  166. package/package.json +5 -5
  167. package/dist/admin/_pos/olive-balance.js +0 -40
  168. package/dist/admin/_pos/olive-balance.js.map +0 -1
  169. package/dist/admin/_pos/olive-state.js +0 -23
  170. package/dist/admin/_pos/olive-state.js.map +0 -1
  171. package/dist/admin/_pos/payments-model.js +0 -55
  172. package/dist/admin/_pos/payments-model.js.map +0 -1
  173. package/dist/admin/_pos/tenant-operators.js +0 -63
  174. package/dist/admin/_pos/tenant-operators.js.map +0 -1
  175. package/dist/admin/_pos/tenant-outlets.js +0 -77
  176. package/dist/admin/_pos/tenant-outlets.js.map +0 -1
  177. package/dist/admin/_pos/tenant-pos-figures.js +0 -82
  178. package/dist/admin/_pos/tenant-pos-figures.js.map +0 -1
  179. package/dist/admin/_pos/tenant-requests.js +0 -64
  180. package/dist/admin/_pos/tenant-requests.js.map +0 -1
  181. package/dist/admin/_pos/tenant-transactions.js +0 -145
  182. package/dist/admin/_pos/tenant-transactions.js.map +0 -1
  183. package/dist/admin/_shell/nav-fold.js +0 -14
  184. package/dist/admin/_shell/nav-fold.js.map +0 -1
  185. package/dist/admin/_shell/nav-group.js +0 -78
  186. package/dist/admin/_shell/nav-group.js.map +0 -1
  187. package/dist/admin/_shell/use-open-groups.js +0 -64
  188. package/dist/admin/_shell/use-open-groups.js.map +0 -1
  189. package/dist/admin/_ui/page-header.module.css +0 -45
  190. package/dist/admin/accounts/account-sessions.js +0 -70
  191. package/dist/admin/accounts/account-sessions.js.map +0 -1
  192. package/dist/admin/accounts/account-sessions.module.css +0 -55
  193. package/dist/admin/accounts/account-stage-filter.js +0 -29
  194. package/dist/admin/accounts/account-stage-filter.js.map +0 -1
  195. package/dist/admin/accounts/account-stage.js +0 -81
  196. package/dist/admin/accounts/account-stage.js.map +0 -1
  197. package/dist/admin/accounts/hint.js +0 -12
  198. package/dist/admin/accounts/hint.js.map +0 -1
  199. package/dist/admin/payout-tiers/requirement-labels.js +0 -70
  200. package/dist/admin/payout-tiers/requirement-labels.js.map +0 -1
  201. package/dist/admin/pos/transactions-tab.js +0 -214
  202. package/dist/admin/pos/transactions-tab.js.map +0 -1
  203. package/dist/admin/revenue/channel-panel.js +0 -49
  204. package/dist/admin/revenue/channel-panel.js.map +0 -1
  205. package/dist/admin/revenue/channel-rows.js +0 -17
  206. package/dist/admin/revenue/channel-rows.js.map +0 -1
  207. package/dist/admin/revenue/download-button.js +0 -40
  208. package/dist/admin/revenue/download-button.js.map +0 -1
  209. package/dist/admin/revenue/earnings/earnings-colors.js +0 -25
  210. package/dist/admin/revenue/earnings/earnings-colors.js.map +0 -1
  211. package/dist/admin/revenue/earnings/earnings-legend.js +0 -75
  212. package/dist/admin/revenue/earnings/earnings-legend.js.map +0 -1
  213. package/dist/admin/revenue/earnings/earnings-summary.js +0 -308
  214. package/dist/admin/revenue/earnings/earnings-summary.js.map +0 -1
  215. package/dist/admin/revenue/earnings/earnings-table.js +0 -143
  216. package/dist/admin/revenue/earnings/earnings-table.js.map +0 -1
  217. package/dist/admin/revenue/earnings/earnings.module.css +0 -201
  218. package/dist/admin/revenue/earnings/use-earnings.js +0 -27
  219. package/dist/admin/revenue/earnings/use-earnings.js.map +0 -1
  220. package/dist/admin/revenue/ledger-model.js +0 -104
  221. package/dist/admin/revenue/ledger-model.js.map +0 -1
  222. package/dist/admin/revenue/ledger.module.css +0 -144
  223. package/dist/admin/revenue/merchant-headline.js +0 -37
  224. package/dist/admin/revenue/merchant-headline.js.map +0 -1
  225. package/dist/admin/revenue/merchant-payments-view.js +0 -234
  226. package/dist/admin/revenue/merchant-payments-view.js.map +0 -1
  227. package/dist/admin/revenue/method-cards.js +0 -40
  228. package/dist/admin/revenue/method-cards.js.map +0 -1
  229. package/dist/admin/revenue/payment-drawer.js +0 -53
  230. package/dist/admin/revenue/payment-drawer.js.map +0 -1
  231. package/dist/admin/revenue/plan-lines.js +0 -36
  232. package/dist/admin/revenue/plan-lines.js.map +0 -1
  233. package/dist/admin/revenue/plan-payment-drawer.js +0 -42
  234. package/dist/admin/revenue/plan-payment-drawer.js.map +0 -1
  235. package/dist/admin/revenue/plans-panel.js +0 -48
  236. package/dist/admin/revenue/plans-panel.js.map +0 -1
  237. package/dist/admin/revenue/platform-fees.js +0 -9
  238. package/dist/admin/revenue/platform-fees.js.map +0 -1
  239. package/dist/admin/revenue/print-summary-button.js +0 -27
  240. package/dist/admin/revenue/print-summary-button.js.map +0 -1
  241. package/dist/admin/revenue/subscriptions-view.js +0 -213
  242. package/dist/admin/revenue/subscriptions-view.js.map +0 -1
  243. package/dist/admin/revenue/summary-download.js +0 -38
  244. package/dist/admin/revenue/summary-download.js.map +0 -1
  245. package/dist/admin/revenue/summary-print.js +0 -82
  246. package/dist/admin/revenue/summary-print.js.map +0 -1
  247. package/dist/admin/revenue/summary-rows.js +0 -44
  248. package/dist/admin/revenue/summary-rows.js.map +0 -1
  249. package/dist/admin/revenue/url-filters.js +0 -36
  250. package/dist/admin/revenue/url-filters.js.map +0 -1
  251. package/dist/admin/revenue/use-url-filters.js +0 -24
  252. package/dist/admin/revenue/use-url-filters.js.map +0 -1
  253. package/dist/admin/tenants/[id]/use-tenant-wallet.js +0 -23
  254. package/dist/admin/tenants/[id]/use-tenant-wallet.js.map +0 -1
  255. package/dist/admin/tenants/[id]/verification/document-file.js +0 -78
  256. package/dist/admin/tenants/[id]/verification/document-file.js.map +0 -1
  257. package/dist/admin/tenants/[id]/verification/sent-files.js +0 -33
  258. package/dist/admin/tenants/[id]/verification/sent-files.js.map +0 -1
  259. package/dist/admin/verification/preview-dialog.js +0 -111
  260. package/dist/admin/verification/preview-dialog.js.map +0 -1
@@ -8,49 +8,49 @@ function SubscriptionsPanel({
8
8
  }) {
9
9
  const rows = [
10
10
  {
11
- label: "Payment missed",
11
+ label: "Past due",
12
12
  status: "past_due",
13
- note: "Their last payment failed, so they may leave",
13
+ note: "Payment failed, at risk of churning",
14
14
  value: integer.format(recurring.pastDueSubscriptions),
15
15
  tone: recurring.pastDueSubscriptions > 0 ? "danger" : "default"
16
16
  },
17
17
  {
18
- label: "Set to end",
18
+ label: "Non-renewing",
19
19
  status: "non_renewing",
20
- note: "Will not renew when the paid period ends",
20
+ note: "Set to cancel at period end",
21
21
  value: integer.format(recurring.nonRenewingSubscriptions),
22
22
  tone: recurring.nonRenewingSubscriptions > 0 ? "danger" : "default"
23
23
  },
24
24
  {
25
25
  label: "Active",
26
26
  status: "active",
27
- note: "Paying for their plan",
27
+ note: "Paying on a live billing cycle",
28
28
  value: integer.format(recurring.activeSubscriptions)
29
29
  },
30
30
  {
31
- label: "On a trial",
31
+ label: "Trialing",
32
32
  status: "trialing",
33
- note: "Trying a plan, not yet paying",
33
+ note: "In trial, not yet billed",
34
34
  value: integer.format(recurring.trialingSubscriptions)
35
35
  },
36
36
  {
37
- label: "Joined this period",
38
- note: `Started paying in ${span}`,
37
+ label: "New this period",
38
+ note: `Started in ${span}`,
39
39
  value: integer.format(recurring.newInRange)
40
40
  },
41
41
  {
42
- label: "Left this period",
43
- note: `Stopped paying in ${span}`,
42
+ label: "Churned this period",
43
+ note: `Cancelled in ${span}`,
44
44
  value: integer.format(recurring.churnedInRange),
45
45
  tone: recurring.churnedInRange > 0 ? "danger" : "default"
46
46
  },
47
47
  {
48
- label: "Cancelled in total",
49
- note: "Since the start",
48
+ label: "Cancelled",
49
+ note: "Lifetime total",
50
50
  value: integer.format(recurring.cancelledSubscriptions)
51
51
  }
52
52
  ];
53
- return /* @__PURE__ */ jsx(Panel, { title: "Plan subscriptions", caption: "Right now", height: "var(--adm-panel-h)", children: /* @__PURE__ */ jsx(FigureList, { rows }) });
53
+ return /* @__PURE__ */ jsx(Panel, { title: "Subscriptions", caption: "Today", height: "var(--adm-panel-h)", children: /* @__PURE__ */ jsx(FigureList, { rows }) });
54
54
  }
55
55
  export {
56
56
  SubscriptionsPanel
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/revenue/subscriptions-panel.tsx"],"sourcesContent":["import type { PlatformRevenue } from '@withpotter/lib/admin-api';\nimport { Panel } from '../_ui';\nimport { FigureList, type Figure } from './figure-list';\n\nconst integer = new Intl.NumberFormat('en-US');\n\n/** Where the subscription base stands, and what started in the window. */\nexport function SubscriptionsPanel({\n recurring,\n span,\n}: {\n recurring: PlatformRevenue['recurring'];\n span: string;\n}) {\n const rows: Figure[] = [\n {\n label: 'Payment missed',\n status: 'past_due',\n note: 'Their last payment failed, so they may leave',\n value: integer.format(recurring.pastDueSubscriptions),\n tone: recurring.pastDueSubscriptions > 0 ? 'danger' : 'default',\n },\n {\n label: 'Set to end',\n status: 'non_renewing',\n note: 'Will not renew when the paid period ends',\n value: integer.format(recurring.nonRenewingSubscriptions),\n tone: recurring.nonRenewingSubscriptions > 0 ? 'danger' : 'default',\n },\n {\n label: 'Active',\n status: 'active',\n note: 'Paying for their plan',\n value: integer.format(recurring.activeSubscriptions),\n },\n {\n label: 'On a trial',\n status: 'trialing',\n note: 'Trying a plan, not yet paying',\n value: integer.format(recurring.trialingSubscriptions),\n },\n {\n label: 'Joined this period',\n note: `Started paying in ${span}`,\n value: integer.format(recurring.newInRange),\n },\n {\n label: 'Left this period',\n note: `Stopped paying in ${span}`,\n value: integer.format(recurring.churnedInRange),\n tone: recurring.churnedInRange > 0 ? 'danger' : 'default',\n },\n {\n label: 'Cancelled in total',\n note: 'Since the start',\n value: integer.format(recurring.cancelledSubscriptions),\n },\n ];\n\n return (\n <Panel title=\"Plan subscriptions\" caption=\"Right now\" height=\"var(--adm-panel-h)\">\n <FigureList rows={rows} />\n </Panel>\n );\n}\n"],"mappings":"AA6DM;AA5DN,SAAS,aAAa;AACtB,SAAS,kBAA+B;AAExC,MAAM,UAAU,IAAI,KAAK,aAAa,OAAO;AAGtC,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGG;AACD,QAAM,OAAiB;AAAA,IACrB;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,oBAAoB;AAAA,MACpD,MAAM,UAAU,uBAAuB,IAAI,WAAW;AAAA,IACxD;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,wBAAwB;AAAA,MACxD,MAAM,UAAU,2BAA2B,IAAI,WAAW;AAAA,IAC5D;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,mBAAmB;AAAA,IACrD;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,qBAAqB;AAAA,IACvD;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,MAAM,qBAAqB,IAAI;AAAA,MAC/B,OAAO,QAAQ,OAAO,UAAU,UAAU;AAAA,IAC5C;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,MAAM,qBAAqB,IAAI;AAAA,MAC/B,OAAO,QAAQ,OAAO,UAAU,cAAc;AAAA,MAC9C,MAAM,UAAU,iBAAiB,IAAI,WAAW;AAAA,IAClD;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,sBAAsB;AAAA,IACxD;AAAA,EACF;AAEA,SACE,oBAAC,SAAM,OAAM,sBAAqB,SAAQ,aAAY,QAAO,sBAC3D,8BAAC,cAAW,MAAY,GAC1B;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/admin/revenue/subscriptions-panel.tsx"],"sourcesContent":["import type { PlatformRevenue } from '@withpotter/lib/admin-api';\nimport { Panel } from '../_ui';\nimport { FigureList, type Figure } from './figure-list';\n\nconst integer = new Intl.NumberFormat('en-US');\n\n/** Where the subscription base stands, and what started in the window. */\nexport function SubscriptionsPanel({\n recurring,\n span,\n}: {\n recurring: PlatformRevenue['recurring'];\n span: string;\n}) {\n const rows: Figure[] = [\n {\n label: 'Past due',\n status: 'past_due',\n note: 'Payment failed, at risk of churning',\n value: integer.format(recurring.pastDueSubscriptions),\n tone: recurring.pastDueSubscriptions > 0 ? 'danger' : 'default',\n },\n {\n label: 'Non-renewing',\n status: 'non_renewing',\n note: 'Set to cancel at period end',\n value: integer.format(recurring.nonRenewingSubscriptions),\n tone: recurring.nonRenewingSubscriptions > 0 ? 'danger' : 'default',\n },\n {\n label: 'Active',\n status: 'active',\n note: 'Paying on a live billing cycle',\n value: integer.format(recurring.activeSubscriptions),\n },\n {\n label: 'Trialing',\n status: 'trialing',\n note: 'In trial, not yet billed',\n value: integer.format(recurring.trialingSubscriptions),\n },\n {\n label: 'New this period',\n note: `Started in ${span}`,\n value: integer.format(recurring.newInRange),\n },\n {\n label: 'Churned this period',\n note: `Cancelled in ${span}`,\n value: integer.format(recurring.churnedInRange),\n tone: recurring.churnedInRange > 0 ? 'danger' : 'default',\n },\n {\n label: 'Cancelled',\n note: 'Lifetime total',\n value: integer.format(recurring.cancelledSubscriptions),\n },\n ];\n\n return (\n <Panel title=\"Subscriptions\" caption=\"Today\" height=\"var(--adm-panel-h)\">\n <FigureList rows={rows} />\n </Panel>\n );\n}\n"],"mappings":"AA6DM;AA5DN,SAAS,aAAa;AACtB,SAAS,kBAA+B;AAExC,MAAM,UAAU,IAAI,KAAK,aAAa,OAAO;AAGtC,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGG;AACD,QAAM,OAAiB;AAAA,IACrB;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,oBAAoB;AAAA,MACpD,MAAM,UAAU,uBAAuB,IAAI,WAAW;AAAA,IACxD;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,wBAAwB;AAAA,MACxD,MAAM,UAAU,2BAA2B,IAAI,WAAW;AAAA,IAC5D;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,mBAAmB;AAAA,IACrD;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,qBAAqB;AAAA,IACvD;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,MAAM,cAAc,IAAI;AAAA,MACxB,OAAO,QAAQ,OAAO,UAAU,UAAU;AAAA,IAC5C;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,MAAM,gBAAgB,IAAI;AAAA,MAC1B,OAAO,QAAQ,OAAO,UAAU,cAAc;AAAA,MAC9C,MAAM,UAAU,iBAAiB,IAAI,WAAW;AAAA,IAClD;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,MAAM;AAAA,MACN,OAAO,QAAQ,OAAO,UAAU,sBAAsB;AAAA,IACxD;AAAA,EACF;AAEA,SACE,oBAAC,SAAM,OAAM,iBAAgB,SAAQ,SAAQ,QAAO,sBAClD,8BAAC,cAAW,MAAY,GAC1B;AAEJ;","names":[]}
@@ -17,7 +17,7 @@ function TopTenantsPanel({
17
17
  return /* @__PURE__ */ jsx(
18
18
  Panel,
19
19
  {
20
- title: "Biggest merchants by sales",
20
+ title: "Top merchants by GMV",
21
21
  count: tenants.length || void 0,
22
22
  caption: focus ?? void 0,
23
23
  action: /* @__PURE__ */ jsx(Link, { href: "/admin/tenants", children: "View all" }),
@@ -31,9 +31,9 @@ function TopTenantsPanel({
31
31
  head: /* @__PURE__ */ jsxs("tr", { children: [
32
32
  /* @__PURE__ */ jsx(Th, { children: "Merchant" }),
33
33
  /* @__PURE__ */ jsx(Th, { align: "right", children: "Orders" }),
34
- /* @__PURE__ */ jsx(Th, { align: "right", children: "Average order" }),
35
- /* @__PURE__ */ jsx(Th, { align: "right", children: "Sales" }),
36
- /* @__PURE__ */ jsx(Th, { align: "right", children: "Share of sales" })
34
+ /* @__PURE__ */ jsx(Th, { align: "right", children: "AOV" }),
35
+ /* @__PURE__ */ jsx(Th, { align: "right", children: "GMV" }),
36
+ /* @__PURE__ */ jsx(Th, { align: "right", children: "% of GMV" })
37
37
  ] }),
38
38
  children: tenants.map((t) => {
39
39
  const aov = t.orders > 0 ? t.gmv / t.orders : 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/revenue/top-tenants-panel.tsx"],"sourcesContent":["import Link from 'next/link';\nimport { useRouter } from 'next/navigation';\nimport { EmptyNote, TableRow, TableShell, Th } from '@withpotter/ui-kit';\nimport type { PlatformRevenue } from '@withpotter/lib/admin-api';\nimport { EntityAvatar } from '../_fx';\nimport { PICK_CURRENCY, Panel, moneyIn } from '../_ui';\nimport { logoOf } from '../tenants/tenants-logo';\nimport styles from './revenue.module.css';\n\nconst integer = new Intl.NumberFormat('en-US');\n\n/**\n * Merchants ranked by GMV within one currency, with order count, AOV and\n * share of that currency's lifetime GMV.\n */\nexport function TopTenantsPanel({\n tenants,\n lifetime,\n focus,\n}: {\n tenants: PlatformRevenue['gmv']['topTenants'];\n /** Lifetime GMV in `focus`, the base for each share. */\n lifetime: number;\n /** The one currency ranked, or null when there are several and none is chosen. */\n focus: string | null;\n}) {\n const router = useRouter();\n const money = moneyIn(focus ?? '');\n\n return (\n <Panel\n title=\"Biggest merchants by sales\"\n count={tenants.length || undefined}\n caption={focus ?? undefined}\n action={<Link href=\"/admin/tenants\">View all</Link>}\n flush\n >\n {tenants.length === 0 ? (\n <EmptyNote className={styles.empty}>\n {focus ? `No ${focus} merchant revenue recorded yet.` : PICK_CURRENCY}\n </EmptyNote>\n ) : (\n <TableShell\n bare\n minWidth={520}\n density=\"compact\"\n head={\n <tr>\n <Th>Merchant</Th>\n <Th align=\"right\">Orders</Th>\n <Th align=\"right\">Average order</Th>\n <Th align=\"right\">Sales</Th>\n <Th align=\"right\">Share of sales</Th>\n </tr>\n }\n >\n {tenants.map((t) => {\n const aov = t.orders > 0 ? t.gmv / t.orders : 0;\n const share = lifetime > 0 ? (t.gmv / lifetime) * 100 : 0;\n const logo = logoOf(t);\n return (\n <TableRow\n key={t.id}\n onClick={() => router.push(`/admin/tenants/${t.id}`)}\n >\n <td className={styles.name}>\n <span className={styles.tenant}>\n {logo && (\n <EntityAvatar\n name={t.businessName}\n src={logo}\n size={28}\n />\n )}\n <span className={styles.tenantText}>\n <Link\n href={`/admin/tenants/${t.id}`}\n title={t.businessName}\n onClick={(e) => e.stopPropagation()}\n >\n {t.businessName}\n </Link>\n {t.slug && (\n <span className={styles.slug} title={t.slug}>\n {t.slug}\n </span>\n )}\n </span>\n </span>\n </td>\n <td className={styles.num}>{integer.format(t.orders)}</td>\n <td className={styles.num}>{money(aov)}</td>\n <td className={styles.numStrong}>{money(t.gmv)}</td>\n <td className={styles.num}>\n <span className={styles.share}>\n <span className={styles.shareTrack} aria-hidden>\n <span\n className={styles.shareFill}\n style={{ width: `${Math.min(share, 100)}%` }}\n />\n </span>\n {share.toFixed(1)}%\n </span>\n </td>\n </TableRow>\n );\n })}\n </TableShell>\n )}\n </Panel>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/admin/revenue/top-tenants-panel.tsx"],"sourcesContent":["import Link from 'next/link';\nimport { useRouter } from 'next/navigation';\nimport { EmptyNote, TableRow, TableShell, Th } from '@withpotter/ui-kit';\nimport type { PlatformRevenue } from '@withpotter/lib/admin-api';\nimport { EntityAvatar } from '../_fx';\nimport { PICK_CURRENCY, Panel, moneyIn } from '../_ui';\nimport { logoOf } from '../tenants/tenants-logo';\nimport styles from './revenue.module.css';\n\nconst integer = new Intl.NumberFormat('en-US');\n\n/**\n * Merchants ranked by GMV within one currency, with order count, AOV and\n * share of that currency's lifetime GMV.\n */\nexport function TopTenantsPanel({\n tenants,\n lifetime,\n focus,\n}: {\n tenants: PlatformRevenue['gmv']['topTenants'];\n /** Lifetime GMV in `focus`, the base for each share. */\n lifetime: number;\n /** The one currency ranked, or null when there are several and none is chosen. */\n focus: string | null;\n}) {\n const router = useRouter();\n const money = moneyIn(focus ?? '');\n\n return (\n <Panel\n title=\"Top merchants by GMV\"\n count={tenants.length || undefined}\n caption={focus ?? undefined}\n action={<Link href=\"/admin/tenants\">View all</Link>}\n flush\n >\n {tenants.length === 0 ? (\n <EmptyNote className={styles.empty}>\n {focus ? `No ${focus} merchant revenue recorded yet.` : PICK_CURRENCY}\n </EmptyNote>\n ) : (\n <TableShell\n bare\n minWidth={520}\n density=\"compact\"\n head={\n <tr>\n <Th>Merchant</Th>\n <Th align=\"right\">Orders</Th>\n <Th align=\"right\">AOV</Th>\n <Th align=\"right\">GMV</Th>\n <Th align=\"right\">% of GMV</Th>\n </tr>\n }\n >\n {tenants.map((t) => {\n const aov = t.orders > 0 ? t.gmv / t.orders : 0;\n const share = lifetime > 0 ? (t.gmv / lifetime) * 100 : 0;\n const logo = logoOf(t);\n return (\n <TableRow\n key={t.id}\n onClick={() => router.push(`/admin/tenants/${t.id}`)}\n >\n <td className={styles.name}>\n <span className={styles.tenant}>\n {logo && (\n <EntityAvatar\n name={t.businessName}\n src={logo}\n size={28}\n />\n )}\n <span className={styles.tenantText}>\n <Link\n href={`/admin/tenants/${t.id}`}\n title={t.businessName}\n onClick={(e) => e.stopPropagation()}\n >\n {t.businessName}\n </Link>\n {t.slug && (\n <span className={styles.slug} title={t.slug}>\n {t.slug}\n </span>\n )}\n </span>\n </span>\n </td>\n <td className={styles.num}>{integer.format(t.orders)}</td>\n <td className={styles.num}>{money(aov)}</td>\n <td className={styles.numStrong}>{money(t.gmv)}</td>\n <td className={styles.num}>\n <span className={styles.share}>\n <span className={styles.shareTrack} aria-hidden>\n <span\n className={styles.shareFill}\n style={{ width: `${Math.min(share, 100)}%` }}\n />\n </span>\n {share.toFixed(1)}%\n </span>\n </td>\n </TableRow>\n );\n })}\n </TableShell>\n )}\n </Panel>\n );\n}\n"],"mappings":"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","names":[]}
@@ -2,17 +2,21 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { useRouter } from "next/navigation";
5
- import { Button } from "@withpotter/ui-kit";
5
+ import { Button, useConfirm, useToast } from "@withpotter/ui-kit";
6
6
  import { SUPPORT_INBOX_EMAIL } from "@withpotter/lib/support-inbox";
7
7
  import { useAdminSession } from "../hooks";
8
+ import { settingsStore } from "../_settings";
8
9
  import { useModuleOn } from "../_shell/modules-context";
9
10
  import { signOutAdmin } from "../_shell/sign-out";
10
11
  import { ChangePasswordDialog } from "./change-password-dialog";
11
12
  import { ProfileCard } from "./profile-card";
12
13
  import { SettingRow, SettingsCard } from "./setting-row";
14
+ import { SystemStatusCard } from "./system-status-card";
13
15
  import styles from "./settings.module.css";
14
16
  function AccountTab() {
15
17
  const router = useRouter();
18
+ const confirm = useConfirm();
19
+ const { toast } = useToast();
16
20
  const { data: session } = useAdminSession();
17
21
  const [changing, setChanging] = useState(false);
18
22
  const [leaving, setLeaving] = useState(false);
@@ -22,6 +26,17 @@ function AccountTab() {
22
26
  await signOutAdmin();
23
27
  router.replace("/admin/login");
24
28
  };
29
+ const reset = async () => {
30
+ const ok = await confirm({
31
+ title: "Reset settings on this device?",
32
+ description: "Density, accessibility, notification and shortcut choices go back to their defaults. Your account is not affected.",
33
+ confirmLabel: "Reset settings",
34
+ tone: "danger"
35
+ });
36
+ if (!ok) return;
37
+ settingsStore.reset();
38
+ toast({ title: "Settings reset on this device" });
39
+ };
25
40
  return /* @__PURE__ */ jsxs("div", { className: styles.stack, children: [
26
41
  session && /* @__PURE__ */ jsx(ProfileCard, { session }),
27
42
  /* @__PURE__ */ jsxs(SettingsCard, { title: "Security", children: [
@@ -42,6 +57,14 @@ function AccountTab() {
42
57
  }
43
58
  )
44
59
  ] }),
60
+ /* @__PURE__ */ jsx(SettingsCard, { title: "This device", children: /* @__PURE__ */ jsx(
61
+ SettingRow,
62
+ {
63
+ label: "Reset all settings on this device",
64
+ description: "Every preference on this page returns to its default.",
65
+ children: /* @__PURE__ */ jsx(Button, { variant: "danger", onClick: reset, children: "Reset" })
66
+ }
67
+ ) }),
45
68
  supportOn && /* @__PURE__ */ jsx(SettingsCard, { title: "Support inbox", children: /* @__PURE__ */ jsx(
46
69
  SettingRow,
47
70
  {
@@ -50,6 +73,7 @@ function AccountTab() {
50
73
  children: /* @__PURE__ */ jsx("span", { className: styles.value, title: SUPPORT_INBOX_EMAIL, children: SUPPORT_INBOX_EMAIL })
51
74
  }
52
75
  ) }),
76
+ /* @__PURE__ */ jsx(SystemStatusCard, {}),
53
77
  changing && /* @__PURE__ */ jsx(ChangePasswordDialog, { onClose: () => setChanging(false) })
54
78
  ] });
55
79
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/settings/account-tab.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { useRouter } from 'next/navigation';\nimport { Button } from '@withpotter/ui-kit';\nimport { SUPPORT_INBOX_EMAIL } from '@withpotter/lib/support-inbox';\nimport { useAdminSession } from '../hooks';\nimport { useModuleOn } from '../_shell/modules-context';\nimport { signOutAdmin } from '../_shell/sign-out';\nimport { ChangePasswordDialog } from './change-password-dialog';\nimport { ProfileCard } from './profile-card';\nimport { SettingRow, SettingsCard } from './setting-row';\nimport styles from './settings.module.css';\n\n/**\n * Who you are and how you sign in. The support inbox\n * address shows only where this box serves Support.\n */\nexport function AccountTab() {\n const router = useRouter();\n const { data: session } = useAdminSession();\n const [changing, setChanging] = useState(false);\n const [leaving, setLeaving] = useState(false);\n const supportOn = useModuleOn('support');\n\n const signOut = async () => {\n setLeaving(true);\n await signOutAdmin();\n router.replace('/admin/login');\n };\n\n return (\n <div className={styles.stack}>\n {session && <ProfileCard session={session} />}\n <SettingsCard title=\"Security\">\n <SettingRow\n label=\"Password\"\n description=\"At least 12 characters. You stay signed in here.\"\n >\n <Button variant=\"secondary\" onClick={() => setChanging(true)}>\n Change password\n </Button>\n </SettingRow>\n <SettingRow\n label=\"Sign out\"\n description=\"Also ends any View as owner session.\"\n >\n <Button variant=\"secondary\" loading={leaving} onClick={signOut}>\n Sign out\n </Button>\n </SettingRow>\n </SettingsCard>\n {supportOn && (\n <SettingsCard title=\"Support inbox\">\n <SettingRow\n label=\"Inbound address\"\n description=\"Merchants write here; each email opens a case in Support.\"\n >\n <span className={styles.value} title={SUPPORT_INBOX_EMAIL}>\n {SUPPORT_INBOX_EMAIL}\n </span>\n </SettingRow>\n </SettingsCard>\n )}\n {changing && <ChangePasswordDialog onClose={() => setChanging(false)} />}\n </div>\n );\n}\n"],"mappings":";AAiCkB,cACZ,YADY;AA/BlB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;AAC7B,SAAS,4BAA4B;AACrC,SAAS,mBAAmB;AAC5B,SAAS,YAAY,oBAAoB;AACzC,OAAO,YAAY;AAMZ,SAAS,aAAa;AAC3B,QAAM,SAAS,UAAU;AACzB,QAAM,EAAE,MAAM,QAAQ,IAAI,gBAAgB;AAC1C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,YAAY,YAAY,SAAS;AAEvC,QAAM,UAAU,YAAY;AAC1B,eAAW,IAAI;AACf,UAAM,aAAa;AACnB,WAAO,QAAQ,cAAc;AAAA,EAC/B;AAEA,SACE,qBAAC,SAAI,WAAW,OAAO,OACpB;AAAA,eAAW,oBAAC,eAAY,SAAkB;AAAA,IAC3C,qBAAC,gBAAa,OAAM,YAClB;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,aAAY;AAAA,UAEZ,8BAAC,UAAO,SAAQ,aAAY,SAAS,MAAM,YAAY,IAAI,GAAG,6BAE9D;AAAA;AAAA,MACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,aAAY;AAAA,UAEZ,8BAAC,UAAO,SAAQ,aAAY,SAAS,SAAS,SAAS,SAAS,sBAEhE;AAAA;AAAA,MACF;AAAA,OACF;AAAA,IACC,aACC,oBAAC,gBAAa,OAAM,iBAClB;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,aAAY;AAAA,QAEZ,8BAAC,UAAK,WAAW,OAAO,OAAO,OAAO,qBACnC,+BACH;AAAA;AAAA,IACF,GACF;AAAA,IAED,YAAY,oBAAC,wBAAqB,SAAS,MAAM,YAAY,KAAK,GAAG;AAAA,KACxE;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/admin/settings/account-tab.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { useRouter } from 'next/navigation';\nimport { Button, useConfirm, useToast } from '@withpotter/ui-kit';\nimport { SUPPORT_INBOX_EMAIL } from '@withpotter/lib/support-inbox';\nimport { useAdminSession } from '../hooks';\nimport { settingsStore } from '../_settings';\nimport { useModuleOn } from '../_shell/modules-context';\nimport { signOutAdmin } from '../_shell/sign-out';\nimport { ChangePasswordDialog } from './change-password-dialog';\nimport { ProfileCard } from './profile-card';\nimport { SettingRow, SettingsCard } from './setting-row';\nimport { SystemStatusCard } from './system-status-card';\nimport styles from './settings.module.css';\n\n/**\n * Who you are, how you sign in, and the box's own health. The support inbox\n * address shows only where this box serves Support.\n */\nexport function AccountTab() {\n const router = useRouter();\n const confirm = useConfirm();\n const { toast } = useToast();\n const { data: session } = useAdminSession();\n const [changing, setChanging] = useState(false);\n const [leaving, setLeaving] = useState(false);\n const supportOn = useModuleOn('support');\n\n const signOut = async () => {\n setLeaving(true);\n await signOutAdmin();\n router.replace('/admin/login');\n };\n\n const reset = async () => {\n const ok = await confirm({\n title: 'Reset settings on this device?',\n description:\n 'Density, accessibility, notification and shortcut choices go back to their defaults. Your account is not affected.',\n confirmLabel: 'Reset settings',\n tone: 'danger',\n });\n if (!ok) return;\n settingsStore.reset();\n toast({ title: 'Settings reset on this device' });\n };\n\n return (\n <div className={styles.stack}>\n {session && <ProfileCard session={session} />}\n <SettingsCard title=\"Security\">\n <SettingRow\n label=\"Password\"\n description=\"At least 12 characters. You stay signed in here.\"\n >\n <Button variant=\"secondary\" onClick={() => setChanging(true)}>\n Change password\n </Button>\n </SettingRow>\n <SettingRow\n label=\"Sign out\"\n description=\"Also ends any View as owner session.\"\n >\n <Button variant=\"secondary\" loading={leaving} onClick={signOut}>\n Sign out\n </Button>\n </SettingRow>\n </SettingsCard>\n <SettingsCard title=\"This device\">\n <SettingRow\n label=\"Reset all settings on this device\"\n description=\"Every preference on this page returns to its default.\"\n >\n <Button variant=\"danger\" onClick={reset}>\n Reset\n </Button>\n </SettingRow>\n </SettingsCard>\n {supportOn && (\n <SettingsCard title=\"Support inbox\">\n <SettingRow\n label=\"Inbound address\"\n description=\"Merchants write here; each email opens a case in Support.\"\n >\n <span className={styles.value} title={SUPPORT_INBOX_EMAIL}>\n {SUPPORT_INBOX_EMAIL}\n </span>\n </SettingRow>\n </SettingsCard>\n )}\n <SystemStatusCard />\n {changing && <ChangePasswordDialog onClose={() => setChanging(false)} />}\n </div>\n );\n}\n"],"mappings":";AAkDkB,cACZ,YADY;AAhDlB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,QAAQ,YAAY,gBAAgB;AAC7C,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;AAC7B,SAAS,4BAA4B;AACrC,SAAS,mBAAmB;AAC5B,SAAS,YAAY,oBAAoB;AACzC,SAAS,wBAAwB;AACjC,OAAO,YAAY;AAMZ,SAAS,aAAa;AAC3B,QAAM,SAAS,UAAU;AACzB,QAAM,UAAU,WAAW;AAC3B,QAAM,EAAE,MAAM,IAAI,SAAS;AAC3B,QAAM,EAAE,MAAM,QAAQ,IAAI,gBAAgB;AAC1C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,YAAY,YAAY,SAAS;AAEvC,QAAM,UAAU,YAAY;AAC1B,eAAW,IAAI;AACf,UAAM,aAAa;AACnB,WAAO,QAAQ,cAAc;AAAA,EAC/B;AAEA,QAAM,QAAQ,YAAY;AACxB,UAAM,KAAK,MAAM,QAAQ;AAAA,MACvB,OAAO;AAAA,MACP,aACE;AAAA,MACF,cAAc;AAAA,MACd,MAAM;AAAA,IACR,CAAC;AACD,QAAI,CAAC,GAAI;AACT,kBAAc,MAAM;AACpB,UAAM,EAAE,OAAO,gCAAgC,CAAC;AAAA,EAClD;AAEA,SACE,qBAAC,SAAI,WAAW,OAAO,OACpB;AAAA,eAAW,oBAAC,eAAY,SAAkB;AAAA,IAC3C,qBAAC,gBAAa,OAAM,YAClB;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,aAAY;AAAA,UAEZ,8BAAC,UAAO,SAAQ,aAAY,SAAS,MAAM,YAAY,IAAI,GAAG,6BAE9D;AAAA;AAAA,MACF;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,aAAY;AAAA,UAEZ,8BAAC,UAAO,SAAQ,aAAY,SAAS,SAAS,SAAS,SAAS,sBAEhE;AAAA;AAAA,MACF;AAAA,OACF;AAAA,IACA,oBAAC,gBAAa,OAAM,eAClB;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,aAAY;AAAA,QAEZ,8BAAC,UAAO,SAAQ,UAAS,SAAS,OAAO,mBAEzC;AAAA;AAAA,IACF,GACF;AAAA,IACC,aACC,oBAAC,gBAAa,OAAM,iBAClB;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,aAAY;AAAA,QAEZ,8BAAC,UAAK,WAAW,OAAO,OAAO,OAAO,qBACnC,+BACH;AAAA;AAAA,IACF,GACF;AAAA,IAEF,oBAAC,oBAAiB;AAAA,IACjB,YAAY,oBAAC,wBAAqB,SAAS,MAAM,YAAY,KAAK,GAAG;AAAA,KACxE;AAEJ;","names":[]}
@@ -17,8 +17,8 @@ const THEMES = [
17
17
  const START_OPTIONS = [
18
18
  { value: "overview", label: "Overview" },
19
19
  { value: "support", label: "Support" },
20
- { value: "merchants", label: "Workspaces" },
21
- { value: "people", label: "User accounts" }
20
+ { value: "merchants", label: "Merchants" },
21
+ { value: "people", label: "People" }
22
22
  ];
23
23
  function GeneralTab() {
24
24
  const settings = useSettings();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/settings/general-tab.tsx"],"sourcesContent":["'use client';\n\nimport { Select } from '@withpotter/ui-kit';\nimport { useTheme } from '@withpotter/lib/theme-context';\nimport { RANGE_OPTIONS, usePersistedDateRange, type RangeKey } from '../_ui';\nimport { useSettings, type AdminSettings } from '../_settings';\nimport { useModuleOn } from '../_shell/modules-context';\nimport { useSidebarCollapsed, sidebarStore } from '../_shell/use-shell-prefs';\nimport { Segmented, SettingRow, SettingsCard } from './setting-row';\nimport { useSave } from './use-save';\nimport styles from './settings.module.css';\n\ntype Theme = 'system' | 'light' | 'dark';\n\nconst THEMES = [\n { value: 'system' as Theme, label: 'System' },\n { value: 'light' as Theme, label: 'Light' },\n { value: 'dark' as Theme, label: 'Dark' },\n];\n\nconst START_OPTIONS: Array<{\n value: AdminSettings['startPage'];\n label: string;\n}> = [\n { value: 'overview', label: 'Overview' },\n { value: 'support', label: 'Support' },\n { value: 'merchants', label: 'Workspaces' },\n { value: 'people', label: 'User accounts' },\n];\n\n/**\n * Look, layout and the views every page opens with. No display currency on a\n * box: money is shown per currency and never converted, so there is nothing\n * to pick. Support is a start page only where this box serves Support.\n */\nexport function GeneralTab() {\n const settings = useSettings();\n const { update, saved } = useSave();\n const { theme, setTheme } = useTheme();\n const { rangeKey, setRangeKey } = usePersistedDateRange();\n const collapsed = useSidebarCollapsed();\n const supportOn = useModuleOn('support');\n const startOptions = START_OPTIONS.filter(\n (o) => supportOn || o.value !== 'support'\n );\n\n return (\n <div className={styles.stack}>\n <SettingsCard title=\"Appearance\">\n <SettingRow\n label=\"Theme\"\n description=\"System follows your computer's light or dark setting.\"\n >\n <Segmented\n label=\"Theme\"\n value={theme}\n options={THEMES}\n onChange={(next) => {\n setTheme(next);\n saved();\n }}\n />\n </SettingRow>\n <SettingRow\n label=\"Density\"\n description=\"Compact fits more rows and cards on screen.\"\n >\n <Segmented\n label=\"Density\"\n value={settings.density}\n options={[\n { value: 'comfortable', label: 'Comfortable' },\n { value: 'compact', label: 'Compact' },\n ]}\n onChange={(density) => update({ density })}\n />\n </SettingRow>\n <SettingRow\n label=\"Sidebar\"\n description=\"Collapsed shows icons only. You can also toggle it from the sidebar.\"\n >\n <Segmented\n label=\"Sidebar\"\n value={collapsed ? 'collapsed' : 'expanded'}\n options={[\n { value: 'expanded', label: 'Expanded' },\n { value: 'collapsed', label: 'Collapsed' },\n ]}\n onChange={(next) => {\n sidebarStore.set(next === 'collapsed');\n saved();\n }}\n />\n </SettingRow>\n </SettingsCard>\n\n <SettingsCard title=\"Defaults\" description=\"What pages open with.\">\n <SettingRow\n label=\"Default period\"\n description=\"The date range reports and charts start on.\"\n >\n <Select\n className={styles.select}\n ariaLabel=\"Default period\"\n value={rangeKey}\n options={RANGE_OPTIONS.map((o) => ({\n value: o.key,\n label: o.label,\n }))}\n onChange={(key) => {\n setRangeKey(key as RangeKey);\n saved();\n }}\n />\n </SettingRow>\n <SettingRow\n label=\"Start page\"\n description=\"Where the console opens when you sign in or reload on Overview.\"\n >\n <Select\n className={styles.select}\n ariaLabel=\"Start page\"\n value={settings.startPage}\n options={startOptions}\n onChange={(value) =>\n update({ startPage: value as AdminSettings['startPage'] })\n }\n />\n </SettingRow>\n </SettingsCard>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/admin/settings/general-tab.tsx"],"sourcesContent":["'use client';\n\nimport { Select } from '@withpotter/ui-kit';\nimport { useTheme } from '@withpotter/lib/theme-context';\nimport { RANGE_OPTIONS, usePersistedDateRange, type RangeKey } from '../_ui';\nimport { useSettings, type AdminSettings } from '../_settings';\nimport { useModuleOn } from '../_shell/modules-context';\nimport { useSidebarCollapsed, sidebarStore } from '../_shell/use-shell-prefs';\nimport { Segmented, SettingRow, SettingsCard } from './setting-row';\nimport { useSave } from './use-save';\nimport styles from './settings.module.css';\n\ntype Theme = 'system' | 'light' | 'dark';\n\nconst THEMES = [\n { value: 'system' as Theme, label: 'System' },\n { value: 'light' as Theme, label: 'Light' },\n { value: 'dark' as Theme, label: 'Dark' },\n];\n\nconst START_OPTIONS: Array<{\n value: AdminSettings['startPage'];\n label: string;\n}> = [\n { value: 'overview', label: 'Overview' },\n { value: 'support', label: 'Support' },\n { value: 'merchants', label: 'Merchants' },\n { value: 'people', label: 'People' },\n];\n\n/**\n * Look, layout and the views every page opens with. No display currency on a\n * box: money is shown per currency and never converted, so there is nothing\n * to pick. Support is a start page only where this box serves Support.\n */\nexport function GeneralTab() {\n const settings = useSettings();\n const { update, saved } = useSave();\n const { theme, setTheme } = useTheme();\n const { rangeKey, setRangeKey } = usePersistedDateRange();\n const collapsed = useSidebarCollapsed();\n const supportOn = useModuleOn('support');\n const startOptions = START_OPTIONS.filter(\n (o) => supportOn || o.value !== 'support'\n );\n\n return (\n <div className={styles.stack}>\n <SettingsCard title=\"Appearance\">\n <SettingRow\n label=\"Theme\"\n description=\"System follows your computer's light or dark setting.\"\n >\n <Segmented\n label=\"Theme\"\n value={theme}\n options={THEMES}\n onChange={(next) => {\n setTheme(next);\n saved();\n }}\n />\n </SettingRow>\n <SettingRow\n label=\"Density\"\n description=\"Compact fits more rows and cards on screen.\"\n >\n <Segmented\n label=\"Density\"\n value={settings.density}\n options={[\n { value: 'comfortable', label: 'Comfortable' },\n { value: 'compact', label: 'Compact' },\n ]}\n onChange={(density) => update({ density })}\n />\n </SettingRow>\n <SettingRow\n label=\"Sidebar\"\n description=\"Collapsed shows icons only. You can also toggle it from the sidebar.\"\n >\n <Segmented\n label=\"Sidebar\"\n value={collapsed ? 'collapsed' : 'expanded'}\n options={[\n { value: 'expanded', label: 'Expanded' },\n { value: 'collapsed', label: 'Collapsed' },\n ]}\n onChange={(next) => {\n sidebarStore.set(next === 'collapsed');\n saved();\n }}\n />\n </SettingRow>\n </SettingsCard>\n\n <SettingsCard title=\"Defaults\" description=\"What pages open with.\">\n <SettingRow\n label=\"Default period\"\n description=\"The date range reports and charts start on.\"\n >\n <Select\n className={styles.select}\n ariaLabel=\"Default period\"\n value={rangeKey}\n options={RANGE_OPTIONS.map((o) => ({\n value: o.key,\n label: o.label,\n }))}\n onChange={(key) => {\n setRangeKey(key as RangeKey);\n saved();\n }}\n />\n </SettingRow>\n <SettingRow\n label=\"Start page\"\n description=\"Where the console opens when you sign in or reload on Overview.\"\n >\n <Select\n className={styles.select}\n ariaLabel=\"Start page\"\n value={settings.startPage}\n options={startOptions}\n onChange={(value) =>\n update({ startPage: value as AdminSettings['startPage'] })\n }\n />\n </SettingRow>\n </SettingsCard>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useQuery } from "@tanstack/react-query";
4
+ import { adminReadinessApi } from "@withpotter/lib/admin-readiness-api";
5
+ import { overallOf, SystemStatusPanel } from "../_shell/system-status-panel";
6
+ import { SettingsCard } from "./setting-row";
7
+ function SystemStatusCard() {
8
+ const query = useQuery({
9
+ queryKey: ["platform-admin", "readiness"],
10
+ queryFn: adminReadinessApi.readiness,
11
+ staleTime: 6e4,
12
+ retry: 1
13
+ });
14
+ return /* @__PURE__ */ jsx(SettingsCard, { title: "System status", children: /* @__PURE__ */ jsx(
15
+ SystemStatusPanel,
16
+ {
17
+ data: query.data,
18
+ overall: overallOf(query.data, query.isError),
19
+ isLoading: query.isLoading,
20
+ isError: query.isError,
21
+ isFetching: query.isFetching,
22
+ checkedAt: query.dataUpdatedAt,
23
+ onRefresh: () => void query.refetch()
24
+ }
25
+ ) });
26
+ }
27
+ export {
28
+ SystemStatusCard
29
+ };
30
+ //# sourceMappingURL=system-status-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/admin/settings/system-status-card.tsx"],"sourcesContent":["'use client';\n\nimport { useQuery } from '@tanstack/react-query';\nimport { adminReadinessApi } from '@withpotter/lib/admin-readiness-api';\nimport { overallOf, SystemStatusPanel } from '../_shell/system-status-panel';\nimport { SettingsCard } from './setting-row';\n\n/** The deployment's integration checks, each with its state. */\nexport function SystemStatusCard() {\n const query = useQuery({\n queryKey: ['platform-admin', 'readiness'],\n queryFn: adminReadinessApi.readiness,\n staleTime: 60_000,\n retry: 1,\n });\n\n return (\n <SettingsCard title=\"System status\">\n <SystemStatusPanel\n data={query.data}\n overall={overallOf(query.data, query.isError)}\n isLoading={query.isLoading}\n isError={query.isError}\n isFetching={query.isFetching}\n checkedAt={query.dataUpdatedAt}\n onRefresh={() => void query.refetch()}\n />\n </SettingsCard>\n );\n}\n"],"mappings":";AAkBM;AAhBN,SAAS,gBAAgB;AACzB,SAAS,yBAAyB;AAClC,SAAS,WAAW,yBAAyB;AAC7C,SAAS,oBAAoB;AAGtB,SAAS,mBAAmB;AACjC,QAAM,QAAQ,SAAS;AAAA,IACrB,UAAU,CAAC,kBAAkB,WAAW;AAAA,IACxC,SAAS,kBAAkB;AAAA,IAC3B,WAAW;AAAA,IACX,OAAO;AAAA,EACT,CAAC;AAED,SACE,oBAAC,gBAAa,OAAM,iBAClB;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,MAAM;AAAA,MACZ,SAAS,UAAU,MAAM,MAAM,MAAM,OAAO;AAAA,MAC5C,WAAW,MAAM;AAAA,MACjB,SAAS,MAAM;AAAA,MACf,YAAY,MAAM;AAAA,MAClB,WAAW,MAAM;AAAA,MACjB,WAAW,MAAM,KAAK,MAAM,QAAQ;AAAA;AAAA,EACtC,GACF;AAEJ;","names":[]}
@@ -75,8 +75,11 @@
75
75
  outline-offset: -2px;
76
76
  }
77
77
 
78
- /* Column header with a hairline, not a shadow. */
78
+ /* Sticky column header with a hairline, not a shadow. */
79
79
  .scroll thead th {
80
+ position: sticky;
81
+ top: 0;
82
+ z-index: 1;
80
83
  background: var(--bg-base);
81
84
  box-shadow: inset 0 -1px 0 var(--border-subtle);
82
85
  white-space: nowrap;
@@ -3,8 +3,7 @@ function moneyIn(currency, decimals = 0) {
3
3
  try {
4
4
  return new Intl.NumberFormat("en-US", {
5
5
  style: "currency",
6
- currencyDisplay: "narrowSymbol",
7
- currency: currency || "NGN",
6
+ currency: currency || "USD",
8
7
  maximumFractionDigits: decimals
9
8
  }).format(n);
10
9
  } catch {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/admin/tenants/%5Bid%5D/commerce/format.ts"],"sourcesContent":["import type { TenantProduct } from '@withpotter/lib/admin-api';\n\n/** Amounts in the merchant's own currency, whole units for headlines. */\nexport function moneyIn(currency: string, decimals = 0) {\n return (n: number) => {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currencyDisplay: 'narrowSymbol',\n currency: currency || 'NGN',\n maximumFractionDigits: decimals,\n }).format(n);\n } catch {\n return `${currency} ${Math.round(n).toLocaleString()}`;\n }\n };\n}\n\nexport type Money = (n: number) => string;\n\n/** 1.2k / 3.4m, for figures in tight tiles. */\nexport const compact = (n: number) =>\n new Intl.NumberFormat('en-US', {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(n);\n\nexport const shortDate = (iso: string) =>\n new Intl.DateTimeFormat('en', { month: 'short', day: 'numeric' }).format(\n new Date(iso),\n );\n\n/** Sentence-case a machine word: \"checked_in\" → \"Checked in\". */\nexport const humanize = (s: string) => {\n const t = s.replace(/[_-]+/g, ' ').trim();\n return t ? t[0].toUpperCase() + t.slice(1) : '–';\n};\n\nexport type PillTone =\n 'success' | 'pending' | 'failed' | 'processing' | 'neutral';\n\nconst TONE_OF: Record<string, PillTone> = {\n completed: 'success',\n paid: 'success',\n success: 'success',\n settled: 'success',\n fulfilled: 'success',\n delivered: 'success',\n collected: 'success',\n pending: 'pending',\n unpaid: 'pending',\n awaiting_confirmation: 'pending',\n authorized: 'pending',\n unfulfilled: 'pending',\n partial: 'pending',\n confirmed: 'processing',\n processing: 'processing',\n checked_in: 'processing',\n ready: 'processing',\n failed: 'failed',\n reversed: 'failed',\n expired: 'failed',\n cancelled: 'neutral',\n refunded: 'neutral',\n partially_refunded: 'neutral',\n};\n\nexport const toneOf = (status: string): PillTone =>\n TONE_OF[status?.toLowerCase()] ?? 'neutral';\n\nexport type StockState = {\n label: string;\n tone: PillTone;\n available: number | null;\n};\n\n/** What a shelf looks like for one item, from the counts the API sends. */\nexport function stockOf(p: TenantProduct): StockState {\n if (!p.trackInventory || p.quantity == null)\n return { label: 'Not tracked', tone: 'neutral', available: null };\n\n const available = p.quantity - (p.reserved ?? 0);\n\n if (available <= 0)\n return { label: 'Out of stock', tone: 'failed', available };\n\n if (p.lowStockThreshold != null && available <= p.lowStockThreshold)\n return { label: `Low · ${available}`, tone: 'pending', available };\n\n return {\n label: `In stock · ${compact(available)}`,\n tone: 'success',\n available,\n };\n}\n"],"mappings":"AAGO,SAAS,QAAQ,UAAkB,WAAW,GAAG;AACtD,SAAO,CAAC,MAAc;AACpB,QAAI;AACF,aAAO,IAAI,KAAK,aAAa,SAAS;AAAA,QACpC,OAAO;AAAA,QACP,iBAAiB;AAAA,QACjB,UAAU,YAAY;AAAA,QACtB,uBAAuB;AAAA,MACzB,CAAC,EAAE,OAAO,CAAC;AAAA,IACb,QAAQ;AACN,aAAO,GAAG,QAAQ,IAAI,KAAK,MAAM,CAAC,EAAE,eAAe,CAAC;AAAA,IACtD;AAAA,EACF;AACF;AAKO,MAAM,UAAU,CAAC,MACtB,IAAI,KAAK,aAAa,SAAS;AAAA,EAC7B,UAAU;AAAA,EACV,uBAAuB;AACzB,CAAC,EAAE,OAAO,CAAC;AAEN,MAAM,YAAY,CAAC,QACxB,IAAI,KAAK,eAAe,MAAM,EAAE,OAAO,SAAS,KAAK,UAAU,CAAC,EAAE;AAAA,EAChE,IAAI,KAAK,GAAG;AACd;AAGK,MAAM,WAAW,CAAC,MAAc;AACrC,QAAM,IAAI,EAAE,QAAQ,UAAU,GAAG,EAAE,KAAK;AACxC,SAAO,IAAI,EAAE,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,IAAI;AAC/C;AAKA,MAAM,UAAoC;AAAA,EACxC,WAAW;AAAA,EACX,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,uBAAuB;AAAA,EACvB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,oBAAoB;AACtB;AAEO,MAAM,SAAS,CAAC,WACrB,QAAQ,QAAQ,YAAY,CAAC,KAAK;AAS7B,SAAS,QAAQ,GAA8B;AACpD,MAAI,CAAC,EAAE,kBAAkB,EAAE,YAAY;AACrC,WAAO,EAAE,OAAO,eAAe,MAAM,WAAW,WAAW,KAAK;AAElE,QAAM,YAAY,EAAE,YAAY,EAAE,YAAY;AAE9C,MAAI,aAAa;AACf,WAAO,EAAE,OAAO,gBAAgB,MAAM,UAAU,UAAU;AAE5D,MAAI,EAAE,qBAAqB,QAAQ,aAAa,EAAE;AAChD,WAAO,EAAE,OAAO,YAAS,SAAS,IAAI,MAAM,WAAW,UAAU;AAEnE,SAAO;AAAA,IACL,OAAO,iBAAc,QAAQ,SAAS,CAAC;AAAA,IACvC,MAAM;AAAA,IACN;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/admin/tenants/%5Bid%5D/commerce/format.ts"],"sourcesContent":["import type { TenantProduct } from '@withpotter/lib/admin-api';\n\n/** Amounts in the merchant's own currency, whole units for headlines. */\nexport function moneyIn(currency: string, decimals = 0) {\n return (n: number) => {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n maximumFractionDigits: decimals,\n }).format(n);\n } catch {\n return `${currency} ${Math.round(n).toLocaleString()}`;\n }\n };\n}\n\nexport type Money = (n: number) => string;\n\n/** 1.2k / 3.4m, for figures in tight tiles. */\nexport const compact = (n: number) =>\n new Intl.NumberFormat('en-US', {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(n);\n\nexport const shortDate = (iso: string) =>\n new Intl.DateTimeFormat('en', { month: 'short', day: 'numeric' }).format(\n new Date(iso),\n );\n\n/** Sentence-case a machine word: \"checked_in\" → \"Checked in\". */\nexport const humanize = (s: string) => {\n const t = s.replace(/[_-]+/g, ' ').trim();\n return t ? t[0].toUpperCase() + t.slice(1) : '–';\n};\n\nexport type PillTone =\n 'success' | 'pending' | 'failed' | 'processing' | 'neutral';\n\nconst TONE_OF: Record<string, PillTone> = {\n completed: 'success',\n paid: 'success',\n success: 'success',\n settled: 'success',\n fulfilled: 'success',\n delivered: 'success',\n collected: 'success',\n pending: 'pending',\n unpaid: 'pending',\n awaiting_confirmation: 'pending',\n authorized: 'pending',\n unfulfilled: 'pending',\n partial: 'pending',\n confirmed: 'processing',\n processing: 'processing',\n checked_in: 'processing',\n ready: 'processing',\n failed: 'failed',\n reversed: 'failed',\n expired: 'failed',\n cancelled: 'neutral',\n refunded: 'neutral',\n partially_refunded: 'neutral',\n};\n\nexport const toneOf = (status: string): PillTone =>\n TONE_OF[status?.toLowerCase()] ?? 'neutral';\n\nexport type StockState = {\n label: string;\n tone: PillTone;\n available: number | null;\n};\n\n/** What a shelf looks like for one item, from the counts the API sends. */\nexport function stockOf(p: TenantProduct): StockState {\n if (!p.trackInventory || p.quantity == null)\n return { label: 'Not tracked', tone: 'neutral', available: null };\n\n const available = p.quantity - (p.reserved ?? 0);\n\n if (available <= 0)\n return { label: 'Out of stock', tone: 'failed', available };\n\n if (p.lowStockThreshold != null && available <= p.lowStockThreshold)\n return { label: `Low · ${available}`, tone: 'pending', available };\n\n return {\n label: `In stock · ${compact(available)}`,\n tone: 'success',\n available,\n };\n}\n"],"mappings":"AAGO,SAAS,QAAQ,UAAkB,WAAW,GAAG;AACtD,SAAO,CAAC,MAAc;AACpB,QAAI;AACF,aAAO,IAAI,KAAK,aAAa,SAAS;AAAA,QACpC,OAAO;AAAA,QACP,UAAU,YAAY;AAAA,QACtB,uBAAuB;AAAA,MACzB,CAAC,EAAE,OAAO,CAAC;AAAA,IACb,QAAQ;AACN,aAAO,GAAG,QAAQ,IAAI,KAAK,MAAM,CAAC,EAAE,eAAe,CAAC;AAAA,IACtD;AAAA,EACF;AACF;AAKO,MAAM,UAAU,CAAC,MACtB,IAAI,KAAK,aAAa,SAAS;AAAA,EAC7B,UAAU;AAAA,EACV,uBAAuB;AACzB,CAAC,EAAE,OAAO,CAAC;AAEN,MAAM,YAAY,CAAC,QACxB,IAAI,KAAK,eAAe,MAAM,EAAE,OAAO,SAAS,KAAK,UAAU,CAAC,EAAE;AAAA,EAChE,IAAI,KAAK,GAAG;AACd;AAGK,MAAM,WAAW,CAAC,MAAc;AACrC,QAAM,IAAI,EAAE,QAAQ,UAAU,GAAG,EAAE,KAAK;AACxC,SAAO,IAAI,EAAE,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,IAAI;AAC/C;AAKA,MAAM,UAAoC;AAAA,EACxC,WAAW;AAAA,EACX,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,uBAAuB;AAAA,EACvB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,oBAAoB;AACtB;AAEO,MAAM,SAAS,CAAC,WACrB,QAAQ,QAAQ,YAAY,CAAC,KAAK;AAS7B,SAAS,QAAQ,GAA8B;AACpD,MAAI,CAAC,EAAE,kBAAkB,EAAE,YAAY;AACrC,WAAO,EAAE,OAAO,eAAe,MAAM,WAAW,WAAW,KAAK;AAElE,QAAM,YAAY,EAAE,YAAY,EAAE,YAAY;AAE9C,MAAI,aAAa;AACf,WAAO,EAAE,OAAO,gBAAgB,MAAM,UAAU,UAAU;AAE5D,MAAI,EAAE,qBAAqB,QAAQ,aAAa,EAAE;AAChD,WAAO,EAAE,OAAO,YAAS,SAAS,IAAI,MAAM,WAAW,UAAU;AAEnE,SAAO;AAAA,IACL,OAAO,iBAAc,QAAQ,SAAS,CAAC;AAAA,IACvC,MAAM;AAAA,IACN;AAAA,EACF;AACF;","names":[]}
@@ -39,7 +39,7 @@ function RecentOrders({
39
39
  /* @__PURE__ */ jsx(Th, { children: "Customer" }),
40
40
  /* @__PURE__ */ jsx(Th, { align: "right", children: "Total" }),
41
41
  /* @__PURE__ */ jsx(Th, { children: "Payment" }),
42
- /* @__PURE__ */ jsx(Th, { children: "Fulfilment" }),
42
+ /* @__PURE__ */ jsx(Th, { children: "Status" }),
43
43
  /* @__PURE__ */ jsx(Th, { align: "right", children: "Placed" })
44
44
  ] }),
45
45
  children: loading ? Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx("tr", { "aria-hidden": true, children: /* @__PURE__ */ jsx("td", { colSpan: 6, children: /* @__PURE__ */ jsx(Skeleton, { height: 20 }) }) }, i)) : orders.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: 6, className: styles.emptyCell, children: "No orders yet. They show here as soon as a customer checks out." }) }) : orders.map((o) => /* @__PURE__ */ jsxs(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/admin/tenants/%5Bid%5D/commerce/recent-orders.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport type {\n DashboardStats,\n TenantActivityOrder,\n Transaction,\n} from '@withpotter/lib/admin-api';\nimport { TableRow, TableShell, Th } from '@withpotter/ui-kit';\nimport { Panel, Skeleton } from '../../../_ui';\nimport { moneyIn, shortDate } from './format';\nimport { OrderDrawer } from './order-drawer';\nimport { OrderPipeline } from './order-pipeline';\nimport { StatusPill } from './status-pill';\nimport styles from './orders.module.css';\n\n/** The order pipeline over the latest orders; a row opens the order. */\nexport function RecentOrders({\n orders,\n stats,\n transactions,\n loading,\n statsLoading,\n currency,\n}: {\n orders: TenantActivityOrder[];\n stats: DashboardStats['orderStats'] | undefined;\n transactions: Transaction[];\n loading: boolean;\n statsLoading: boolean;\n currency: string;\n}) {\n const [open, setOpen] = useState<TenantActivityOrder | null>(null);\n\n return (\n <>\n <Panel\n title=\"Orders\"\n count={stats?.total}\n caption={stats ? `${stats.today.toLocaleString()} today` : undefined}\n height=\"calc(var(--adm-panel-h) + 120px)\"\n flush\n >\n <OrderPipeline stats={stats} loading={statsLoading} />\n <TableShell\n bare\n minWidth={640}\n density=\"compact\"\n head={\n <tr>\n <Th>Order</Th>\n <Th>Customer</Th>\n <Th align=\"right\">Total</Th>\n <Th>Payment</Th>\n <Th>Fulfilment</Th>\n <Th align=\"right\">Placed</Th>\n </tr>\n }\n >\n {loading ? (\n Array.from({ length: 5 }, (_, i) => (\n <tr key={i} aria-hidden>\n <td colSpan={6}>\n <Skeleton height={20} />\n </td>\n </tr>\n ))\n ) : orders.length === 0 ? (\n <tr>\n <td colSpan={6} className={styles.emptyCell}>\n No orders yet. They show here as soon as a customer checks out.\n </td>\n </tr>\n ) : (\n orders.map((o) => (\n <TableRow\n key={o.id}\n active={open?.id === o.id}\n onClick={() => setOpen(o)}\n >\n <td className={styles.mono} title={o.orderNumber}>\n {/* The row opens on click; this is its keyboard way in. */}\n <button\n type=\"button\"\n className={styles.orderLink}\n onClick={(e) => {\n e.stopPropagation();\n setOpen(o);\n }}\n >\n {o.orderNumber}\n </button>\n </td>\n <td>\n <span\n className={styles.truncate}\n title={o.customerName || o.customerEmail}\n >\n {o.customerName || o.customerEmail}\n </span>\n </td>\n <td className={styles.num}>\n {moneyIn(o.currency || currency, 2)(o.total)}\n </td>\n <td>\n <StatusPill status={o.paymentStatus} />\n </td>\n <td>\n <StatusPill status={o.status} />\n </td>\n <td className={styles.num}>{shortDate(o.createdAt)}</td>\n </TableRow>\n ))\n )}\n </TableShell>\n </Panel>\n <OrderDrawer\n order={open}\n transactions={transactions}\n currency={currency}\n onClose={() => setOpen(null)}\n />\n </>\n );\n}\n"],"mappings":";AAmCI,mBAQI,KAMI,YAdR;AAjCJ,SAAS,gBAAgB;AAMzB,SAAS,UAAU,YAAY,UAAU;AACzC,SAAS,OAAO,gBAAgB;AAChC,SAAS,SAAS,iBAAiB;AACnC,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,OAAO,YAAY;AAGZ,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAqC,IAAI;AAEjE,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO,OAAO;AAAA,QACd,SAAS,QAAQ,GAAG,MAAM,MAAM,eAAe,CAAC,WAAW;AAAA,QAC3D,QAAO;AAAA,QACP,OAAK;AAAA,QAEL;AAAA,8BAAC,iBAAc,OAAc,SAAS,cAAc;AAAA,UACpD;AAAA,YAAC;AAAA;AAAA,cACC,MAAI;AAAA,cACJ,UAAU;AAAA,cACV,SAAQ;AAAA,cACR,MACE,qBAAC,QACC;AAAA,oCAAC,MAAG,mBAAK;AAAA,gBACT,oBAAC,MAAG,sBAAQ;AAAA,gBACZ,oBAAC,MAAG,OAAM,SAAQ,mBAAK;AAAA,gBACvB,oBAAC,MAAG,qBAAO;AAAA,gBACX,oBAAC,MAAG,wBAAU;AAAA,gBACd,oBAAC,MAAG,OAAM,SAAQ,oBAAM;AAAA,iBAC1B;AAAA,cAGD,oBACC,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,MAC5B,oBAAC,QAAW,eAAW,MACrB,8BAAC,QAAG,SAAS,GACX,8BAAC,YAAS,QAAQ,IAAI,GACxB,KAHO,CAIT,CACD,IACC,OAAO,WAAW,IACpB,oBAAC,QACC,8BAAC,QAAG,SAAS,GAAG,WAAW,OAAO,WAAW,6EAE7C,GACF,IAEA,OAAO,IAAI,CAAC,MACV;AAAA,gBAAC;AAAA;AAAA,kBAEC,QAAQ,MAAM,OAAO,EAAE;AAAA,kBACvB,SAAS,MAAM,QAAQ,CAAC;AAAA,kBAExB;AAAA,wCAAC,QAAG,WAAW,OAAO,MAAM,OAAO,EAAE,aAEnC;AAAA,sBAAC;AAAA;AAAA,wBACC,MAAK;AAAA,wBACL,WAAW,OAAO;AAAA,wBAClB,SAAS,CAAC,MAAM;AACd,4BAAE,gBAAgB;AAClB,kCAAQ,CAAC;AAAA,wBACX;AAAA,wBAEC,YAAE;AAAA;AAAA,oBACL,GACF;AAAA,oBACA,oBAAC,QACC;AAAA,sBAAC;AAAA;AAAA,wBACC,WAAW,OAAO;AAAA,wBAClB,OAAO,EAAE,gBAAgB,EAAE;AAAA,wBAE1B,YAAE,gBAAgB,EAAE;AAAA;AAAA,oBACvB,GACF;AAAA,oBACA,oBAAC,QAAG,WAAW,OAAO,KACnB,kBAAQ,EAAE,YAAY,UAAU,CAAC,EAAE,EAAE,KAAK,GAC7C;AAAA,oBACA,oBAAC,QACC,8BAAC,cAAW,QAAQ,EAAE,eAAe,GACvC;AAAA,oBACA,oBAAC,QACC,8BAAC,cAAW,QAAQ,EAAE,QAAQ,GAChC;AAAA,oBACA,oBAAC,QAAG,WAAW,OAAO,KAAM,oBAAU,EAAE,SAAS,GAAE;AAAA;AAAA;AAAA,gBAlC9C,EAAE;AAAA,cAmCT,CACD;AAAA;AAAA,UAEL;AAAA;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA,SAAS,MAAM,QAAQ,IAAI;AAAA;AAAA,IAC7B;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/admin/tenants/%5Bid%5D/commerce/recent-orders.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport type {\n DashboardStats,\n TenantActivityOrder,\n Transaction,\n} from '@withpotter/lib/admin-api';\nimport { TableRow, TableShell, Th } from '@withpotter/ui-kit';\nimport { Panel, Skeleton } from '../../../_ui';\nimport { moneyIn, shortDate } from './format';\nimport { OrderDrawer } from './order-drawer';\nimport { OrderPipeline } from './order-pipeline';\nimport { StatusPill } from './status-pill';\nimport styles from './orders.module.css';\n\n/** The order pipeline over the latest orders; a row opens the order. */\nexport function RecentOrders({\n orders,\n stats,\n transactions,\n loading,\n statsLoading,\n currency,\n}: {\n orders: TenantActivityOrder[];\n stats: DashboardStats['orderStats'] | undefined;\n transactions: Transaction[];\n loading: boolean;\n statsLoading: boolean;\n currency: string;\n}) {\n const [open, setOpen] = useState<TenantActivityOrder | null>(null);\n\n return (\n <>\n <Panel\n title=\"Orders\"\n count={stats?.total}\n caption={stats ? `${stats.today.toLocaleString()} today` : undefined}\n height=\"calc(var(--adm-panel-h) + 120px)\"\n flush\n >\n <OrderPipeline stats={stats} loading={statsLoading} />\n <TableShell\n bare\n minWidth={640}\n density=\"compact\"\n head={\n <tr>\n <Th>Order</Th>\n <Th>Customer</Th>\n <Th align=\"right\">Total</Th>\n <Th>Payment</Th>\n <Th>Status</Th>\n <Th align=\"right\">Placed</Th>\n </tr>\n }\n >\n {loading ? (\n Array.from({ length: 5 }, (_, i) => (\n <tr key={i} aria-hidden>\n <td colSpan={6}>\n <Skeleton height={20} />\n </td>\n </tr>\n ))\n ) : orders.length === 0 ? (\n <tr>\n <td colSpan={6} className={styles.emptyCell}>\n No orders yet. They show here as soon as a customer checks out.\n </td>\n </tr>\n ) : (\n orders.map((o) => (\n <TableRow\n key={o.id}\n active={open?.id === o.id}\n onClick={() => setOpen(o)}\n >\n <td className={styles.mono} title={o.orderNumber}>\n {/* The row opens on click; this is its keyboard way in. */}\n <button\n type=\"button\"\n className={styles.orderLink}\n onClick={(e) => {\n e.stopPropagation();\n setOpen(o);\n }}\n >\n {o.orderNumber}\n </button>\n </td>\n <td>\n <span\n className={styles.truncate}\n title={o.customerName || o.customerEmail}\n >\n {o.customerName || o.customerEmail}\n </span>\n </td>\n <td className={styles.num}>\n {moneyIn(o.currency || currency, 2)(o.total)}\n </td>\n <td>\n <StatusPill status={o.paymentStatus} />\n </td>\n <td>\n <StatusPill status={o.status} />\n </td>\n <td className={styles.num}>{shortDate(o.createdAt)}</td>\n </TableRow>\n ))\n )}\n </TableShell>\n </Panel>\n <OrderDrawer\n order={open}\n transactions={transactions}\n currency={currency}\n onClose={() => setOpen(null)}\n />\n </>\n );\n}\n"],"mappings":";AAmCI,mBAQI,KAMI,YAdR;AAjCJ,SAAS,gBAAgB;AAMzB,SAAS,UAAU,YAAY,UAAU;AACzC,SAAS,OAAO,gBAAgB;AAChC,SAAS,SAAS,iBAAiB;AACnC,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,OAAO,YAAY;AAGZ,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAqC,IAAI;AAEjE,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO,OAAO;AAAA,QACd,SAAS,QAAQ,GAAG,MAAM,MAAM,eAAe,CAAC,WAAW;AAAA,QAC3D,QAAO;AAAA,QACP,OAAK;AAAA,QAEL;AAAA,8BAAC,iBAAc,OAAc,SAAS,cAAc;AAAA,UACpD;AAAA,YAAC;AAAA;AAAA,cACC,MAAI;AAAA,cACJ,UAAU;AAAA,cACV,SAAQ;AAAA,cACR,MACE,qBAAC,QACC;AAAA,oCAAC,MAAG,mBAAK;AAAA,gBACT,oBAAC,MAAG,sBAAQ;AAAA,gBACZ,oBAAC,MAAG,OAAM,SAAQ,mBAAK;AAAA,gBACvB,oBAAC,MAAG,qBAAO;AAAA,gBACX,oBAAC,MAAG,oBAAM;AAAA,gBACV,oBAAC,MAAG,OAAM,SAAQ,oBAAM;AAAA,iBAC1B;AAAA,cAGD,oBACC,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,MAC5B,oBAAC,QAAW,eAAW,MACrB,8BAAC,QAAG,SAAS,GACX,8BAAC,YAAS,QAAQ,IAAI,GACxB,KAHO,CAIT,CACD,IACC,OAAO,WAAW,IACpB,oBAAC,QACC,8BAAC,QAAG,SAAS,GAAG,WAAW,OAAO,WAAW,6EAE7C,GACF,IAEA,OAAO,IAAI,CAAC,MACV;AAAA,gBAAC;AAAA;AAAA,kBAEC,QAAQ,MAAM,OAAO,EAAE;AAAA,kBACvB,SAAS,MAAM,QAAQ,CAAC;AAAA,kBAExB;AAAA,wCAAC,QAAG,WAAW,OAAO,MAAM,OAAO,EAAE,aAEnC;AAAA,sBAAC;AAAA;AAAA,wBACC,MAAK;AAAA,wBACL,WAAW,OAAO;AAAA,wBAClB,SAAS,CAAC,MAAM;AACd,4BAAE,gBAAgB;AAClB,kCAAQ,CAAC;AAAA,wBACX;AAAA,wBAEC,YAAE;AAAA;AAAA,oBACL,GACF;AAAA,oBACA,oBAAC,QACC;AAAA,sBAAC;AAAA;AAAA,wBACC,WAAW,OAAO;AAAA,wBAClB,OAAO,EAAE,gBAAgB,EAAE;AAAA,wBAE1B,YAAE,gBAAgB,EAAE;AAAA;AAAA,oBACvB,GACF;AAAA,oBACA,oBAAC,QAAG,WAAW,OAAO,KACnB,kBAAQ,EAAE,YAAY,UAAU,CAAC,EAAE,EAAE,KAAK,GAC7C;AAAA,oBACA,oBAAC,QACC,8BAAC,cAAW,QAAQ,EAAE,eAAe,GACvC;AAAA,oBACA,oBAAC,QACC,8BAAC,cAAW,QAAQ,EAAE,QAAQ,GAChC;AAAA,oBACA,oBAAC,QAAG,WAAW,OAAO,KAAM,oBAAU,EAAE,SAAS,GAAE;AAAA;AAAA;AAAA,gBAlC9C,EAAE;AAAA,cAmCT,CACD;AAAA;AAAA,UAEL;AAAA;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA,SAAS,MAAM,QAAQ,IAAI;AAAA;AAAA,IAC7B;AAAA,KACF;AAEJ;","names":[]}
@@ -14,7 +14,6 @@ import { moduleOn } from "../../_shell/nav-modules";
14
14
  import { TenantOverview } from "./tenant-overview";
15
15
  import { TenantPeoplePanel } from "./tenant-people-panel";
16
16
  import { TenantWalletCard } from "./tenant-wallet-card";
17
- import { useTenantWallet } from "./use-tenant-wallet";
18
17
  import { LedgerCurrencyFilter, MerchantLedger } from "./merchant-ledger";
19
18
  import { TenantSupport } from "./tenant-support";
20
19
  import { TenantVerification } from "./verification/tenant-verification";
@@ -62,7 +61,6 @@ function moneyCur(n, currency) {
62
61
  try {
63
62
  return new Intl.NumberFormat("en-US", {
64
63
  style: "currency",
65
- currencyDisplay: "narrowSymbol",
66
64
  currency,
67
65
  maximumFractionDigits: 0
68
66
  }).format(n);
@@ -70,10 +68,6 @@ function moneyCur(n, currency) {
70
68
  return `${currency} ${n.toFixed(0)}`;
71
69
  }
72
70
  }
73
- function sharedCurrency(rows) {
74
- const codes = new Set(rows.map((r) => r.currency));
75
- return codes.size === 1 ? [...codes][0] || null : null;
76
- }
77
71
  function num(n) {
78
72
  return new Intl.NumberFormat("en-US").format(n ?? 0);
79
73
  }
@@ -159,11 +153,6 @@ function TenantDetailPage({
159
153
  startDate: range.startDate,
160
154
  endDate: range.endDate
161
155
  });
162
- const { wallet, walletNote } = useTenantWallet(
163
- id,
164
- walletLedger,
165
- data?.wallet
166
- );
167
156
  const queryClient = useQueryClient();
168
157
  const statusMutation = useMutation({
169
158
  mutationFn: (status) => platformAdminApi.setTenantStatus(id, status),
@@ -180,8 +169,7 @@ function TenantDetailPage({
180
169
  return /* @__PURE__ */ jsx("p", { style: { color: "var(--error)" }, children: "Failed to load tenant." });
181
170
  }
182
171
  if (isLoading || !data) return /* @__PURE__ */ jsx(AdmLoading, { label: "Loading tenant\u2026" });
183
- const view = { ...data, wallet };
184
- const currency = data.currency ?? "NGN";
172
+ const currency = data.currency ?? "USD";
185
173
  const currencyControl = /* @__PURE__ */ jsx(
186
174
  CurrencyFilter,
187
175
  {
@@ -189,7 +177,7 @@ function TenantDetailPage({
189
177
  onChange: setShown,
190
178
  currencies: currenciesIn(
191
179
  data.currencies,
192
- view.wallet?.balances.map((b) => b.currency),
180
+ data.wallet?.balances.map((b) => b.currency),
193
181
  data.recentOrders.map((o) => o.currency)
194
182
  )
195
183
  }
@@ -220,8 +208,7 @@ function TenantDetailPage({
220
208
  tab === "overview" && /* @__PURE__ */ jsx(
221
209
  TenantOverview,
222
210
  {
223
- data: view,
224
- walletNote,
211
+ data,
225
212
  periodLabel: periodPhrase(range),
226
213
  periodControl,
227
214
  recentOrders: /* @__PURE__ */ jsx(
@@ -278,14 +265,7 @@ function TenantDetailPage({
278
265
  ]
279
266
  }
280
267
  ),
281
- group === "wallet" && current !== "money" && /* @__PURE__ */ jsx(
282
- TenantWalletCard,
283
- {
284
- data: view,
285
- currency: shown,
286
- walletNote
287
- }
288
- ),
268
+ group === "wallet" && current !== "money" && /* @__PURE__ */ jsx(TenantWalletCard, { data, currency: shown }),
289
269
  current === "money" && /* @__PURE__ */ jsx(
290
270
  MerchantLedger,
291
271
  {
@@ -1570,17 +1550,15 @@ function InvoicesTab({ id }) {
1570
1550
  if (isError) return /* @__PURE__ */ jsx(EmptyPanel, { children: "Failed to load invoices." });
1571
1551
  const rows = data?.invoices ?? [];
1572
1552
  const s = data?.stats;
1573
- const invoiceCurrency = sharedCurrency(rows) ?? "NGN";
1574
- const invoiceMoney = (n) => moneyCur(n, invoiceCurrency);
1575
1553
  const statItems = [
1576
1554
  {
1577
1555
  label: "Revenue",
1578
- value: invoiceMoney(s?.totalRevenue ?? 0),
1556
+ value: moneyCur(s?.totalRevenue ?? 0, "USD"),
1579
1557
  hint: "Total amount collected from invoices that have been paid."
1580
1558
  },
1581
1559
  {
1582
1560
  label: "Outstanding",
1583
- value: invoiceMoney(s?.totalOutstanding ?? 0),
1561
+ value: moneyCur(s?.totalOutstanding ?? 0, "USD"),
1584
1562
  hint: "Amount still owed across sent and overdue invoices that have not been paid."
1585
1563
  },
1586
1564
  {
@@ -1776,7 +1754,7 @@ function DiscountsTab({ id }) {
1776
1754
  /* @__PURE__ */ jsx("tbody", { children: rows.map((d) => /* @__PURE__ */ jsxs("tr", { children: [
1777
1755
  /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: d.code }),
1778
1756
  /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: d.name }),
1779
- /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: d.discountType === "percentage" ? `${d.value}%` : moneyCur(d.value, "NGN") }),
1757
+ /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: d.discountType === "percentage" ? `${d.value}%` : moneyCur(d.value, "USD") }),
1780
1758
  /* @__PURE__ */ jsxs("td", { style: tableStyles.cellMuted, children: [
1781
1759
  num(d.usageCount),
1782
1760
  d.usageLimit ? ` / ${num(d.usageLimit)}` : ""
@@ -1801,7 +1779,7 @@ function SettlementsTab({ id, range }) {
1801
1779
  if (isError) return /* @__PURE__ */ jsx(EmptyPanel, { children: "Failed to load settlements." });
1802
1780
  if (isLoading || !data) return /* @__PURE__ */ jsx(AdmLoading, { label: "Loading settlements\u2026" });
1803
1781
  const sum = data.summary;
1804
- const cur = sum.currency || "NGN";
1782
+ const cur = sum.currency || "USD";
1805
1783
  const banks = data.bankAccounts ?? [];
1806
1784
  const rows = data.settlements ?? [];
1807
1785
  const statItems = [
@@ -1891,7 +1869,7 @@ function SubscriptionsTab({ id }) {
1891
1869
  if (isLoading || !data) return /* @__PURE__ */ jsx(AdmLoading, { label: "Loading subscriptions\u2026" });
1892
1870
  const stats = data.stats;
1893
1871
  const rows = data.subscriptions ?? [];
1894
- const mrrCurrency = rows[0]?.currency || "NGN";
1872
+ const mrrCurrency = rows[0]?.currency || "USD";
1895
1873
  const statItems = [
1896
1874
  {
1897
1875
  label: "Active",
@@ -2240,7 +2218,6 @@ function ActivityTable({
2240
2218
  /* @__PURE__ */ jsx("th", { style: tableStyles.th, children: "Customer" }),
2241
2219
  /* @__PURE__ */ jsx("th", { style: tableStyles.th, children: "Total" }),
2242
2220
  /* @__PURE__ */ jsx("th", { style: tableStyles.th, children: "Payment" }),
2243
- /* @__PURE__ */ jsx("th", { style: tableStyles.th, children: "Paid by" }),
2244
2221
  /* @__PURE__ */ jsx("th", { style: tableStyles.th, children: "Status" }),
2245
2222
  /* @__PURE__ */ jsx("th", { style: tableStyles.th, children: "Date" })
2246
2223
  ] }) }),
@@ -2249,10 +2226,7 @@ function ActivityTable({
2249
2226
  "#",
2250
2227
  o.orderNumber
2251
2228
  ] }),
2252
- /* @__PURE__ */ jsxs("td", { style: tableStyles.cell, children: [
2253
- o.customerName ?? o.customerEmail,
2254
- o.customerName ? /* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: "var(--text-tertiary)" }, children: [o.customerEmail, o.customerPhone].filter(Boolean).join(" \xB7 ") }) : null
2255
- ] }),
2229
+ /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: o.customerName ?? o.customerEmail }),
2256
2230
  /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: moneyCur(o.total, o.currency) }),
2257
2231
  /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: /* @__PURE__ */ jsx(
2258
2232
  Badge,
@@ -2261,7 +2235,6 @@ function ActivityTable({
2261
2235
  children: o.paymentStatus
2262
2236
  }
2263
2237
  ) }),
2264
- /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: o.paymentMethod ?? /* @__PURE__ */ jsx("span", { style: { color: "var(--text-tertiary)" }, children: "Not recorded" }) }),
2265
2238
  /* @__PURE__ */ jsx("td", { style: tableStyles.cell, children: /* @__PURE__ */ jsx(
2266
2239
  Badge,
2267
2240
  {