@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
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/admin/_pos/tenant-operators.tsx"],"sourcesContent":["'use client';\n\nimport { TableRow, Th } from '@withpotter/ui-kit';\nimport { ListCard } from '../_ui/list-card';\nimport list from '../_ui/list-card.module.css';\nimport { LoadError } from './pos-parts';\nimport { isForbidden, posErrorText } from './pos-rules';\nimport { atTime } from './pos-words';\nimport { useTenantRoster } from './use-pos';\nimport pos from './pos.module.css';\n\nconst sentence = (s: string) =>\n s ? s.charAt(0).toUpperCase() + s.slice(1).replace(/_/g, ' ') : s;\n\n/** \"168 h\", \"30 min\", \"1 h 30 min\". */\nexport function shiftLimit(minutes: number): string {\n if (!Number.isFinite(minutes) || minutes <= 0) return '–';\n\n const h = Math.floor(minutes / 60);\n const m = minutes % 60;\n\n if (!h) return `${m} min`;\n\n return m ? `${h} h ${m} min` : `${h} h`;\n}\n\n/** The business's whole till roster: who can sign in, as what, and for how long a shift may run. */\nexport function TenantOperators({ tenantId }: { tenantId: string }) {\n const { data, isLoading, isError, error, refetch } =\n useTenantRoster(tenantId);\n\n if (isError && !data)\n return (\n <LoadError\n error={error}\n what=\"this business's operators\"\n onRetry={() => void refetch()}\n />\n );\n\n return (\n <ListCard\n title=\"Operators\"\n count={data?.length}\n columns={4}\n minWidth={640}\n isLoading={isLoading}\n errorTitle={\n isForbidden(error) ? '' : posErrorText(error, 'Operators did not load.')\n }\n isEmpty={data?.length === 0}\n emptyTitle=\"Nobody can sign in at this business's terminals yet.\"\n head={\n <tr>\n <Th>Operator</Th>\n <Th>Role</Th>\n <Th>Shift limit</Th>\n <Th>Updated</Th>\n </tr>\n }\n >\n {data?.map((o) => (\n <TableRow key={o.id}>\n <td>\n <span className={pos.cellStack}>\n <span className={pos.clip}>{o.name}</span>\n <span className={pos.subtle}>\n {o.active\n ? o.signIn !== o.name\n ? `Signs in as ${o.signIn}`\n : ''\n : 'Removed'}\n </span>\n </span>\n </td>\n <td className={`${list.nowrap} ${list.muted}`}>{sentence(o.role)}</td>\n <td className={`${list.nowrap} ${list.muted}`}>\n {shiftLimit(o.shiftLimitMinutes)}\n </td>\n <td className={`${list.nowrap} ${list.muted}`}>\n {atTime(o.updatedAt)}\n </td>\n </TableRow>\n ))}\n </ListCard>\n );\n}\n"],"mappings":";AAiCM,cAoBE,YApBF;AA/BN,SAAS,UAAU,UAAU;AAC7B,SAAS,gBAAgB;AACzB,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAC1B,SAAS,aAAa,oBAAoB;AAC1C,SAAS,cAAc;AACvB,SAAS,uBAAuB;AAChC,OAAO,SAAS;AAEhB,MAAM,WAAW,CAAC,MAChB,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,EAAE,QAAQ,MAAM,GAAG,IAAI;AAG3D,SAAS,WAAW,SAAyB;AAClD,MAAI,CAAC,OAAO,SAAS,OAAO,KAAK,WAAW,EAAG,QAAO;AAEtD,QAAM,IAAI,KAAK,MAAM,UAAU,EAAE;AACjC,QAAM,IAAI,UAAU;AAEpB,MAAI,CAAC,EAAG,QAAO,GAAG,CAAC;AAEnB,SAAO,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC;AACrC;AAGO,SAAS,gBAAgB,EAAE,SAAS,GAAyB;AAClE,QAAM,EAAE,MAAM,WAAW,SAAS,OAAO,QAAQ,IAC/C,gBAAgB,QAAQ;AAE1B,MAAI,WAAW,CAAC;AACd,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,SAAS,MAAM,KAAK,QAAQ;AAAA;AAAA,IAC9B;AAGJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,OAAO,MAAM;AAAA,MACb,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,MACA,YACE,YAAY,KAAK,IAAI,KAAK,aAAa,OAAO,yBAAyB;AAAA,MAEzE,SAAS,MAAM,WAAW;AAAA,MAC1B,YAAW;AAAA,MACX,MACE,qBAAC,QACC;AAAA,4BAAC,MAAG,sBAAQ;AAAA,QACZ,oBAAC,MAAG,kBAAI;AAAA,QACR,oBAAC,MAAG,yBAAW;AAAA,QACf,oBAAC,MAAG,qBAAO;AAAA,SACb;AAAA,MAGD,gBAAM,IAAI,CAAC,MACV,qBAAC,YACC;AAAA,4BAAC,QACC,+BAAC,UAAK,WAAW,IAAI,WACnB;AAAA,8BAAC,UAAK,WAAW,IAAI,MAAO,YAAE,MAAK;AAAA,UACnC,oBAAC,UAAK,WAAW,IAAI,QAClB,YAAE,SACC,EAAE,WAAW,EAAE,OACb,eAAe,EAAE,MAAM,KACvB,KACF,WACN;AAAA,WACF,GACF;AAAA,QACA,oBAAC,QAAG,WAAW,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,IAAK,mBAAS,EAAE,IAAI,GAAE;AAAA,QACjE,oBAAC,QAAG,WAAW,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,IACxC,qBAAW,EAAE,iBAAiB,GACjC;AAAA,QACA,oBAAC,QAAG,WAAW,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,IACxC,iBAAO,EAAE,SAAS,GACrB;AAAA,WAnBa,EAAE,EAoBjB,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -1,77 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useMemo, useState } from "react";
4
- import { Badge, TableRow, Th } from "@withpotter/ui-kit";
5
- import { oliveOutlets } from "@withpotter/lib/admin-pos-olive";
6
- import { FilterSearch, Filters } from "../_ui";
7
- import { ListCard } from "../_ui/list-card";
8
- import list from "../_ui/list-card.module.css";
9
- import { OLIVE_NOTE, OliveProblem } from "./olive-state";
10
- import { atTime } from "./pos-words";
11
- import { useOliveOutlets } from "./use-pos";
12
- function TenantOutlets({ tenantId }) {
13
- const { data, isLoading, isError, error, refetch } = useOliveOutlets(tenantId);
14
- const [search, setSearch] = useState("");
15
- const outlets = useMemo(() => oliveOutlets(data), [data]);
16
- const shown = useMemo(() => {
17
- const q = search.trim().toLowerCase();
18
- if (!q) return outlets;
19
- return outlets.filter(
20
- (o) => [o.name, o.address, o.contact].some((v) => v?.toLowerCase().includes(q))
21
- );
22
- }, [outlets, search]);
23
- if (isError)
24
- return /* @__PURE__ */ jsx(
25
- OliveProblem,
26
- {
27
- error,
28
- what: "outlets",
29
- onRetry: () => void refetch()
30
- }
31
- );
32
- return /* @__PURE__ */ jsx(
33
- ListCard,
34
- {
35
- title: "Outlets",
36
- count: outlets.length,
37
- columns: 6,
38
- minWidth: 860,
39
- isLoading,
40
- errorTitle: "",
41
- isEmpty: shown.length === 0,
42
- emptyTitle: search ? "No outlets match." : "No outlets yet.",
43
- controls: /* @__PURE__ */ jsxs(Filters, { label: "Filter outlets", children: [
44
- /* @__PURE__ */ jsx(
45
- FilterSearch,
46
- {
47
- value: search,
48
- onChange: setSearch,
49
- placeholder: "Search outlets\u2026",
50
- label: "Search outlets"
51
- }
52
- ),
53
- /* @__PURE__ */ jsx("span", { className: "adm-caption", children: OLIVE_NOTE })
54
- ] }),
55
- head: /* @__PURE__ */ jsxs("tr", { children: [
56
- /* @__PURE__ */ jsx(Th, { children: "Outlet" }),
57
- /* @__PURE__ */ jsx(Th, { children: "Address" }),
58
- /* @__PURE__ */ jsx(Th, { children: "Contact" }),
59
- /* @__PURE__ */ jsx(Th, { children: "Terminals" }),
60
- /* @__PURE__ */ jsx(Th, { children: "Status" }),
61
- /* @__PURE__ */ jsx(Th, { children: "Created" })
62
- ] }),
63
- children: shown.map((o) => /* @__PURE__ */ jsxs(TableRow, { children: [
64
- /* @__PURE__ */ jsx("td", { children: o.name }),
65
- /* @__PURE__ */ jsx("td", { className: list.muted, children: o.address ?? "\u2013" }),
66
- /* @__PURE__ */ jsx("td", { className: list.muted, children: o.contact ?? "\u2013" }),
67
- /* @__PURE__ */ jsx("td", { className: list.nowrap, children: o.terminalCount ?? "\u2013" }),
68
- /* @__PURE__ */ jsx("td", { className: list.nowrap, children: /* @__PURE__ */ jsx(Badge, { variant: o.active ? "success" : "secondary", children: o.active ? "Active" : "Inactive" }) }),
69
- /* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: o.createdAt ? atTime(o.createdAt) : "\u2013" })
70
- ] }, o.id))
71
- }
72
- );
73
- }
74
- export {
75
- TenantOutlets
76
- };
77
- //# sourceMappingURL=tenant-outlets.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/admin/_pos/tenant-outlets.tsx"],"sourcesContent":["'use client';\n\nimport { useMemo, useState } from 'react';\nimport { Badge, TableRow, Th } from '@withpotter/ui-kit';\nimport { oliveOutlets } from '@withpotter/lib/admin-pos-olive';\nimport { FilterSearch, Filters } from '../_ui';\nimport { ListCard } from '../_ui/list-card';\nimport list from '../_ui/list-card.module.css';\nimport { OLIVE_NOTE, OliveProblem } from './olive-state';\nimport { atTime } from './pos-words';\nimport { useOliveOutlets } from './use-pos';\n\n/** The business's outlets as Olive keeps them: where it sells, who to call, how many terminals. */\nexport function TenantOutlets({ tenantId }: { tenantId: string }) {\n const { data, isLoading, isError, error, refetch } =\n useOliveOutlets(tenantId);\n const [search, setSearch] = useState('');\n const outlets = useMemo(() => oliveOutlets(data), [data]);\n const shown = useMemo(() => {\n const q = search.trim().toLowerCase();\n\n if (!q) return outlets;\n\n return outlets.filter((o) =>\n [o.name, o.address, o.contact].some((v) => v?.toLowerCase().includes(q)),\n );\n }, [outlets, search]);\n\n if (isError)\n return (\n <OliveProblem\n error={error}\n what=\"outlets\"\n onRetry={() => void refetch()}\n />\n );\n\n return (\n <ListCard\n title=\"Outlets\"\n count={outlets.length}\n columns={6}\n minWidth={860}\n isLoading={isLoading}\n errorTitle=\"\"\n isEmpty={shown.length === 0}\n emptyTitle={search ? 'No outlets match.' : 'No outlets yet.'}\n controls={\n <Filters label=\"Filter outlets\">\n <FilterSearch\n value={search}\n onChange={setSearch}\n placeholder=\"Search outlets…\"\n label=\"Search outlets\"\n />\n <span className=\"adm-caption\">{OLIVE_NOTE}</span>\n </Filters>\n }\n head={\n <tr>\n <Th>Outlet</Th>\n <Th>Address</Th>\n <Th>Contact</Th>\n <Th>Terminals</Th>\n <Th>Status</Th>\n <Th>Created</Th>\n </tr>\n }\n >\n {shown.map((o) => (\n <TableRow key={o.id}>\n <td>{o.name}</td>\n <td className={list.muted}>{o.address ?? '–'}</td>\n <td className={list.muted}>{o.contact ?? '–'}</td>\n <td className={list.nowrap}>{o.terminalCount ?? '–'}</td>\n <td className={list.nowrap}>\n <Badge variant={o.active ? 'success' : 'secondary'}>\n {o.active ? 'Active' : 'Inactive'}\n </Badge>\n </td>\n <td className={`${list.nowrap} ${list.muted}`}>\n {o.createdAt ? atTime(o.createdAt) : '–'}\n </td>\n </TableRow>\n ))}\n </ListCard>\n );\n}\n"],"mappings":";AA8BM,cAkBE,YAlBF;AA5BN,SAAS,SAAS,gBAAgB;AAClC,SAAS,OAAO,UAAU,UAAU;AACpC,SAAS,oBAAoB;AAC7B,SAAS,cAAc,eAAe;AACtC,SAAS,gBAAgB;AACzB,OAAO,UAAU;AACjB,SAAS,YAAY,oBAAoB;AACzC,SAAS,cAAc;AACvB,SAAS,uBAAuB;AAGzB,SAAS,cAAc,EAAE,SAAS,GAAyB;AAChE,QAAM,EAAE,MAAM,WAAW,SAAS,OAAO,QAAQ,IAC/C,gBAAgB,QAAQ;AAC1B,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,EAAE;AACvC,QAAM,UAAU,QAAQ,MAAM,aAAa,IAAI,GAAG,CAAC,IAAI,CAAC;AACxD,QAAM,QAAQ,QAAQ,MAAM;AAC1B,UAAM,IAAI,OAAO,KAAK,EAAE,YAAY;AAEpC,QAAI,CAAC,EAAG,QAAO;AAEf,WAAO,QAAQ;AAAA,MAAO,CAAC,MACrB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,YAAY,EAAE,SAAS,CAAC,CAAC;AAAA,IACzE;AAAA,EACF,GAAG,CAAC,SAAS,MAAM,CAAC;AAEpB,MAAI;AACF,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,SAAS,MAAM,KAAK,QAAQ;AAAA;AAAA,IAC9B;AAGJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,OAAO,QAAQ;AAAA,MACf,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,MACA,YAAW;AAAA,MACX,SAAS,MAAM,WAAW;AAAA,MAC1B,YAAY,SAAS,sBAAsB;AAAA,MAC3C,UACE,qBAAC,WAAQ,OAAM,kBACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,UAAU;AAAA,YACV,aAAY;AAAA,YACZ,OAAM;AAAA;AAAA,QACR;AAAA,QACA,oBAAC,UAAK,WAAU,eAAe,sBAAW;AAAA,SAC5C;AAAA,MAEF,MACE,qBAAC,QACC;AAAA,4BAAC,MAAG,oBAAM;AAAA,QACV,oBAAC,MAAG,qBAAO;AAAA,QACX,oBAAC,MAAG,qBAAO;AAAA,QACX,oBAAC,MAAG,uBAAS;AAAA,QACb,oBAAC,MAAG,oBAAM;AAAA,QACV,oBAAC,MAAG,qBAAO;AAAA,SACb;AAAA,MAGD,gBAAM,IAAI,CAAC,MACV,qBAAC,YACC;AAAA,4BAAC,QAAI,YAAE,MAAK;AAAA,QACZ,oBAAC,QAAG,WAAW,KAAK,OAAQ,YAAE,WAAW,UAAI;AAAA,QAC7C,oBAAC,QAAG,WAAW,KAAK,OAAQ,YAAE,WAAW,UAAI;AAAA,QAC7C,oBAAC,QAAG,WAAW,KAAK,QAAS,YAAE,iBAAiB,UAAI;AAAA,QACpD,oBAAC,QAAG,WAAW,KAAK,QAClB,8BAAC,SAAM,SAAS,EAAE,SAAS,YAAY,aACpC,YAAE,SAAS,WAAW,YACzB,GACF;AAAA,QACA,oBAAC,QAAG,WAAW,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,IACxC,YAAE,YAAY,OAAO,EAAE,SAAS,IAAI,UACvC;AAAA,WAZa,EAAE,EAajB,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -1,82 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { StatCard } from "../_ui";
4
- import { amountLines } from "./pos-money";
5
- import { isLongOpen } from "./pos-rules";
6
- import { inPeriod, onlineTone } from "./pos-words";
7
- import styles from "./pos.module.css";
8
- function TenantPosFigures({
9
- data,
10
- phrase,
11
- currency = ""
12
- }) {
13
- const live = data.terminals.filter((t) => t.status !== "revoked");
14
- const online = live.filter((t) => t.online).length;
15
- const offlineOverDay = live.filter((t) => {
16
- const tone = onlineTone(t);
17
- return tone === "stale" || tone === "never";
18
- }).length;
19
- const suspended = live.filter((t) => t.status === "suspended").length;
20
- const longOpen = data.openShifts.filter(isLongOpen).length;
21
- const money = amountLines(data.takings.amounts, currency);
22
- return /* @__PURE__ */ jsxs(
23
- "section",
24
- {
25
- className: styles.figures,
26
- "aria-label": "This business's POS at a glance",
27
- children: [
28
- /* @__PURE__ */ jsx(
29
- StatCard,
30
- {
31
- compact: true,
32
- label: "Terminals",
33
- value: String(live.length),
34
- sub: `${data.terminals.length - live.length} revoked`
35
- }
36
- ),
37
- /* @__PURE__ */ jsx(
38
- StatCard,
39
- {
40
- compact: true,
41
- label: "Online now",
42
- value: String(online),
43
- sub: `Of ${live.length}`
44
- }
45
- ),
46
- /* @__PURE__ */ jsx(
47
- StatCard,
48
- {
49
- compact: true,
50
- label: "Offline over a day",
51
- value: String(offlineOverDay),
52
- alert: offlineOverDay > 0
53
- }
54
- ),
55
- /* @__PURE__ */ jsx(StatCard, { compact: true, label: "Suspended", value: String(suspended) }),
56
- /* @__PURE__ */ jsx(
57
- StatCard,
58
- {
59
- compact: true,
60
- label: "Open shifts",
61
- value: String(data.openShifts.length),
62
- sub: longOpen ? `${longOpen} open over 12 h` : void 0,
63
- alert: longOpen > 0
64
- }
65
- ),
66
- /* @__PURE__ */ jsx(
67
- StatCard,
68
- {
69
- compact: true,
70
- label: "Card payments",
71
- value: data.takings.count.toLocaleString("en-US"),
72
- sub: money.length ? `${money.join(" \xB7 ")}, ${phrase}` : `None ${inPeriod(phrase)}`
73
- }
74
- )
75
- ]
76
- }
77
- );
78
- }
79
- export {
80
- TenantPosFigures
81
- };
82
- //# sourceMappingURL=tenant-pos-figures.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/admin/_pos/tenant-pos-figures.tsx"],"sourcesContent":["'use client';\n\nimport type { TenantPos } from '@withpotter/lib/admin-pos-types';\nimport { StatCard } from '../_ui';\nimport { amountLines } from './pos-money';\nimport { isLongOpen } from './pos-rules';\nimport { inPeriod, onlineTone } from './pos-words';\nimport styles from './pos.module.css';\n\n/**\n * One business's POS at a glance, worked out from its own terminals and\n * shifts, so it matches what the merchant's POS page counts.\n */\nexport function TenantPosFigures({\n data,\n phrase,\n currency = '',\n}: {\n data: TenantPos;\n phrase: string;\n currency?: string;\n}) {\n const live = data.terminals.filter((t) => t.status !== 'revoked');\n const online = live.filter((t) => t.online).length;\n const offlineOverDay = live.filter((t) => {\n const tone = onlineTone(t);\n\n return tone === 'stale' || tone === 'never';\n }).length;\n const suspended = live.filter((t) => t.status === 'suspended').length;\n const longOpen = data.openShifts.filter(isLongOpen).length;\n const money = amountLines(data.takings.amounts, currency);\n\n return (\n <section\n className={styles.figures}\n aria-label=\"This business's POS at a glance\"\n >\n <StatCard\n compact\n label=\"Terminals\"\n value={String(live.length)}\n sub={`${data.terminals.length - live.length} revoked`}\n />\n <StatCard\n compact\n label=\"Online now\"\n value={String(online)}\n sub={`Of ${live.length}`}\n />\n <StatCard\n compact\n label=\"Offline over a day\"\n value={String(offlineOverDay)}\n alert={offlineOverDay > 0}\n />\n <StatCard compact label=\"Suspended\" value={String(suspended)} />\n <StatCard\n compact\n label=\"Open shifts\"\n value={String(data.openShifts.length)}\n sub={longOpen ? `${longOpen} open over 12 h` : undefined}\n alert={longOpen > 0}\n />\n <StatCard\n compact\n label=\"Card payments\"\n value={data.takings.count.toLocaleString('en-US')}\n sub={\n money.length\n ? `${money.join(' · ')}, ${phrase}`\n : `None ${inPeriod(phrase)}`\n }\n />\n </section>\n );\n}\n"],"mappings":";AAkCI,SAIE,KAJF;AA/BJ,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,UAAU,kBAAkB;AACrC,OAAO,YAAY;AAMZ,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,WAAW;AACb,GAIG;AACD,QAAM,OAAO,KAAK,UAAU,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAChE,QAAM,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE;AAC5C,QAAM,iBAAiB,KAAK,OAAO,CAAC,MAAM;AACxC,UAAM,OAAO,WAAW,CAAC;AAEzB,WAAO,SAAS,WAAW,SAAS;AAAA,EACtC,CAAC,EAAE;AACH,QAAM,YAAY,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW,EAAE;AAC/D,QAAM,WAAW,KAAK,WAAW,OAAO,UAAU,EAAE;AACpD,QAAM,QAAQ,YAAY,KAAK,QAAQ,SAAS,QAAQ;AAExD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,OAAO;AAAA,MAClB,cAAW;AAAA,MAEX;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAO;AAAA,YACP,OAAM;AAAA,YACN,OAAO,OAAO,KAAK,MAAM;AAAA,YACzB,KAAK,GAAG,KAAK,UAAU,SAAS,KAAK,MAAM;AAAA;AAAA,QAC7C;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAO;AAAA,YACP,OAAM;AAAA,YACN,OAAO,OAAO,MAAM;AAAA,YACpB,KAAK,MAAM,KAAK,MAAM;AAAA;AAAA,QACxB;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAO;AAAA,YACP,OAAM;AAAA,YACN,OAAO,OAAO,cAAc;AAAA,YAC5B,OAAO,iBAAiB;AAAA;AAAA,QAC1B;AAAA,QACA,oBAAC,YAAS,SAAO,MAAC,OAAM,aAAY,OAAO,OAAO,SAAS,GAAG;AAAA,QAC9D;AAAA,UAAC;AAAA;AAAA,YACC,SAAO;AAAA,YACP,OAAM;AAAA,YACN,OAAO,OAAO,KAAK,WAAW,MAAM;AAAA,YACpC,KAAK,WAAW,GAAG,QAAQ,oBAAoB;AAAA,YAC/C,OAAO,WAAW;AAAA;AAAA,QACpB;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAO;AAAA,YACP,OAAM;AAAA,YACN,OAAO,KAAK,QAAQ,MAAM,eAAe,OAAO;AAAA,YAChD,KACE,MAAM,SACF,GAAG,MAAM,KAAK,QAAK,CAAC,KAAK,MAAM,KAC/B,QAAQ,SAAS,MAAM,CAAC;AAAA;AAAA,QAEhC;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1,64 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { Badge, TableRow, Th } from "@withpotter/ui-kit";
4
- import { ListCard } from "../_ui/list-card";
5
- import list from "../_ui/list-card.module.css";
6
- import { LoadError } from "./pos-parts";
7
- import { isForbidden, posErrorText } from "./pos-rules";
8
- import { atTime, count } from "./pos-words";
9
- import { useTenantTillRequests } from "./use-pos";
10
- import pos from "./pos.module.css";
11
- const LABEL = {
12
- pending: "Pending",
13
- approved: "Approved",
14
- rejected: "Rejected",
15
- fulfilled: "Provisioned"
16
- };
17
- const TONE = {
18
- pending: "warning",
19
- approved: "success",
20
- rejected: "secondary",
21
- fulfilled: "success"
22
- };
23
- function TenantRequests({ tenantId }) {
24
- const { data, isLoading, isError, error, refetch } = useTenantTillRequests(tenantId);
25
- if (isError && !data)
26
- return /* @__PURE__ */ jsx(
27
- LoadError,
28
- {
29
- error,
30
- what: "this business's terminal requests",
31
- onRetry: () => void refetch()
32
- }
33
- );
34
- return /* @__PURE__ */ jsx(
35
- ListCard,
36
- {
37
- title: "Terminal requests",
38
- count: data?.length,
39
- columns: 3,
40
- minWidth: 560,
41
- isLoading,
42
- errorTitle: isForbidden(error) ? "" : posErrorText(error, "Requests did not load."),
43
- isEmpty: data?.length === 0,
44
- emptyTitle: "This business has not asked for any terminals.",
45
- head: /* @__PURE__ */ jsxs("tr", { children: [
46
- /* @__PURE__ */ jsx(Th, { children: "Request" }),
47
- /* @__PURE__ */ jsx(Th, { children: "Status" }),
48
- /* @__PURE__ */ jsx(Th, { children: "Requested" })
49
- ] }),
50
- children: data?.map((r) => /* @__PURE__ */ jsxs(TableRow, { children: [
51
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("span", { className: pos.cellStack, children: [
52
- /* @__PURE__ */ jsx("span", { className: pos.clip, children: `${count(r.quantity, "terminal")} requested` }),
53
- (r.decisionNote || r.note) && /* @__PURE__ */ jsx("span", { className: pos.subtle, children: r.decisionNote ?? r.note })
54
- ] }) }),
55
- /* @__PURE__ */ jsx("td", { className: list.nowrap, children: /* @__PURE__ */ jsx(Badge, { variant: TONE[r.status] ?? "secondary", children: LABEL[r.status] ?? r.status }) }),
56
- /* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: atTime(r.createdAt) })
57
- ] }, r.id))
58
- }
59
- );
60
- }
61
- export {
62
- TenantRequests
63
- };
64
- //# sourceMappingURL=tenant-requests.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/admin/_pos/tenant-requests.tsx"],"sourcesContent":["'use client';\n\nimport { Badge, TableRow, Th } from '@withpotter/ui-kit';\nimport type { TillRequestStatus } from '@withpotter/lib/admin-pos-types';\nimport { ListCard } from '../_ui/list-card';\nimport list from '../_ui/list-card.module.css';\nimport { LoadError } from './pos-parts';\nimport { isForbidden, posErrorText } from './pos-rules';\nimport { atTime, count } from './pos-words';\nimport { useTenantTillRequests } from './use-pos';\nimport pos from './pos.module.css';\n\nconst LABEL: Record<TillRequestStatus, string> = {\n pending: 'Pending',\n approved: 'Approved',\n rejected: 'Rejected',\n fulfilled: 'Provisioned',\n};\n\nconst TONE = {\n pending: 'warning',\n approved: 'success',\n rejected: 'secondary',\n fulfilled: 'success',\n} as const;\n\n/** The terminals the business has asked for, newest first, and where each request stands. */\nexport function TenantRequests({ tenantId }: { tenantId: string }) {\n const { data, isLoading, isError, error, refetch } =\n useTenantTillRequests(tenantId);\n\n if (isError && !data)\n return (\n <LoadError\n error={error}\n what=\"this business's terminal requests\"\n onRetry={() => void refetch()}\n />\n );\n\n return (\n <ListCard\n title=\"Terminal requests\"\n count={data?.length}\n columns={3}\n minWidth={560}\n isLoading={isLoading}\n errorTitle={\n isForbidden(error) ? '' : posErrorText(error, 'Requests did not load.')\n }\n isEmpty={data?.length === 0}\n emptyTitle=\"This business has not asked for any terminals.\"\n head={\n <tr>\n <Th>Request</Th>\n <Th>Status</Th>\n <Th>Requested</Th>\n </tr>\n }\n >\n {data?.map((r) => (\n <TableRow key={r.id}>\n <td>\n <span className={pos.cellStack}>\n <span className={pos.clip}>\n {`${count(r.quantity, 'terminal')} requested`}\n </span>\n {(r.decisionNote || r.note) && (\n <span className={pos.subtle}>{r.decisionNote ?? r.note}</span>\n )}\n </span>\n </td>\n <td className={list.nowrap}>\n <Badge variant={TONE[r.status] ?? 'secondary'}>\n {LABEL[r.status] ?? r.status}\n </Badge>\n </td>\n <td className={`${list.nowrap} ${list.muted}`}>\n {atTime(r.createdAt)}\n </td>\n </TableRow>\n ))}\n </ListCard>\n );\n}\n"],"mappings":";AAiCM,cAoBE,YApBF;AA/BN,SAAS,OAAO,UAAU,UAAU;AAEpC,SAAS,gBAAgB;AACzB,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAC1B,SAAS,aAAa,oBAAoB;AAC1C,SAAS,QAAQ,aAAa;AAC9B,SAAS,6BAA6B;AACtC,OAAO,SAAS;AAEhB,MAAM,QAA2C;AAAA,EAC/C,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AACb;AAEA,MAAM,OAAO;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AACb;AAGO,SAAS,eAAe,EAAE,SAAS,GAAyB;AACjE,QAAM,EAAE,MAAM,WAAW,SAAS,OAAO,QAAQ,IAC/C,sBAAsB,QAAQ;AAEhC,MAAI,WAAW,CAAC;AACd,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,SAAS,MAAM,KAAK,QAAQ;AAAA;AAAA,IAC9B;AAGJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,OAAO,MAAM;AAAA,MACb,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,MACA,YACE,YAAY,KAAK,IAAI,KAAK,aAAa,OAAO,wBAAwB;AAAA,MAExE,SAAS,MAAM,WAAW;AAAA,MAC1B,YAAW;AAAA,MACX,MACE,qBAAC,QACC;AAAA,4BAAC,MAAG,qBAAO;AAAA,QACX,oBAAC,MAAG,oBAAM;AAAA,QACV,oBAAC,MAAG,uBAAS;AAAA,SACf;AAAA,MAGD,gBAAM,IAAI,CAAC,MACV,qBAAC,YACC;AAAA,4BAAC,QACC,+BAAC,UAAK,WAAW,IAAI,WACnB;AAAA,8BAAC,UAAK,WAAW,IAAI,MAClB,aAAG,MAAM,EAAE,UAAU,UAAU,CAAC,cACnC;AAAA,WACE,EAAE,gBAAgB,EAAE,SACpB,oBAAC,UAAK,WAAW,IAAI,QAAS,YAAE,gBAAgB,EAAE,MAAK;AAAA,WAE3D,GACF;AAAA,QACA,oBAAC,QAAG,WAAW,KAAK,QAClB,8BAAC,SAAM,SAAS,KAAK,EAAE,MAAM,KAAK,aAC/B,gBAAM,EAAE,MAAM,KAAK,EAAE,QACxB,GACF;AAAA,QACA,oBAAC,QAAG,WAAW,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,IACxC,iBAAO,EAAE,SAAS,GACrB;AAAA,WAlBa,EAAE,EAmBjB,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -1,145 +0,0 @@
1
- "use client";
2
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { useMemo, useState } from "react";
4
- import { Badge, Button, TableRow, Th } from "@withpotter/ui-kit";
5
- import { oliveTransactions } from "@withpotter/lib/admin-pos-olive";
6
- import { formatMinor } from "@withpotter/lib/money-minor";
7
- import { FilterPress, Filters } from "../_ui";
8
- import { ListCard } from "../_ui/list-card";
9
- import list from "../_ui/list-card.module.css";
10
- import { OLIVE_NOTE, OliveProblem, naira } from "./olive-state";
11
- import { LoadError } from "./pos-parts";
12
- import { isForbidden, posErrorText } from "./pos-rules";
13
- import { atTime } from "./pos-words";
14
- import { useOliveAccountTransactions, useTenantPayments } from "./use-pos";
15
- import pos from "./pos.module.css";
16
- function TenantTransactions({ tenantId }) {
17
- const [source, setSource] = useState("card");
18
- const switcher = /* @__PURE__ */ jsxs(Filters, { label: "Transactions source", children: [
19
- /* @__PURE__ */ jsx(FilterPress, { on: source === "card", onToggle: () => setSource("card"), children: "Card payments" }),
20
- /* @__PURE__ */ jsx(
21
- FilterPress,
22
- {
23
- on: source === "account",
24
- onToggle: () => setSource("account"),
25
- children: "POS account"
26
- }
27
- )
28
- ] });
29
- return source === "card" ? /* @__PURE__ */ jsx(CardPayments, { tenantId, controls: switcher }) : /* @__PURE__ */ jsx(AccountLines, { tenantId, controls: switcher });
30
- }
31
- function CardPayments({
32
- tenantId,
33
- controls
34
- }) {
35
- const q = useTenantPayments(tenantId);
36
- const rows = useMemo(
37
- () => q.data?.pages.flatMap((p) => p.rows) ?? [],
38
- [q.data]
39
- );
40
- if (q.isError && !q.data)
41
- return /* @__PURE__ */ jsx(
42
- LoadError,
43
- {
44
- error: q.error,
45
- what: "this business's card payments",
46
- onRetry: () => void q.refetch()
47
- }
48
- );
49
- return /* @__PURE__ */ jsx(
50
- ListCard,
51
- {
52
- title: "Card payments",
53
- count: q.hasNextPage ? void 0 : rows.length,
54
- columns: 5,
55
- minWidth: 760,
56
- isLoading: q.isLoading,
57
- errorTitle: isForbidden(q.error) ? "" : posErrorText(q.error, "Payments did not load."),
58
- isEmpty: rows.length === 0,
59
- emptyTitle: "No card payments yet.",
60
- controls,
61
- head: /* @__PURE__ */ jsxs("tr", { children: [
62
- /* @__PURE__ */ jsx(Th, { children: "Terminal" }),
63
- /* @__PURE__ */ jsx(Th, { children: "Reference" }),
64
- /* @__PURE__ */ jsx(Th, { children: "Status" }),
65
- /* @__PURE__ */ jsx(Th, { children: "Amount" }),
66
- /* @__PURE__ */ jsx(Th, { children: "When" })
67
- ] }),
68
- footer: q.hasNextPage ? /* @__PURE__ */ jsx("div", { className: pos.stack, children: /* @__PURE__ */ jsx(
69
- Button,
70
- {
71
- size: "sm",
72
- variant: "secondary",
73
- disabled: q.isFetchingNextPage,
74
- onClick: () => void q.fetchNextPage(),
75
- children: q.isFetchingNextPage ? "Loading\u2026" : "Show more"
76
- }
77
- ) }) : void 0,
78
- children: rows.map((p) => /* @__PURE__ */ jsxs(TableRow, { children: [
79
- /* @__PURE__ */ jsx("td", { children: p.deviceLabel ?? "\u2013" }),
80
- /* @__PURE__ */ jsx("td", { className: list.muted, children: p.reference ?? "\u2013" }),
81
- /* @__PURE__ */ jsx("td", { className: list.nowrap, children: /* @__PURE__ */ jsx(Badge, { variant: p.status === "SUCCEEDED" ? "success" : "secondary", children: p.status.charAt(0) + p.status.slice(1).toLowerCase() }) }),
82
- /* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${pos.num}`, children: `${p.direction === "out" ? "-" : ""}${formatMinor(
83
- p.amountMinor,
84
- p.currency
85
- )}` }),
86
- /* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: atTime(p.at) })
87
- ] }, p.id))
88
- }
89
- );
90
- }
91
- function AccountLines({
92
- tenantId,
93
- controls
94
- }) {
95
- const q = useOliveAccountTransactions(tenantId);
96
- const rows = useMemo(() => oliveTransactions(q.data), [q.data]);
97
- if (q.isError)
98
- return /* @__PURE__ */ jsxs(Fragment, { children: [
99
- controls,
100
- /* @__PURE__ */ jsx(
101
- OliveProblem,
102
- {
103
- error: q.error,
104
- what: "account transactions",
105
- onRetry: () => void q.refetch()
106
- }
107
- )
108
- ] });
109
- return /* @__PURE__ */ jsx(
110
- ListCard,
111
- {
112
- title: "POS account",
113
- count: rows.length,
114
- columns: 4,
115
- minWidth: 680,
116
- isLoading: q.isLoading,
117
- errorTitle: "",
118
- isEmpty: rows.length === 0,
119
- emptyTitle: "No account transactions yet.",
120
- controls: /* @__PURE__ */ jsxs(Fragment, { children: [
121
- controls,
122
- /* @__PURE__ */ jsx("span", { className: "adm-caption", children: OLIVE_NOTE })
123
- ] }),
124
- head: /* @__PURE__ */ jsxs("tr", { children: [
125
- /* @__PURE__ */ jsx(Th, { children: "Transaction" }),
126
- /* @__PURE__ */ jsx(Th, { children: "Status" }),
127
- /* @__PURE__ */ jsx(Th, { children: "Amount" }),
128
- /* @__PURE__ */ jsx(Th, { children: "When" })
129
- ] }),
130
- children: rows.map((t) => /* @__PURE__ */ jsxs(TableRow, { children: [
131
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("span", { className: pos.cellStack, children: [
132
- /* @__PURE__ */ jsx("span", { className: pos.clip, children: t.summary }),
133
- t.reference && /* @__PURE__ */ jsx("span", { className: pos.subtle, children: t.reference })
134
- ] }) }),
135
- /* @__PURE__ */ jsx("td", { className: list.nowrap, children: t.status ?? "\u2013" }),
136
- /* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${pos.num}`, children: `${t.direction === "in" ? "+" : t.direction === "out" ? "-" : ""}${naira(t.amountMinor)}` }),
137
- /* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: t.at ? atTime(t.at) : "\u2013" })
138
- ] }, t.id))
139
- }
140
- );
141
- }
142
- export {
143
- TenantTransactions
144
- };
145
- //# sourceMappingURL=tenant-transactions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/admin/_pos/tenant-transactions.tsx"],"sourcesContent":["'use client';\n\nimport { useMemo, useState } from 'react';\nimport { Badge, Button, TableRow, Th } from '@withpotter/ui-kit';\nimport { oliveTransactions } from '@withpotter/lib/admin-pos-olive';\nimport { formatMinor } from '@withpotter/lib/money-minor';\nimport { FilterPress, Filters } from '../_ui';\nimport { ListCard } from '../_ui/list-card';\nimport list from '../_ui/list-card.module.css';\nimport { OLIVE_NOTE, OliveProblem, naira } from './olive-state';\nimport { LoadError } from './pos-parts';\nimport { isForbidden, posErrorText } from './pos-rules';\nimport { atTime } from './pos-words';\nimport { useOliveAccountTransactions, useTenantPayments } from './use-pos';\nimport pos from './pos.module.css';\n\ntype Source = 'card' | 'account';\n\n/**\n * What moved: the card payments its terminals took (Box's own record), or the lines on its POS account\n * (Olive's). One switch; the other source is not fetched until it is chosen.\n */\nexport function TenantTransactions({ tenantId }: { tenantId: string }) {\n const [source, setSource] = useState<Source>('card');\n\n const switcher = (\n <Filters label=\"Transactions source\">\n <FilterPress on={source === 'card'} onToggle={() => setSource('card')}>\n Card payments\n </FilterPress>\n <FilterPress\n on={source === 'account'}\n onToggle={() => setSource('account')}\n >\n POS account\n </FilterPress>\n </Filters>\n );\n\n return source === 'card' ? (\n <CardPayments tenantId={tenantId} controls={switcher} />\n ) : (\n <AccountLines tenantId={tenantId} controls={switcher} />\n );\n}\n\nfunction CardPayments({\n tenantId,\n controls,\n}: {\n tenantId: string;\n controls: React.ReactNode;\n}) {\n const q = useTenantPayments(tenantId);\n const rows = useMemo(\n () => q.data?.pages.flatMap((p) => p.rows) ?? [],\n [q.data],\n );\n\n if (q.isError && !q.data)\n return (\n <LoadError\n error={q.error}\n what=\"this business's card payments\"\n onRetry={() => void q.refetch()}\n />\n );\n\n return (\n <ListCard\n title=\"Card payments\"\n count={q.hasNextPage ? undefined : rows.length}\n columns={5}\n minWidth={760}\n isLoading={q.isLoading}\n errorTitle={\n isForbidden(q.error)\n ? ''\n : posErrorText(q.error, 'Payments did not load.')\n }\n isEmpty={rows.length === 0}\n emptyTitle=\"No card payments yet.\"\n controls={controls}\n head={\n <tr>\n <Th>Terminal</Th>\n <Th>Reference</Th>\n <Th>Status</Th>\n <Th>Amount</Th>\n <Th>When</Th>\n </tr>\n }\n footer={\n q.hasNextPage ? (\n <div className={pos.stack}>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n disabled={q.isFetchingNextPage}\n onClick={() => void q.fetchNextPage()}\n >\n {q.isFetchingNextPage ? 'Loading…' : 'Show more'}\n </Button>\n </div>\n ) : undefined\n }\n >\n {rows.map((p) => (\n <TableRow key={p.id}>\n <td>{p.deviceLabel ?? '–'}</td>\n <td className={list.muted}>{p.reference ?? '–'}</td>\n <td className={list.nowrap}>\n <Badge variant={p.status === 'SUCCEEDED' ? 'success' : 'secondary'}>\n {p.status.charAt(0) + p.status.slice(1).toLowerCase()}\n </Badge>\n </td>\n <td className={`${list.nowrap} ${pos.num}`}>\n {`${p.direction === 'out' ? '-' : ''}${formatMinor(\n p.amountMinor,\n p.currency,\n )}`}\n </td>\n <td className={`${list.nowrap} ${list.muted}`}>{atTime(p.at)}</td>\n </TableRow>\n ))}\n </ListCard>\n );\n}\n\nfunction AccountLines({\n tenantId,\n controls,\n}: {\n tenantId: string;\n controls: React.ReactNode;\n}) {\n const q = useOliveAccountTransactions(tenantId);\n const rows = useMemo(() => oliveTransactions(q.data), [q.data]);\n\n if (q.isError)\n return (\n <>\n {controls}\n <OliveProblem\n error={q.error}\n what=\"account transactions\"\n onRetry={() => void q.refetch()}\n />\n </>\n );\n\n return (\n <ListCard\n title=\"POS account\"\n count={rows.length}\n columns={4}\n minWidth={680}\n isLoading={q.isLoading}\n errorTitle=\"\"\n isEmpty={rows.length === 0}\n emptyTitle=\"No account transactions yet.\"\n controls={\n <>\n {controls}\n <span className=\"adm-caption\">{OLIVE_NOTE}</span>\n </>\n }\n head={\n <tr>\n <Th>Transaction</Th>\n <Th>Status</Th>\n <Th>Amount</Th>\n <Th>When</Th>\n </tr>\n }\n >\n {rows.map((t) => (\n <TableRow key={t.id}>\n <td>\n <span className={pos.cellStack}>\n <span className={pos.clip}>{t.summary}</span>\n {t.reference && <span className={pos.subtle}>{t.reference}</span>}\n </span>\n </td>\n <td className={list.nowrap}>{t.status ?? '–'}</td>\n <td className={`${list.nowrap} ${pos.num}`}>\n {`${\n t.direction === 'in' ? '+' : t.direction === 'out' ? '-' : ''\n }${naira(t.amountMinor)}`}\n </td>\n <td className={`${list.nowrap} ${list.muted}`}>\n {t.at ? atTime(t.at) : '–'}\n </td>\n </TableRow>\n ))}\n </ListCard>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,14 +0,0 @@
1
- const FOLDABLE_GROUPS = /* @__PURE__ */ new Set([
2
- "Workspaces",
3
- "Operations",
4
- "Inbox",
5
- "Platform"
6
- ]);
7
- const foldsGroup = (label, rows, collapsed) => label !== null && FOLDABLE_GROUPS.has(label) && rows > 1 && !collapsed;
8
- const isGroupOpen = (choices, label, containsActive) => choices[label] ?? containsActive;
9
- export {
10
- FOLDABLE_GROUPS,
11
- foldsGroup,
12
- isGroupOpen
13
- };
14
- //# sourceMappingURL=nav-fold.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/admin/_shell/nav-fold.ts"],"sourcesContent":["/**\n * Which sidebar groups fold, and which one is open. Pure, so it is tested\n * without a browser. The merchant rail's hubs follow the same rules.\n */\n\n/**\n * The groups the admin opened or closed by hand, by label. A group not listed\n * has no choice yet, and each group is chosen on its own.\n */\nexport type GroupChoices = Record<string, boolean>;\n\n/** The groups that fold; every other group keeps its plain heading. */\nexport const FOLDABLE_GROUPS: ReadonlySet<string> = new Set([\n 'Workspaces',\n 'Operations',\n 'Inbox',\n 'Platform',\n]);\n\n/**\n * A group folds only when it is one of those, has more than one row to hide,\n * and the rail is wide: the icon-only rail has no headings to press.\n */\nexport const foldsGroup = (\n label: string | null,\n rows: number,\n collapsed: boolean,\n): label is string =>\n label !== null && FOLDABLE_GROUPS.has(label) && rows > 1 && !collapsed;\n\n/**\n * A group the admin chose is as they left it, whatever the others are doing.\n * With no choice yet it is open when it owns the current page, so the page\n * you are on always has a lit row.\n */\nexport const isGroupOpen = (\n choices: GroupChoices,\n label: string,\n containsActive: boolean,\n) => choices[label] ?? containsActive;\n"],"mappings":"AAYO,MAAM,kBAAuC,oBAAI,IAAI;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAMM,MAAM,aAAa,CACxB,OACA,MACA,cAEA,UAAU,QAAQ,gBAAgB,IAAI,KAAK,KAAK,OAAO,KAAK,CAAC;AAOxD,MAAM,cAAc,CACzB,SACA,OACA,mBACG,QAAQ,KAAK,KAAK;","names":[]}
@@ -1,78 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { ChevronDown } from "lucide-react";
4
- import { useRouter } from "next/navigation";
5
- import { AnimatePresence, motion, useReducedMotion } from "motion/react";
6
- import { eases } from "@withpotter/lib/motion";
7
- import { isActive } from "./nav-filter";
8
- import { foldsGroup, isGroupOpen } from "./nav-fold";
9
- import { NavRow } from "./nav-row";
10
- import styles from "./sidebar.module.css";
11
- function NavGroupView({
12
- group,
13
- pathname,
14
- collapsed,
15
- canSupport,
16
- choices,
17
- onToggle,
18
- badges
19
- }) {
20
- const reduced = useReducedMotion();
21
- const router = useRouter();
22
- const { label, items } = group;
23
- const containsActive = items.some((item) => isActive(item, pathname));
24
- const rows = items.map((item) => /* @__PURE__ */ jsx(
25
- NavRow,
26
- {
27
- item,
28
- active: isActive(item, pathname),
29
- collapsed,
30
- canSupport,
31
- badges
32
- },
33
- item.href
34
- ));
35
- if (!foldsGroup(label, items.length, collapsed))
36
- return /* @__PURE__ */ jsxs("div", { className: styles.group, children: [
37
- label && /* @__PURE__ */ jsx("div", { className: styles.groupLabel, children: label }),
38
- rows
39
- ] });
40
- const open = isGroupOpen(choices, label, containsActive);
41
- const warm = () => items.forEach((item) => router.prefetch(item.href));
42
- return /* @__PURE__ */ jsxs("div", { className: `${styles.group} ${styles.groupFold}`, children: [
43
- /* @__PURE__ */ jsxs(
44
- "button",
45
- {
46
- type: "button",
47
- className: `${styles.groupLabel} ${styles.groupToggle}`,
48
- "aria-expanded": open,
49
- onPointerEnter: warm,
50
- onFocus: warm,
51
- onClick: () => onToggle(label, !open),
52
- children: [
53
- /* @__PURE__ */ jsx("span", { children: label }),
54
- /* @__PURE__ */ jsx(ChevronDown, { size: 14, className: styles.groupChevron, "aria-hidden": true })
55
- ]
56
- }
57
- ),
58
- /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: open && /* @__PURE__ */ jsx(
59
- motion.div,
60
- {
61
- className: styles.groupRows,
62
- initial: { height: 0, opacity: 0 },
63
- animate: { height: "auto", opacity: 1 },
64
- exit: { height: 0, opacity: 0 },
65
- transition: reduced ? { duration: 0 } : {
66
- height: { duration: 0.24, ease: eases.settle },
67
- opacity: { duration: 0.16, ease: eases.out }
68
- },
69
- style: { overflow: "hidden" },
70
- children: rows
71
- }
72
- ) })
73
- ] });
74
- }
75
- export {
76
- NavGroupView
77
- };
78
- //# sourceMappingURL=nav-group.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/admin/_shell/nav-group.tsx"],"sourcesContent":["'use client';\n\nimport type { ComponentType } from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { useRouter } from 'next/navigation';\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react';\nimport { eases } from '@withpotter/lib/motion';\nimport type { NavGroup } from './nav-config';\nimport { isActive } from './nav-filter';\nimport { foldsGroup, isGroupOpen, type GroupChoices } from './nav-fold';\nimport { NavRow } from './nav-row';\nimport styles from './sidebar.module.css';\n\n/**\n * One sidebar group. With a heading and more than one row, the heading is a\n * button that opens and closes the rows, on its own: no other group moves.\n * The group holding the current page starts open, and the icon-only rail shows\n * every row.\n */\nexport function NavGroupView({\n group,\n pathname,\n collapsed,\n canSupport,\n choices,\n onToggle,\n badges,\n}: {\n group: NavGroup;\n pathname: string;\n collapsed: boolean;\n canSupport: boolean;\n choices: GroupChoices;\n onToggle: (label: string, next: boolean) => void;\n /** A mark beside a row, by the row's href (a count of what needs a decision). */\n badges?: Record<string, ComponentType>;\n}) {\n const reduced = useReducedMotion();\n const router = useRouter();\n const { label, items } = group;\n const containsActive = items.some((item) => isActive(item, pathname));\n\n const rows = items.map((item) => (\n <NavRow\n key={item.href}\n item={item}\n active={isActive(item, pathname)}\n collapsed={collapsed}\n canSupport={canSupport}\n badges={badges}\n />\n ));\n\n if (!foldsGroup(label, items.length, collapsed))\n return (\n <div className={styles.group}>\n {label && <div className={styles.groupLabel}>{label}</div>}\n {rows}\n </div>\n );\n\n const open = isGroupOpen(choices, label, containsActive);\n\n // A heading is only ever pressed on the way to one of its pages, and the\n // pointer or focus arriving is the earliest sign of it, so warm them now.\n const warm = () => items.forEach((item) => router.prefetch(item.href));\n\n return (\n <div className={`${styles.group} ${styles.groupFold}`}>\n <button\n type=\"button\"\n className={`${styles.groupLabel} ${styles.groupToggle}`}\n aria-expanded={open}\n onPointerEnter={warm}\n onFocus={warm}\n onClick={() => onToggle(label, !open)}\n >\n <span>{label}</span>\n <ChevronDown size={14} className={styles.groupChevron} aria-hidden />\n </button>\n {/* The rows grow and collapse rather than blink, as the merchant rail's\n hubs do: height so the groups below move with them, opacity finishing\n early on the way in. Clipped, or the rows spill past the closing box. */}\n <AnimatePresence initial={false}>\n {open && (\n <motion.div\n className={styles.groupRows}\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={\n reduced\n ? { duration: 0 }\n : {\n height: { duration: 0.24, ease: eases.settle },\n opacity: { duration: 0.16, ease: eases.out },\n }\n }\n style={{ overflow: 'hidden' }}\n >\n {rows}\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n"],"mappings":";AA2CI,cAYE,YAZF;AAxCJ,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB,QAAQ,wBAAwB;AAC1D,SAAS,aAAa;AAEtB,SAAS,gBAAgB;AACzB,SAAS,YAAY,mBAAsC;AAC3D,SAAS,cAAc;AACvB,OAAO,YAAY;AAQZ,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASG;AACD,QAAM,UAAU,iBAAiB;AACjC,QAAM,SAAS,UAAU;AACzB,QAAM,EAAE,OAAO,MAAM,IAAI;AACzB,QAAM,iBAAiB,MAAM,KAAK,CAAC,SAAS,SAAS,MAAM,QAAQ,CAAC;AAEpE,QAAM,OAAO,MAAM,IAAI,CAAC,SACtB;AAAA,IAAC;AAAA;AAAA,MAEC;AAAA,MACA,QAAQ,SAAS,MAAM,QAAQ;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IALK,KAAK;AAAA,EAMZ,CACD;AAED,MAAI,CAAC,WAAW,OAAO,MAAM,QAAQ,SAAS;AAC5C,WACE,qBAAC,SAAI,WAAW,OAAO,OACpB;AAAA,eAAS,oBAAC,SAAI,WAAW,OAAO,YAAa,iBAAM;AAAA,MACnD;AAAA,OACH;AAGJ,QAAM,OAAO,YAAY,SAAS,OAAO,cAAc;AAIvD,QAAM,OAAO,MAAM,MAAM,QAAQ,CAAC,SAAS,OAAO,SAAS,KAAK,IAAI,CAAC;AAErE,SACE,qBAAC,SAAI,WAAW,GAAG,OAAO,KAAK,IAAI,OAAO,SAAS,IACjD;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAW,GAAG,OAAO,UAAU,IAAI,OAAO,WAAW;AAAA,QACrD,iBAAe;AAAA,QACf,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,SAAS,MAAM,SAAS,OAAO,CAAC,IAAI;AAAA,QAEpC;AAAA,8BAAC,UAAM,iBAAM;AAAA,UACb,oBAAC,eAAY,MAAM,IAAI,WAAW,OAAO,cAAc,eAAW,MAAC;AAAA;AAAA;AAAA,IACrE;AAAA,IAIA,oBAAC,mBAAgB,SAAS,OACvB,kBACC;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,WAAW,OAAO;AAAA,QAClB,SAAS,EAAE,QAAQ,GAAG,SAAS,EAAE;AAAA,QACjC,SAAS,EAAE,QAAQ,QAAQ,SAAS,EAAE;AAAA,QACtC,MAAM,EAAE,QAAQ,GAAG,SAAS,EAAE;AAAA,QAC9B,YACE,UACI,EAAE,UAAU,EAAE,IACd;AAAA,UACE,QAAQ,EAAE,UAAU,MAAM,MAAM,MAAM,OAAO;AAAA,UAC7C,SAAS,EAAE,UAAU,MAAM,MAAM,MAAM,IAAI;AAAA,QAC7C;AAAA,QAEN,OAAO,EAAE,UAAU,SAAS;AAAA,QAE3B;AAAA;AAAA,IACH,GAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -1,64 +0,0 @@
1
- "use client";
2
- import { useState, useSyncExternalStore } from "react";
3
- const STORAGE_KEY = "pb_admin_nav_groups";
4
- let cache = {};
5
- let cachedRaw = null;
6
- const listeners = /* @__PURE__ */ new Set();
7
- function read() {
8
- if (typeof window === "undefined") return cache;
9
- let raw = null;
10
- try {
11
- raw = localStorage.getItem(STORAGE_KEY);
12
- } catch {
13
- return cache;
14
- }
15
- if (raw !== cachedRaw) {
16
- cachedRaw = raw;
17
- try {
18
- const parsed = raw ? JSON.parse(raw) : {};
19
- cache = parsed && typeof parsed === "object" ? parsed : {};
20
- } catch {
21
- cache = {};
22
- }
23
- }
24
- return cache;
25
- }
26
- const empty = {};
27
- const emptySnapshot = () => empty;
28
- function subscribe(listener) {
29
- listeners.add(listener);
30
- return () => listeners.delete(listener);
31
- }
32
- function remember(label, open) {
33
- const next = { ...read(), [label]: open };
34
- try {
35
- localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
36
- } catch {
37
- }
38
- cachedRaw = JSON.stringify(next);
39
- cache = next;
40
- listeners.forEach((listener) => listener());
41
- }
42
- function useOpenGroups(pathname, activeGroup) {
43
- const remembered = useSyncExternalStore(subscribe, read, emptySnapshot);
44
- const [arrived, setArrived] = useState({});
45
- const [choiceRoute, setChoiceRoute] = useState(pathname);
46
- if (choiceRoute !== pathname) {
47
- setChoiceRoute(pathname);
48
- if (activeGroup && arrived[activeGroup] !== true)
49
- setArrived({ ...arrived, [activeGroup]: true });
50
- }
51
- const setGroupOpen = (label, next) => {
52
- if (label in arrived) {
53
- const rest = { ...arrived };
54
- delete rest[label];
55
- setArrived(rest);
56
- }
57
- remember(label, next);
58
- };
59
- return { choices: { ...remembered, ...arrived }, setGroupOpen };
60
- }
61
- export {
62
- useOpenGroups
63
- };
64
- //# sourceMappingURL=use-open-groups.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/admin/_shell/use-open-groups.ts"],"sourcesContent":["'use client';\n\nimport { useState, useSyncExternalStore } from 'react';\nimport type { GroupChoices } from './nav-fold';\n\nconst STORAGE_KEY = 'pb_admin_nav_groups';\n\n/**\n * The groups the admin has opened or closed by hand, remembered across visits.\n * An external store, not state read in an effect: localStorage does not exist\n * while the server renders, and the snapshot must stay referentially stable\n * between renders, so it is cached by the raw string.\n */\nlet cache: GroupChoices = {};\nlet cachedRaw: string | null = null;\nconst listeners = new Set<() => void>();\n\nfunction read(): GroupChoices {\n if (typeof window === 'undefined') return cache;\n\n let raw: string | null = null;\n\n try {\n raw = localStorage.getItem(STORAGE_KEY);\n } catch {\n return cache;\n }\n\n if (raw !== cachedRaw) {\n cachedRaw = raw;\n\n try {\n const parsed: unknown = raw ? JSON.parse(raw) : {};\n\n cache =\n parsed && typeof parsed === 'object' ? (parsed as GroupChoices) : {};\n } catch {\n cache = {};\n }\n }\n\n return cache;\n}\n\nconst empty: GroupChoices = {};\nconst emptySnapshot = () => empty;\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n}\n\nfunction remember(label: string, open: boolean) {\n const next = { ...read(), [label]: open };\n\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(next));\n } catch {\n /* private mode: the choice just won't survive the visit */\n }\n\n cachedRaw = JSON.stringify(next);\n cache = next;\n listeners.forEach((listener) => listener());\n}\n\n/**\n * Which sidebar groups are open by choice, each on its own: pressing one never\n * moves another. `activeGroup` is the group holding the current page, or null.\n *\n * Arriving on a page opens its own group and holds it open, so a group that was\n * open only for the last page does not shut by itself, and one closed by hand\n * does not hide the row you landed on. That arrival is kept for the visit only;\n * what is remembered is what was pressed. Pressing a group again takes over.\n * Adjusted during render, not in an effect, so no stale frame paints.\n */\nexport function useOpenGroups(pathname: string, activeGroup: string | null) {\n const remembered = useSyncExternalStore(subscribe, read, emptySnapshot);\n const [arrived, setArrived] = useState<GroupChoices>({});\n const [choiceRoute, setChoiceRoute] = useState(pathname);\n\n if (choiceRoute !== pathname) {\n setChoiceRoute(pathname);\n\n if (activeGroup && arrived[activeGroup] !== true)\n setArrived({ ...arrived, [activeGroup]: true });\n }\n\n const setGroupOpen = (label: string, next: boolean) => {\n if (label in arrived) {\n const rest = { ...arrived };\n\n delete rest[label];\n setArrived(rest);\n }\n\n remember(label, next);\n };\n\n return { choices: { ...remembered, ...arrived }, setGroupOpen };\n}\n"],"mappings":";AAEA,SAAS,UAAU,4BAA4B;AAG/C,MAAM,cAAc;AAQpB,IAAI,QAAsB,CAAC;AAC3B,IAAI,YAA2B;AAC/B,MAAM,YAAY,oBAAI,IAAgB;AAEtC,SAAS,OAAqB;AAC5B,MAAI,OAAO,WAAW,YAAa,QAAO;AAE1C,MAAI,MAAqB;AAEzB,MAAI;AACF,UAAM,aAAa,QAAQ,WAAW;AAAA,EACxC,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,WAAW;AACrB,gBAAY;AAEZ,QAAI;AACF,YAAM,SAAkB,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAEjD,cACE,UAAU,OAAO,WAAW,WAAY,SAA0B,CAAC;AAAA,IACvE,QAAQ;AACN,cAAQ,CAAC;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;AAEA,MAAM,QAAsB,CAAC;AAC7B,MAAM,gBAAgB,MAAM;AAE5B,SAAS,UAAU,UAAsB;AACvC,YAAU,IAAI,QAAQ;AAEtB,SAAO,MAAM,UAAU,OAAO,QAAQ;AACxC;AAEA,SAAS,SAAS,OAAe,MAAe;AAC9C,QAAM,OAAO,EAAE,GAAG,KAAK,GAAG,CAAC,KAAK,GAAG,KAAK;AAExC,MAAI;AACF,iBAAa,QAAQ,aAAa,KAAK,UAAU,IAAI,CAAC;AAAA,EACxD,QAAQ;AAAA,EAER;AAEA,cAAY,KAAK,UAAU,IAAI;AAC/B,UAAQ;AACR,YAAU,QAAQ,CAAC,aAAa,SAAS,CAAC;AAC5C;AAYO,SAAS,cAAc,UAAkB,aAA4B;AAC1E,QAAM,aAAa,qBAAqB,WAAW,MAAM,aAAa;AACtE,QAAM,CAAC,SAAS,UAAU,IAAI,SAAuB,CAAC,CAAC;AACvD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,QAAQ;AAEvD,MAAI,gBAAgB,UAAU;AAC5B,mBAAe,QAAQ;AAEvB,QAAI,eAAe,QAAQ,WAAW,MAAM;AAC1C,iBAAW,EAAE,GAAG,SAAS,CAAC,WAAW,GAAG,KAAK,CAAC;AAAA,EAClD;AAEA,QAAM,eAAe,CAAC,OAAe,SAAkB;AACrD,QAAI,SAAS,SAAS;AACpB,YAAM,OAAO,EAAE,GAAG,QAAQ;AAE1B,aAAO,KAAK,KAAK;AACjB,iBAAW,IAAI;AAAA,IACjB;AAEA,aAAS,OAAO,IAAI;AAAA,EACtB;AAEA,SAAO,EAAE,SAAS,EAAE,GAAG,YAAY,GAAG,QAAQ,GAAG,aAAa;AAChE;","names":[]}