@withpotter/pages-admin 0.13.0-next.124 → 0.13.0-next.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/_money/cash-postings.js +3 -20
- package/dist/admin/_money/cash-postings.js.map +1 -1
- package/dist/admin/_money/cash.module.css +0 -10
- package/dist/admin/_money/finder-format.js +0 -1
- package/dist/admin/_money/finder-format.js.map +1 -1
- package/dist/admin/_money/format.js +0 -1
- package/dist/admin/_money/format.js.map +1 -1
- package/dist/admin/_overview/activation-panel.js +6 -6
- package/dist/admin/_overview/activation-panel.js.map +1 -1
- package/dist/admin/_overview/attention-groups.js +8 -8
- package/dist/admin/_overview/attention-groups.js.map +1 -1
- package/dist/admin/_overview/attention-panel.js +33 -37
- package/dist/admin/_overview/attention-panel.js.map +1 -1
- package/dist/admin/_overview/attention.module.css +3 -0
- package/dist/admin/_overview/control-room.js +13 -41
- package/dist/admin/_overview/control-room.js.map +1 -1
- package/dist/admin/_overview/kpi-row.js +7 -7
- package/dist/admin/_overview/kpi-row.js.map +1 -1
- package/dist/admin/_overview/leaders-panel.js +1 -1
- package/dist/admin/_overview/leaders-panel.js.map +1 -1
- package/dist/admin/_overview/overdue-outstanding.js +1 -2
- package/dist/admin/_overview/overdue-outstanding.js.map +1 -1
- package/dist/admin/_overview/portfolio-panel.js +5 -5
- package/dist/admin/_overview/portfolio-panel.js.map +1 -1
- package/dist/admin/_overview/position-panel.js +12 -8
- package/dist/admin/_overview/position-panel.js.map +1 -1
- package/dist/admin/_pos/pos-figures.js +5 -18
- package/dist/admin/_pos/pos-figures.js.map +1 -1
- package/dist/admin/_pos/pos-rules.js +0 -2
- package/dist/admin/_pos/pos-rules.js.map +1 -1
- package/dist/admin/_pos/pos-words.js +1 -6
- package/dist/admin/_pos/pos-words.js.map +1 -1
- package/dist/admin/_pos/use-pos.js +1 -70
- package/dist/admin/_pos/use-pos.js.map +1 -1
- package/dist/admin/_shell/nav-config.js +3 -3
- package/dist/admin/_shell/nav-config.js.map +1 -1
- package/dist/admin/_shell/nav-filter.js +2 -4
- package/dist/admin/_shell/nav-filter.js.map +1 -1
- package/dist/admin/_shell/nav-row.js +2 -5
- package/dist/admin/_shell/nav-row.js.map +1 -1
- package/dist/admin/_shell/sidebar-footer.js +0 -20
- package/dist/admin/_shell/sidebar-footer.js.map +1 -1
- package/dist/admin/_shell/sidebar-footer.module.css +0 -17
- package/dist/admin/_shell/sidebar.js +15 -25
- package/dist/admin/_shell/sidebar.js.map +1 -1
- package/dist/admin/_shell/sidebar.module.css +0 -69
- package/dist/admin/_shell/use-fluid-hover.js +6 -37
- package/dist/admin/_shell/use-fluid-hover.js.map +1 -1
- package/dist/admin/_ui/admin.css +0 -7
- package/dist/admin/_ui/data-table.js +1 -1
- package/dist/admin/_ui/data-table.js.map +1 -1
- package/dist/admin/_ui/list-card.js +1 -1
- package/dist/admin/_ui/list-card.js.map +1 -1
- package/dist/admin/_ui/list-card.module.css +16 -2
- package/dist/admin/_ui/money-view.js +0 -1
- package/dist/admin/_ui/money-view.js.map +1 -1
- package/dist/admin/_ui/page-header.js +4 -31
- package/dist/admin/_ui/page-header.js.map +1 -1
- package/dist/admin/_ui/panel.module.css +10 -0
- package/dist/admin/_ui/stat-card.js +2 -11
- package/dist/admin/_ui/stat-card.js.map +1 -1
- package/dist/admin/_ui/trend.js +2 -2
- package/dist/admin/_ui/trend.js.map +1 -1
- package/dist/admin/_ui/workspace-tab.js +1 -11
- package/dist/admin/_ui/workspace-tab.js.map +1 -1
- package/dist/admin/accounts/account-panel.js +6 -49
- package/dist/admin/accounts/account-panel.js.map +1 -1
- package/dist/admin/accounts/account-panel.module.css +0 -73
- package/dist/admin/accounts/account-row.js +2 -11
- package/dist/admin/accounts/account-row.js.map +1 -1
- package/dist/admin/accounts/account-vitals.js +13 -15
- package/dist/admin/accounts/account-vitals.js.map +1 -1
- package/dist/admin/accounts/accounts-table.js +8 -39
- package/dist/admin/accounts/accounts-table.js.map +1 -1
- package/dist/admin/accounts/accounts-workspace.js +2 -2
- package/dist/admin/accounts/accounts-workspace.js.map +1 -1
- package/dist/admin/accounts/owner-session.js +6 -0
- package/dist/admin/accounts/owner-session.js.map +1 -1
- package/dist/admin/accounts/rows.module.css +0 -17
- package/dist/admin/audit/status-pill.js +0 -6
- package/dist/admin/audit/status-pill.js.map +1 -1
- package/dist/admin/audit/status-pill.module.css +0 -4
- package/dist/admin/commerce/commerce-overview.js +2 -2
- package/dist/admin/commerce/commerce-overview.js.map +1 -1
- package/dist/admin/commerce/merchant-meta.js +0 -1
- package/dist/admin/commerce/merchant-meta.js.map +1 -1
- package/dist/admin/commerce/merchant-view.js +2 -2
- package/dist/admin/commerce/merchant-view.js.map +1 -1
- package/dist/admin/feedback/prompt-operations.module.css +2 -0
- package/dist/admin/feedback/prompt-preview.module.css +2 -0
- package/dist/admin/hooks.js +1 -57
- package/dist/admin/hooks.js.map +1 -1
- package/dist/admin/layout.js +2 -8
- package/dist/admin/layout.js.map +1 -1
- package/dist/admin/page.js +8 -28
- package/dist/admin/page.js.map +1 -1
- package/dist/admin/payout-tiers/_tier-dialog.js +21 -31
- package/dist/admin/payout-tiers/_tier-dialog.js.map +1 -1
- package/dist/admin/payout-tiers/tier-preview-result.js +9 -10
- package/dist/admin/payout-tiers/tier-preview-result.js.map +1 -1
- package/dist/admin/payout-tiers/tiers-table.js +17 -40
- package/dist/admin/payout-tiers/tiers-table.js.map +1 -1
- package/dist/admin/payout-tiers/tiers-workspace.js +17 -20
- package/dist/admin/payout-tiers/tiers-workspace.js.map +1 -1
- package/dist/admin/pos/pos-workspace.js +2 -6
- package/dist/admin/pos/pos-workspace.js.map +1 -1
- package/dist/admin/pos/shifts-tab.js +9 -16
- package/dist/admin/pos/shifts-tab.js.map +1 -1
- package/dist/admin/revenue/cohort-panel.js +6 -6
- package/dist/admin/revenue/cohort-panel.js.map +1 -1
- package/dist/admin/revenue/health-panel.js +21 -22
- package/dist/admin/revenue/health-panel.js.map +1 -1
- package/dist/admin/revenue/plan-mix-panel.js +3 -3
- package/dist/admin/revenue/plan-mix-panel.js.map +1 -1
- package/dist/admin/revenue/quality-panel.js +19 -19
- package/dist/admin/revenue/quality-panel.js.map +1 -1
- package/dist/admin/revenue/revenue-kpis.js +50 -111
- package/dist/admin/revenue/revenue-kpis.js.map +1 -1
- package/dist/admin/revenue/revenue-overview.js +46 -39
- package/dist/admin/revenue/revenue-overview.js.map +1 -1
- package/dist/admin/revenue/revenue-retention.js +13 -17
- package/dist/admin/revenue/revenue-retention.js.map +1 -1
- package/dist/admin/revenue/revenue-workspace.js +6 -53
- package/dist/admin/revenue/revenue-workspace.js.map +1 -1
- package/dist/admin/revenue/subscriptions-panel.js +14 -14
- package/dist/admin/revenue/subscriptions-panel.js.map +1 -1
- package/dist/admin/revenue/top-tenants-panel.js +4 -4
- package/dist/admin/revenue/top-tenants-panel.js.map +1 -1
- package/dist/admin/settings/account-tab.js +25 -1
- package/dist/admin/settings/account-tab.js.map +1 -1
- package/dist/admin/settings/general-tab.js +2 -2
- package/dist/admin/settings/general-tab.js.map +1 -1
- package/dist/admin/settings/system-status-card.js +30 -0
- package/dist/admin/settings/system-status-card.js.map +1 -0
- package/dist/admin/support/queue-card.module.css +4 -1
- package/dist/admin/tenants/[id]/commerce/format.js +1 -2
- package/dist/admin/tenants/[id]/commerce/format.js.map +1 -1
- package/dist/admin/tenants/[id]/commerce/recent-orders.js +1 -1
- package/dist/admin/tenants/[id]/commerce/recent-orders.js.map +1 -1
- package/dist/admin/tenants/[id]/page.js +10 -37
- package/dist/admin/tenants/[id]/page.js.map +1 -1
- package/dist/admin/tenants/[id]/tenant-layout.module.css +4 -1
- package/dist/admin/tenants/[id]/tenant-overview.js +2 -3
- package/dist/admin/tenants/[id]/tenant-overview.js.map +1 -1
- package/dist/admin/tenants/[id]/tenant-overview.module.css +1 -1
- package/dist/admin/tenants/[id]/tenant-pos.js +16 -64
- package/dist/admin/tenants/[id]/tenant-pos.js.map +1 -1
- package/dist/admin/tenants/[id]/tenant-wallet-card.js +2 -3
- package/dist/admin/tenants/[id]/tenant-wallet-card.js.map +1 -1
- package/dist/admin/tenants/[id]/verification/document-viewer.js +52 -3
- package/dist/admin/tenants/[id]/verification/document-viewer.js.map +1 -1
- package/dist/admin/tenants/[id]/verification/document-viewer.module.css +0 -51
- package/dist/admin/tenants/[id]/verification/tenant-verification.js +0 -10
- package/dist/admin/tenants/[id]/verification/tenant-verification.js.map +1 -1
- package/dist/admin/tenants/tenant-list-row.js +1 -2
- package/dist/admin/tenants/tenant-list-row.js.map +1 -1
- package/dist/admin/tenants/tenants-table.js +2 -3
- package/dist/admin/tenants/tenants-table.js.map +1 -1
- package/dist/admin/tenants/tenants-workspace.js +2 -2
- package/dist/admin/tenants/tenants-workspace.js.map +1 -1
- package/dist/admin/verification/verification-page.js +3 -19
- package/dist/admin/verification/verification-page.js.map +1 -1
- package/dist/admin/verification/verification.module.css +0 -10
- package/dist/admin/verification/waiting-case-actions.js +68 -0
- package/dist/admin/verification/waiting-case-actions.js.map +1 -0
- package/dist/admin/verification/waiting-cases.js +48 -66
- package/dist/admin/verification/waiting-cases.js.map +1 -1
- package/package.json +5 -5
- package/dist/admin/_pos/olive-balance.js +0 -40
- package/dist/admin/_pos/olive-balance.js.map +0 -1
- package/dist/admin/_pos/olive-state.js +0 -23
- package/dist/admin/_pos/olive-state.js.map +0 -1
- package/dist/admin/_pos/payments-model.js +0 -55
- package/dist/admin/_pos/payments-model.js.map +0 -1
- package/dist/admin/_pos/tenant-operators.js +0 -63
- package/dist/admin/_pos/tenant-operators.js.map +0 -1
- package/dist/admin/_pos/tenant-outlets.js +0 -77
- package/dist/admin/_pos/tenant-outlets.js.map +0 -1
- package/dist/admin/_pos/tenant-pos-figures.js +0 -82
- package/dist/admin/_pos/tenant-pos-figures.js.map +0 -1
- package/dist/admin/_pos/tenant-requests.js +0 -64
- package/dist/admin/_pos/tenant-requests.js.map +0 -1
- package/dist/admin/_pos/tenant-transactions.js +0 -145
- package/dist/admin/_pos/tenant-transactions.js.map +0 -1
- package/dist/admin/_shell/nav-fold.js +0 -14
- package/dist/admin/_shell/nav-fold.js.map +0 -1
- package/dist/admin/_shell/nav-group.js +0 -78
- package/dist/admin/_shell/nav-group.js.map +0 -1
- package/dist/admin/_shell/use-open-groups.js +0 -64
- package/dist/admin/_shell/use-open-groups.js.map +0 -1
- package/dist/admin/_ui/page-header.module.css +0 -45
- package/dist/admin/accounts/account-sessions.js +0 -70
- package/dist/admin/accounts/account-sessions.js.map +0 -1
- package/dist/admin/accounts/account-sessions.module.css +0 -55
- package/dist/admin/accounts/account-stage-filter.js +0 -29
- package/dist/admin/accounts/account-stage-filter.js.map +0 -1
- package/dist/admin/accounts/account-stage.js +0 -81
- package/dist/admin/accounts/account-stage.js.map +0 -1
- package/dist/admin/accounts/hint.js +0 -12
- package/dist/admin/accounts/hint.js.map +0 -1
- package/dist/admin/payout-tiers/requirement-labels.js +0 -70
- package/dist/admin/payout-tiers/requirement-labels.js.map +0 -1
- package/dist/admin/pos/transactions-tab.js +0 -214
- package/dist/admin/pos/transactions-tab.js.map +0 -1
- package/dist/admin/revenue/channel-panel.js +0 -49
- package/dist/admin/revenue/channel-panel.js.map +0 -1
- package/dist/admin/revenue/channel-rows.js +0 -17
- package/dist/admin/revenue/channel-rows.js.map +0 -1
- package/dist/admin/revenue/download-button.js +0 -40
- package/dist/admin/revenue/download-button.js.map +0 -1
- package/dist/admin/revenue/earnings/earnings-colors.js +0 -25
- package/dist/admin/revenue/earnings/earnings-colors.js.map +0 -1
- package/dist/admin/revenue/earnings/earnings-legend.js +0 -75
- package/dist/admin/revenue/earnings/earnings-legend.js.map +0 -1
- package/dist/admin/revenue/earnings/earnings-summary.js +0 -308
- package/dist/admin/revenue/earnings/earnings-summary.js.map +0 -1
- package/dist/admin/revenue/earnings/earnings-table.js +0 -143
- package/dist/admin/revenue/earnings/earnings-table.js.map +0 -1
- package/dist/admin/revenue/earnings/earnings.module.css +0 -201
- package/dist/admin/revenue/earnings/use-earnings.js +0 -27
- package/dist/admin/revenue/earnings/use-earnings.js.map +0 -1
- package/dist/admin/revenue/ledger-model.js +0 -104
- package/dist/admin/revenue/ledger-model.js.map +0 -1
- package/dist/admin/revenue/ledger.module.css +0 -144
- package/dist/admin/revenue/merchant-headline.js +0 -37
- package/dist/admin/revenue/merchant-headline.js.map +0 -1
- package/dist/admin/revenue/merchant-payments-view.js +0 -234
- package/dist/admin/revenue/merchant-payments-view.js.map +0 -1
- package/dist/admin/revenue/method-cards.js +0 -40
- package/dist/admin/revenue/method-cards.js.map +0 -1
- package/dist/admin/revenue/payment-drawer.js +0 -53
- package/dist/admin/revenue/payment-drawer.js.map +0 -1
- package/dist/admin/revenue/plan-lines.js +0 -36
- package/dist/admin/revenue/plan-lines.js.map +0 -1
- package/dist/admin/revenue/plan-payment-drawer.js +0 -42
- package/dist/admin/revenue/plan-payment-drawer.js.map +0 -1
- package/dist/admin/revenue/plans-panel.js +0 -48
- package/dist/admin/revenue/plans-panel.js.map +0 -1
- package/dist/admin/revenue/platform-fees.js +0 -9
- package/dist/admin/revenue/platform-fees.js.map +0 -1
- package/dist/admin/revenue/print-summary-button.js +0 -27
- package/dist/admin/revenue/print-summary-button.js.map +0 -1
- package/dist/admin/revenue/subscriptions-view.js +0 -213
- package/dist/admin/revenue/subscriptions-view.js.map +0 -1
- package/dist/admin/revenue/summary-download.js +0 -38
- package/dist/admin/revenue/summary-download.js.map +0 -1
- package/dist/admin/revenue/summary-print.js +0 -82
- package/dist/admin/revenue/summary-print.js.map +0 -1
- package/dist/admin/revenue/summary-rows.js +0 -44
- package/dist/admin/revenue/summary-rows.js.map +0 -1
- package/dist/admin/revenue/url-filters.js +0 -36
- package/dist/admin/revenue/url-filters.js.map +0 -1
- package/dist/admin/revenue/use-url-filters.js +0 -24
- package/dist/admin/revenue/use-url-filters.js.map +0 -1
- package/dist/admin/tenants/[id]/use-tenant-wallet.js +0 -23
- package/dist/admin/tenants/[id]/use-tenant-wallet.js.map +0 -1
- package/dist/admin/tenants/[id]/verification/document-file.js +0 -78
- package/dist/admin/tenants/[id]/verification/document-file.js.map +0 -1
- package/dist/admin/tenants/[id]/verification/sent-files.js +0 -33
- package/dist/admin/tenants/[id]/verification/sent-files.js.map +0 -1
- package/dist/admin/verification/preview-dialog.js +0 -111
- 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":[]}
|