@withpotter/pages-admin 0.13.0-next.103 → 0.13.0-next.105
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/_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 +3 -3
- package/dist/admin/_overview/attention-panel.js.map +1 -1
- package/dist/admin/_overview/control-room.js +9 -9
- 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/portfolio-panel.js +5 -5
- package/dist/admin/_overview/portfolio-panel.js.map +1 -1
- package/dist/admin/_overview/position-panel.js +6 -6
- package/dist/admin/_overview/position-panel.js.map +1 -1
- package/dist/admin/_pos/olive-balance.js +40 -0
- package/dist/admin/_pos/olive-balance.js.map +1 -0
- package/dist/admin/_pos/olive-state.js +23 -0
- package/dist/admin/_pos/olive-state.js.map +1 -0
- package/dist/admin/_pos/pos-rules.js +2 -0
- package/dist/admin/_pos/pos-rules.js.map +1 -1
- package/dist/admin/_pos/tenant-operators.js +36 -46
- package/dist/admin/_pos/tenant-operators.js.map +1 -1
- package/dist/admin/_pos/tenant-outlets.js +77 -0
- package/dist/admin/_pos/tenant-outlets.js.map +1 -0
- package/dist/admin/_pos/tenant-requests.js +64 -0
- package/dist/admin/_pos/tenant-requests.js.map +1 -0
- package/dist/admin/_pos/tenant-transactions.js +145 -0
- package/dist/admin/_pos/tenant-transactions.js.map +1 -0
- package/dist/admin/_pos/use-pos.js +60 -11
- package/dist/admin/_pos/use-pos.js.map +1 -1
- 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/trend.js +2 -2
- package/dist/admin/_ui/trend.js.map +1 -1
- package/dist/admin/page.js +6 -6
- package/dist/admin/page.js.map +1 -1
- package/dist/admin/payout-tiers/_tier-dialog.js +31 -21
- package/dist/admin/payout-tiers/_tier-dialog.js.map +1 -1
- package/dist/admin/payout-tiers/requirement-labels.js +70 -0
- package/dist/admin/payout-tiers/requirement-labels.js.map +1 -0
- package/dist/admin/payout-tiers/tier-preview-result.js +10 -9
- package/dist/admin/payout-tiers/tier-preview-result.js.map +1 -1
- package/dist/admin/payout-tiers/tiers-table.js +6 -7
- package/dist/admin/payout-tiers/tiers-table.js.map +1 -1
- package/dist/admin/payout-tiers/tiers-workspace.js +2 -2
- package/dist/admin/payout-tiers/tiers-workspace.js.map +1 -1
- package/dist/admin/revenue/cohort-panel.js +1 -1
- package/dist/admin/revenue/cohort-panel.js.map +1 -1
- package/dist/admin/revenue/plan-mix-panel.js +2 -2
- package/dist/admin/revenue/plan-mix-panel.js.map +1 -1
- package/dist/admin/revenue/revenue-kpis.js +3 -3
- package/dist/admin/revenue/revenue-kpis.js.map +1 -1
- package/dist/admin/revenue/revenue-overview.js +1 -1
- package/dist/admin/revenue/revenue-overview.js.map +1 -1
- package/dist/admin/revenue/subscriptions-view.js +3 -3
- package/dist/admin/revenue/subscriptions-view.js.map +1 -1
- package/dist/admin/revenue/top-tenants-panel.js +3 -3
- package/dist/admin/revenue/top-tenants-panel.js.map +1 -1
- package/dist/admin/tenants/[id]/tenant-pos.js +13 -2
- package/dist/admin/tenants/[id]/tenant-pos.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/_pos/olive-state.tsx"],"sourcesContent":["'use client';\n\nimport { EmptyNote } from '@withpotter/ui-kit';\nimport { formatMinor } from '@withpotter/lib/money-minor';\nimport { LoadError } from './pos-parts';\nimport { isNotLinked } from './pos-rules';\n\n/** Olive's amounts are kobo; the merchant's own POS page shows them as naira. */\nexport const naira = (minor: number | null) =>\n minor === null ? '–' : formatMinor(String(Math.trunc(minor)), 'NGN');\n\n/**\n * Why Olive's data is not on screen. A business that has not linked Olive is a state, not a fault, and\n * says so; anything else is a retry.\n */\nexport function OliveProblem({\n error,\n what,\n onRetry,\n}: {\n error: unknown;\n what: string;\n onRetry: () => void;\n}) {\n if (isNotLinked(error))\n return (\n <EmptyNote well>\n {`This business has not linked its Olive account, so its ${what} cannot be read yet.`}\n </EmptyNote>\n );\n\n return <LoadError error={error} what={`its ${what}`} onRetry={onRetry} />;\n}\n\nexport const OLIVE_NOTE =\n 'Read live from Olive under the business’s own login. Each view is recorded in the audit log.';\n"],"mappings":";AA0BM;AAxBN,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAGrB,MAAM,QAAQ,CAAC,UACpB,UAAU,OAAO,WAAM,YAAY,OAAO,KAAK,MAAM,KAAK,CAAC,GAAG,KAAK;AAM9D,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,MAAI,YAAY,KAAK;AACnB,WACE,oBAAC,aAAU,MAAI,MACZ,oEAA0D,IAAI,wBACjE;AAGJ,SAAO,oBAAC,aAAU,OAAc,MAAM,OAAO,IAAI,IAAI,SAAkB;AACzE;AAEO,MAAM,aACX;","names":[]}
|
|
@@ -17,6 +17,7 @@ const statusOf = (e) => e?.status;
|
|
|
17
17
|
const isStale = (e) => statusOf(e) === 409;
|
|
18
18
|
const isForbidden = (e) => statusOf(e) === 403;
|
|
19
19
|
const isNotFound = (e) => statusOf(e) === 404;
|
|
20
|
+
const isNotLinked = (e) => statusOf(e) === 400;
|
|
20
21
|
const STALE_TEXT = "This changed since you opened it. Refresh to see where it stands now.";
|
|
21
22
|
function posErrorText(error, fallback) {
|
|
22
23
|
const status = statusOf(error);
|
|
@@ -35,6 +36,7 @@ export {
|
|
|
35
36
|
isForbidden,
|
|
36
37
|
isLongOpen,
|
|
37
38
|
isNotFound,
|
|
39
|
+
isNotLinked,
|
|
38
40
|
isStale,
|
|
39
41
|
posErrorText,
|
|
40
42
|
reasonError,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/_pos/pos-rules.ts"],"sourcesContent":["import type {\n PosShift,\n PosTerminalStatus,\n} from '@withpotter/lib/admin-pos-types';\n\n/**\n * What an admin may do to a terminal or a shift, the forms' checks and what\n * an error says. Pure, so the rules the API enforces are tested here rather\n * than met as a 409.\n */\n\nexport const REASON_MAX = 300;\n\n/** A shift open this long is flagged; the API's own threshold. */\nexport const LONG_OPEN_HOURS = 12;\n\nexport type TerminalAction = 'suspend' | 'resume' | 'revoke';\n\n/**\n * Suspend needs active, resume needs suspended, revoke works from either\n * and is one-way. A revoked terminal has nothing left to do.\n */\nexport function terminalActions(status: PosTerminalStatus): TerminalAction[] {\n if (status === 'revoked') return [];\n\n return [status === 'active' ? 'suspend' : 'resume', 'revoke'];\n}\n\nexport const canCloseShift = (s: Pick<PosShift, 'status'>) =>\n s.status === 'open';\n\nexport const isLongOpen = (s: Pick<PosShift, 'status' | 'openHours'>) =>\n s.status === 'open' && (s.openHours ?? 0) >= LONG_OPEN_HOURS;\n\n/** An error for a reason, or undefined when it can be sent. */\nexport function reasonError(reason: string): string | undefined {\n const clean = reason.trim();\n\n if (!clean) return 'Say why, for the audit log.';\n\n if (clean.length > REASON_MAX)\n return `Keep the reason to ${REASON_MAX} characters.`;\n\n return undefined;\n}\n\nconst statusOf = (e: unknown) => (e as { status?: unknown } | null)?.status;\n\n/** The record changed under the admin: someone else acted first. */\nexport const isStale = (e: unknown) => statusOf(e) === 409;\n\nexport const isForbidden = (e: unknown) => statusOf(e) === 403;\n\nexport const isNotFound = (e: unknown) => statusOf(e) === 404;\n\nexport const STALE_TEXT =\n 'This changed since you opened it. Refresh to see where it stands now.';\n\n/**\n * An error in plain words. A 409 means the terminal or shift moved on, so\n * it says so and offers a refresh. A 400 keeps the server's line.\n */\nexport function posErrorText(error: unknown, fallback: string): string {\n const status = statusOf(error);\n const message = error instanceof Error ? error.message.trim() : '';\n\n if (status === 409) return STALE_TEXT;\n\n if (status === 403) return \"You don't have permission to do this.\";\n\n if (status === 404) return 'This no longer exists. Refresh the list.';\n\n if (status === 400 && message) return message;\n\n return fallback;\n}\n"],"mappings":"AAWO,MAAM,aAAa;AAGnB,MAAM,kBAAkB;AAQxB,SAAS,gBAAgB,QAA6C;AAC3E,MAAI,WAAW,UAAW,QAAO,CAAC;AAElC,SAAO,CAAC,WAAW,WAAW,YAAY,UAAU,QAAQ;AAC9D;AAEO,MAAM,gBAAgB,CAAC,MAC5B,EAAE,WAAW;AAER,MAAM,aAAa,CAAC,MACzB,EAAE,WAAW,WAAW,EAAE,aAAa,MAAM;AAGxC,SAAS,YAAY,QAAoC;AAC9D,QAAM,QAAQ,OAAO,KAAK;AAE1B,MAAI,CAAC,MAAO,QAAO;AAEnB,MAAI,MAAM,SAAS;AACjB,WAAO,sBAAsB,UAAU;AAEzC,SAAO;AACT;AAEA,MAAM,WAAW,CAAC,MAAgB,GAAmC;AAG9D,MAAM,UAAU,CAAC,MAAe,SAAS,CAAC,MAAM;AAEhD,MAAM,cAAc,CAAC,MAAe,SAAS,CAAC,MAAM;AAEpD,MAAM,aAAa,CAAC,MAAe,SAAS,CAAC,MAAM;
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/_pos/pos-rules.ts"],"sourcesContent":["import type {\n PosShift,\n PosTerminalStatus,\n} from '@withpotter/lib/admin-pos-types';\n\n/**\n * What an admin may do to a terminal or a shift, the forms' checks and what\n * an error says. Pure, so the rules the API enforces are tested here rather\n * than met as a 409.\n */\n\nexport const REASON_MAX = 300;\n\n/** A shift open this long is flagged; the API's own threshold. */\nexport const LONG_OPEN_HOURS = 12;\n\nexport type TerminalAction = 'suspend' | 'resume' | 'revoke';\n\n/**\n * Suspend needs active, resume needs suspended, revoke works from either\n * and is one-way. A revoked terminal has nothing left to do.\n */\nexport function terminalActions(status: PosTerminalStatus): TerminalAction[] {\n if (status === 'revoked') return [];\n\n return [status === 'active' ? 'suspend' : 'resume', 'revoke'];\n}\n\nexport const canCloseShift = (s: Pick<PosShift, 'status'>) =>\n s.status === 'open';\n\nexport const isLongOpen = (s: Pick<PosShift, 'status' | 'openHours'>) =>\n s.status === 'open' && (s.openHours ?? 0) >= LONG_OPEN_HOURS;\n\n/** An error for a reason, or undefined when it can be sent. */\nexport function reasonError(reason: string): string | undefined {\n const clean = reason.trim();\n\n if (!clean) return 'Say why, for the audit log.';\n\n if (clean.length > REASON_MAX)\n return `Keep the reason to ${REASON_MAX} characters.`;\n\n return undefined;\n}\n\nconst statusOf = (e: unknown) => (e as { status?: unknown } | null)?.status;\n\n/** The record changed under the admin: someone else acted first. */\nexport const isStale = (e: unknown) => statusOf(e) === 409;\n\nexport const isForbidden = (e: unknown) => statusOf(e) === 403;\n\nexport const isNotFound = (e: unknown) => statusOf(e) === 404;\n\n/** The business has not linked Olive (or must reconnect it): Olive's data cannot be read yet. */\nexport const isNotLinked = (e: unknown) => statusOf(e) === 400;\n\nexport const STALE_TEXT =\n 'This changed since you opened it. Refresh to see where it stands now.';\n\n/**\n * An error in plain words. A 409 means the terminal or shift moved on, so\n * it says so and offers a refresh. A 400 keeps the server's line.\n */\nexport function posErrorText(error: unknown, fallback: string): string {\n const status = statusOf(error);\n const message = error instanceof Error ? error.message.trim() : '';\n\n if (status === 409) return STALE_TEXT;\n\n if (status === 403) return \"You don't have permission to do this.\";\n\n if (status === 404) return 'This no longer exists. Refresh the list.';\n\n if (status === 400 && message) return message;\n\n return fallback;\n}\n"],"mappings":"AAWO,MAAM,aAAa;AAGnB,MAAM,kBAAkB;AAQxB,SAAS,gBAAgB,QAA6C;AAC3E,MAAI,WAAW,UAAW,QAAO,CAAC;AAElC,SAAO,CAAC,WAAW,WAAW,YAAY,UAAU,QAAQ;AAC9D;AAEO,MAAM,gBAAgB,CAAC,MAC5B,EAAE,WAAW;AAER,MAAM,aAAa,CAAC,MACzB,EAAE,WAAW,WAAW,EAAE,aAAa,MAAM;AAGxC,SAAS,YAAY,QAAoC;AAC9D,QAAM,QAAQ,OAAO,KAAK;AAE1B,MAAI,CAAC,MAAO,QAAO;AAEnB,MAAI,MAAM,SAAS;AACjB,WAAO,sBAAsB,UAAU;AAEzC,SAAO;AACT;AAEA,MAAM,WAAW,CAAC,MAAgB,GAAmC;AAG9D,MAAM,UAAU,CAAC,MAAe,SAAS,CAAC,MAAM;AAEhD,MAAM,cAAc,CAAC,MAAe,SAAS,CAAC,MAAM;AAEpD,MAAM,aAAa,CAAC,MAAe,SAAS,CAAC,MAAM;AAGnD,MAAM,cAAc,CAAC,MAAe,SAAS,CAAC,MAAM;AAEpD,MAAM,aACX;AAMK,SAAS,aAAa,OAAgB,UAA0B;AACrE,QAAM,SAAS,SAAS,KAAK;AAC7B,QAAM,UAAU,iBAAiB,QAAQ,MAAM,QAAQ,KAAK,IAAI;AAEhE,MAAI,WAAW,IAAK,QAAO;AAE3B,MAAI,WAAW,IAAK,QAAO;AAE3B,MAAI,WAAW,IAAK,QAAO;AAE3B,MAAI,WAAW,OAAO,QAAS,QAAO;AAEtC,SAAO;AACT;","names":[]}
|
|
@@ -1,73 +1,63 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo } from "react";
|
|
4
3
|
import { TableRow, Th } from "@withpotter/ui-kit";
|
|
5
4
|
import { ListCard } from "../_ui/list-card";
|
|
6
5
|
import list from "../_ui/list-card.module.css";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { LoadError } from "./pos-parts";
|
|
7
|
+
import { isForbidden, posErrorText } from "./pos-rules";
|
|
8
|
+
import { atTime } from "./pos-words";
|
|
9
|
+
import { useTenantRoster } from "./use-pos";
|
|
10
10
|
import pos from "./pos.module.css";
|
|
11
11
|
const sentence = (s) => s ? s.charAt(0).toUpperCase() + s.slice(1).replace(/_/g, " ") : s;
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
for (const r of results) {
|
|
29
|
-
const t = r.data;
|
|
30
|
-
if (!t) continue;
|
|
31
|
-
for (const o of t.operators) {
|
|
32
|
-
const row = byId.get(o.id) ?? { ...o, at: [] };
|
|
33
|
-
row.at.push(t.label);
|
|
34
|
-
byId.set(o.id, row);
|
|
12
|
+
function shiftLimit(minutes) {
|
|
13
|
+
if (!Number.isFinite(minutes) || minutes <= 0) return "\u2013";
|
|
14
|
+
const h = Math.floor(minutes / 60);
|
|
15
|
+
const m = minutes % 60;
|
|
16
|
+
if (!h) return `${m} min`;
|
|
17
|
+
return m ? `${h} h ${m} min` : `${h} h`;
|
|
18
|
+
}
|
|
19
|
+
function TenantOperators({ tenantId }) {
|
|
20
|
+
const { data, isLoading, isError, error, refetch } = useTenantRoster(tenantId);
|
|
21
|
+
if (isError && !data)
|
|
22
|
+
return /* @__PURE__ */ jsx(
|
|
23
|
+
LoadError,
|
|
24
|
+
{
|
|
25
|
+
error,
|
|
26
|
+
what: "this business's operators",
|
|
27
|
+
onRetry: () => void refetch()
|
|
35
28
|
}
|
|
36
|
-
|
|
37
|
-
return [...byId.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
38
|
-
}, [results.map((r) => r.dataUpdatedAt).join(",")]);
|
|
39
|
-
const open = live.some((t) => t.operatorAccess === "any_member");
|
|
29
|
+
);
|
|
40
30
|
return /* @__PURE__ */ jsx(
|
|
41
31
|
ListCard,
|
|
42
32
|
{
|
|
43
33
|
title: "Operators",
|
|
44
|
-
count:
|
|
45
|
-
columns:
|
|
46
|
-
minWidth:
|
|
34
|
+
count: data?.length,
|
|
35
|
+
columns: 4,
|
|
36
|
+
minWidth: 640,
|
|
47
37
|
isLoading,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
isEmpty: people.length === 0,
|
|
52
|
-
emptyTitle: live.length === 0 ? "This business has no terminals, so no operators." : "Nobody can sign in at its terminals yet.",
|
|
53
|
-
controls: live[0] ? /* @__PURE__ */ jsx("span", { className: "adm-caption", children: open ? accessLine({ operatorAccess: "any_member" }) : accessLine(live[0]) }) : void 0,
|
|
38
|
+
errorTitle: isForbidden(error) ? "" : posErrorText(error, "Operators did not load."),
|
|
39
|
+
isEmpty: data?.length === 0,
|
|
40
|
+
emptyTitle: "Nobody can sign in at this business's terminals yet.",
|
|
54
41
|
head: /* @__PURE__ */ jsxs("tr", { children: [
|
|
55
|
-
/* @__PURE__ */ jsx(Th, { children: "
|
|
42
|
+
/* @__PURE__ */ jsx(Th, { children: "Operator" }),
|
|
56
43
|
/* @__PURE__ */ jsx(Th, { children: "Role" }),
|
|
57
|
-
/* @__PURE__ */ jsx(Th, { children: "
|
|
44
|
+
/* @__PURE__ */ jsx(Th, { children: "Shift limit" }),
|
|
45
|
+
/* @__PURE__ */ jsx(Th, { children: "Updated" })
|
|
58
46
|
] }),
|
|
59
|
-
children:
|
|
47
|
+
children: data?.map((o) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
60
48
|
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("span", { className: pos.cellStack, children: [
|
|
61
49
|
/* @__PURE__ */ jsx("span", { className: pos.clip, children: o.name }),
|
|
62
|
-
|
|
50
|
+
/* @__PURE__ */ jsx("span", { className: pos.subtle, children: o.active ? o.signIn !== o.name ? `Signs in as ${o.signIn}` : "" : "Removed" })
|
|
63
51
|
] }) }),
|
|
64
52
|
/* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: sentence(o.role) }),
|
|
65
|
-
/* @__PURE__ */ jsx("td", { className: list.muted
|
|
53
|
+
/* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: shiftLimit(o.shiftLimitMinutes) }),
|
|
54
|
+
/* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: atTime(o.updatedAt) })
|
|
66
55
|
] }, o.id))
|
|
67
56
|
}
|
|
68
57
|
);
|
|
69
58
|
}
|
|
70
59
|
export {
|
|
71
|
-
TenantOperators
|
|
60
|
+
TenantOperators,
|
|
61
|
+
shiftLimit
|
|
72
62
|
};
|
|
73
63
|
//# sourceMappingURL=tenant-operators.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/_pos/tenant-operators.tsx"],"sourcesContent":["'use client';\n\nimport {
|
|
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":[]}
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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":[]}
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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":[]}
|
|
@@ -0,0 +1,145 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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":[]}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
keepPreviousData,
|
|
4
4
|
useMutation,
|
|
5
|
-
|
|
5
|
+
useInfiniteQuery,
|
|
6
6
|
useQuery,
|
|
7
7
|
useQueryClient
|
|
8
8
|
} from "@tanstack/react-query";
|
|
9
9
|
import { adminPosApi } from "@withpotter/lib/admin-pos-api";
|
|
10
|
-
import { isForbidden, isNotFound } from "./pos-rules";
|
|
10
|
+
import { isForbidden, isNotFound, isNotLinked } from "./pos-rules";
|
|
11
11
|
const POS_KEY = ["platform-admin", "pos"];
|
|
12
12
|
const key = (...parts) => [...POS_KEY, ...parts];
|
|
13
13
|
const retry = (count, error) => !isForbidden(error) && !isNotFound(error) && count < 1;
|
|
@@ -53,14 +53,58 @@ function usePosShifts(filters, enabled = true) {
|
|
|
53
53
|
retry
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
-
function
|
|
57
|
-
return
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
function useTenantRoster(tenantId, enabled = true) {
|
|
57
|
+
return useQuery({
|
|
58
|
+
queryKey: key("roster", tenantId),
|
|
59
|
+
queryFn: () => adminPosApi.roster(tenantId),
|
|
60
|
+
enabled,
|
|
61
|
+
retry
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function useTenantTillRequests(tenantId, enabled = true) {
|
|
65
|
+
return useQuery({
|
|
66
|
+
queryKey: key("till-requests", tenantId),
|
|
67
|
+
queryFn: () => adminPosApi.tillRequests(tenantId),
|
|
68
|
+
enabled,
|
|
69
|
+
retry
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function useTenantPayments(tenantId, enabled = true) {
|
|
73
|
+
return useInfiniteQuery({
|
|
74
|
+
queryKey: key("payments", tenantId),
|
|
75
|
+
queryFn: ({ pageParam }) => adminPosApi.payments({ tenantId, cursor: pageParam, limit: 25 }),
|
|
76
|
+
initialPageParam: void 0,
|
|
77
|
+
getNextPageParam: (last) => last.nextCursor ?? void 0,
|
|
78
|
+
enabled,
|
|
79
|
+
retry
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const oliveRetry = (count, error) => !isForbidden(error) && !isNotFound(error) && !isNotLinked(error) && count < 1;
|
|
83
|
+
function useOliveAccount(tenantId, enabled = true) {
|
|
84
|
+
return useQuery({
|
|
85
|
+
queryKey: key("olive", tenantId, "account"),
|
|
86
|
+
queryFn: () => adminPosApi.olive.account(tenantId),
|
|
87
|
+
enabled,
|
|
88
|
+
retry: oliveRetry,
|
|
89
|
+
staleTime: 6e4
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function useOliveAccountTransactions(tenantId, enabled = true) {
|
|
93
|
+
return useQuery({
|
|
94
|
+
queryKey: key("olive", tenantId, "account-transactions"),
|
|
95
|
+
queryFn: () => adminPosApi.olive.accountTransactions(tenantId),
|
|
96
|
+
enabled,
|
|
97
|
+
retry: oliveRetry,
|
|
98
|
+
staleTime: 6e4
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function useOliveOutlets(tenantId, enabled = true) {
|
|
102
|
+
return useQuery({
|
|
103
|
+
queryKey: key("olive", tenantId, "outlets"),
|
|
104
|
+
queryFn: () => adminPosApi.olive.outlets(tenantId),
|
|
105
|
+
enabled,
|
|
106
|
+
retry: oliveRetry,
|
|
107
|
+
staleTime: 6e4
|
|
64
108
|
});
|
|
65
109
|
}
|
|
66
110
|
function useTenantPos(tenantId, w, enabled = true) {
|
|
@@ -89,13 +133,18 @@ const useCloseShift = () => usePosWrite(
|
|
|
89
133
|
export {
|
|
90
134
|
POS_KEY,
|
|
91
135
|
useCloseShift,
|
|
136
|
+
useOliveAccount,
|
|
137
|
+
useOliveAccountTransactions,
|
|
138
|
+
useOliveOutlets,
|
|
92
139
|
usePosHistory,
|
|
93
140
|
usePosShifts,
|
|
94
141
|
usePosSummary,
|
|
95
142
|
usePosTerminal,
|
|
96
143
|
usePosTerminals,
|
|
97
|
-
|
|
144
|
+
useTenantPayments,
|
|
98
145
|
useTenantPos,
|
|
146
|
+
useTenantRoster,
|
|
147
|
+
useTenantTillRequests,
|
|
99
148
|
useTerminalStatus
|
|
100
149
|
};
|
|
101
150
|
//# sourceMappingURL=use-pos.js.map
|