@withpotter/pages-admin 0.13.0-next.61 → 0.13.0-next.62

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.
@@ -0,0 +1,111 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useRef, useState } from "react";
4
+ import {
5
+ Button,
6
+ ErrorBanner,
7
+ FormDialog,
8
+ useConfirm,
9
+ useToast
10
+ } from "@withpotter/ui-kit";
11
+ import { AdmLoading } from "../_ui";
12
+ import { useMoneyPermissions } from "../_money/permissions";
13
+ import { documentWord } from "../tenants/[id]/verification/case-checks";
14
+ import {
15
+ barMode,
16
+ caseErrorText
17
+ } from "../tenants/[id]/verification/case-rules";
18
+ import { DenyDialog } from "../tenants/[id]/verification/decision-dialogs";
19
+ import { DocumentFile } from "../tenants/[id]/verification/document-file";
20
+ import { ownerName } from "../tenants/[id]/verification/document-view";
21
+ import { useCase, useDecideCase } from "../tenants/[id]/verification/use-case";
22
+ import styles from "../tenants/[id]/verification/verification.module.css";
23
+ import viewer from "../tenants/[id]/verification/document-viewer.module.css";
24
+ function PreviewDialog({
25
+ tenantId,
26
+ business,
27
+ onClose
28
+ }) {
29
+ const { toast } = useToast();
30
+ const confirm = useConfirm();
31
+ const { manageComplianceHint } = useMoneyPermissions();
32
+ const query = useCase(tenantId);
33
+ const decide = useDecideCase(tenantId);
34
+ const [denying, setDenying] = useState(false);
35
+ const data = query.data;
36
+ const mode = data ? barMode(data.status) : null;
37
+ const wasDeciding = useRef(false);
38
+ useEffect(() => {
39
+ if (mode === "decide") wasDeciding.current = true;
40
+ else if (wasDeciding.current) onClose();
41
+ }, [mode, onClose]);
42
+ async function approve() {
43
+ const ok = await confirm({
44
+ title: `Approve ${business}?`,
45
+ description: "Everyone listed is marked verified.",
46
+ confirmLabel: "Approve"
47
+ });
48
+ if (!ok) return;
49
+ decide.mutate(
50
+ { decision: "APPROVE" },
51
+ {
52
+ onSuccess: () => toast({ title: `${business} approved` }),
53
+ onError: (e) => toast({ title: caseErrorText(e, "decide"), variant: "destructive" })
54
+ }
55
+ );
56
+ }
57
+ const files = data?.documents ?? [];
58
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
59
+ /* @__PURE__ */ jsxs(
60
+ FormDialog,
61
+ {
62
+ open: !denying,
63
+ onClose,
64
+ title: business,
65
+ description: "What the merchant sent",
66
+ size: "lg",
67
+ footer: /* @__PURE__ */ jsxs("div", { className: styles.footer, children: [
68
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onClose, children: "Close" }),
69
+ mode === "decide" && /* @__PURE__ */ jsxs(Fragment, { children: [
70
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setDenying(true), children: "Deny" }),
71
+ /* @__PURE__ */ jsx(
72
+ Button,
73
+ {
74
+ loading: decide.isPending,
75
+ onClick: () => void approve(),
76
+ children: "Approve"
77
+ }
78
+ )
79
+ ] })
80
+ ] }),
81
+ children: [
82
+ query.isLoading && /* @__PURE__ */ jsx(AdmLoading, { label: "Loading what was sent\u2026" }),
83
+ (query.isError || !query.isLoading && !data) && /* @__PURE__ */ jsx(ErrorBanner, { children: caseErrorText(query.error, "load") }),
84
+ data && files.length === 0 && /* @__PURE__ */ jsx("p", { className: viewer.note, children: "No photos or documents sent." }),
85
+ data && files.map((d) => /* @__PURE__ */ jsxs("div", { className: styles.stack, children: [
86
+ /* @__PURE__ */ jsxs("span", { className: viewer.note, children: [
87
+ documentWord(d),
88
+ " \xB7 ",
89
+ ownerName(d, data.people)
90
+ ] }),
91
+ /* @__PURE__ */ jsx(DocumentFile, { tenantId, document: d })
92
+ ] }, d.id)),
93
+ manageComplianceHint && /* @__PURE__ */ jsx("span", { className: "adm-caption", children: manageComplianceHint })
94
+ ]
95
+ }
96
+ ),
97
+ /* @__PURE__ */ jsx(
98
+ DenyDialog,
99
+ {
100
+ tenantId,
101
+ business,
102
+ open: denying,
103
+ onClose: () => setDenying(false)
104
+ }
105
+ )
106
+ ] });
107
+ }
108
+ export {
109
+ PreviewDialog
110
+ };
111
+ //# sourceMappingURL=preview-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/admin/verification/preview-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport {\n Button,\n ErrorBanner,\n FormDialog,\n useConfirm,\n useToast,\n} from \"@withpotter/ui-kit\";\nimport { AdmLoading } from \"../_ui\";\nimport { useMoneyPermissions } from \"../_money/permissions\";\nimport { documentWord } from \"../tenants/[id]/verification/case-checks\";\nimport {\n barMode,\n caseErrorText,\n} from \"../tenants/[id]/verification/case-rules\";\nimport { DenyDialog } from \"../tenants/[id]/verification/decision-dialogs\";\nimport { DocumentFile } from \"../tenants/[id]/verification/document-file\";\nimport { ownerName } from \"../tenants/[id]/verification/document-view\";\nimport { useCase, useDecideCase } from \"../tenants/[id]/verification/use-case\";\nimport styles from \"../tenants/[id]/verification/verification.module.css\";\nimport viewer from \"../tenants/[id]/verification/document-viewer.module.css\";\n\n/**\n * A popup over the Verification list: every photo and document the business\n * sent, full size, with Approve and Deny at the foot, so the admin decides\n * without leaving the list. It closes once the case is no longer waiting.\n */\nexport function PreviewDialog({\n tenantId,\n business,\n onClose,\n}: {\n tenantId: string;\n business: string;\n onClose: () => void;\n}) {\n const { toast } = useToast();\n const confirm = useConfirm();\n const { manageComplianceHint } = useMoneyPermissions();\n const query = useCase(tenantId);\n const decide = useDecideCase(tenantId);\n const [denying, setDenying] = useState(false);\n const data = query.data;\n const mode = data ? barMode(data.status) : null;\n const wasDeciding = useRef(false);\n\n useEffect(() => {\n if (mode === \"decide\") wasDeciding.current = true;\n else if (wasDeciding.current) onClose();\n }, [mode, onClose]);\n\n async function approve() {\n const ok = await confirm({\n title: `Approve ${business}?`,\n description: \"Everyone listed is marked verified.\",\n confirmLabel: \"Approve\",\n });\n\n if (!ok) return;\n\n decide.mutate(\n { decision: \"APPROVE\" },\n {\n onSuccess: () => toast({ title: `${business} approved` }),\n onError: (e) =>\n toast({ title: caseErrorText(e, \"decide\"), variant: \"destructive\" }),\n }\n );\n }\n\n const files = data?.documents ?? [];\n\n return (\n <>\n <FormDialog\n open={!denying}\n onClose={onClose}\n title={business}\n description=\"What the merchant sent\"\n size=\"lg\"\n footer={\n <div className={styles.footer}>\n <Button variant=\"secondary\" onClick={onClose}>\n Close\n </Button>\n {mode === \"decide\" && (\n <>\n <Button variant=\"secondary\" onClick={() => setDenying(true)}>\n Deny\n </Button>\n <Button\n loading={decide.isPending}\n onClick={() => void approve()}\n >\n Approve\n </Button>\n </>\n )}\n </div>\n }\n >\n {query.isLoading && <AdmLoading label=\"Loading what was sent…\" />}\n {(query.isError || (!query.isLoading && !data)) && (\n <ErrorBanner>{caseErrorText(query.error, \"load\")}</ErrorBanner>\n )}\n {data && files.length === 0 && (\n <p className={viewer.note}>No photos or documents sent.</p>\n )}\n {data &&\n files.map((d) => (\n <div key={d.id} className={styles.stack}>\n <span className={viewer.note}>\n {documentWord(d)} · {ownerName(d, data.people)}\n </span>\n <DocumentFile tenantId={tenantId} document={d} />\n </div>\n ))}\n {manageComplianceHint && (\n <span className=\"adm-caption\">{manageComplianceHint}</span>\n )}\n </FormDialog>\n <DenyDialog\n tenantId={tenantId}\n business={business}\n open={denying}\n onClose={() => setDenying(false)}\n />\n </>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,7 @@
1
1
  "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import Link from "next/link";
4
+ import { useState } from "react";
4
5
  import { useQuery } from "@tanstack/react-query";
5
6
  import { Button, TableRow, Th } from "@withpotter/ui-kit";
6
7
  import { adminCaseApi } from "@withpotter/lib/admin-case-api";
@@ -9,6 +10,7 @@ import list from "../_ui/list-card.module.css";
9
10
  import rows from "../accounts/rows.module.css";
10
11
  import { flagWords, waited } from "../tenants/[id]/verification/case-words";
11
12
  import { caseErrorText } from "../tenants/[id]/verification/case-rules";
13
+ import { PreviewDialog } from "./preview-dialog";
12
14
  const WAITING_LIST_KEY = [
13
15
  "platform-admin",
14
16
  "compliance",
@@ -23,45 +25,67 @@ function WaitingCases() {
23
25
  retry: false
24
26
  });
25
27
  const items = data?.items ?? [];
26
- return /* @__PURE__ */ jsx(
27
- ListCard,
28
- {
29
- title: "Businesses waiting for review",
30
- count: data?.total,
31
- columns: COLUMNS,
32
- minWidth: 720,
33
- isLoading,
34
- isError,
35
- onRetry: () => void refetch(),
36
- errorTitle: caseErrorText(error, "load"),
37
- isEmpty: items.length === 0,
38
- emptyTitle: "No business is waiting for review.",
39
- head: /* @__PURE__ */ jsxs("tr", { children: [
40
- /* @__PURE__ */ jsx(Th, { children: "Business" }),
41
- /* @__PURE__ */ jsx(Th, { children: "People" }),
42
- /* @__PURE__ */ jsx(Th, { children: "Waiting" }),
43
- /* @__PURE__ */ jsx(Th, { children: "Flags" }),
44
- /* @__PURE__ */ jsx(Th, { align: "right", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Actions" }) })
45
- ] }),
46
- children: items.map((c) => {
47
- const flags = flagWords(c.flags);
48
- return /* @__PURE__ */ jsxs(TableRow, { children: [
49
- /* @__PURE__ */ jsx("td", { className: list.nowrap, children: /* @__PURE__ */ jsx(
50
- Link,
51
- {
52
- href: `/admin/tenants/${c.tenantId}?tab=verification`,
53
- className: "text-brand-500 hover:underline",
54
- children: c.businessName ?? "Unnamed business"
55
- }
56
- ) }),
57
- /* @__PURE__ */ jsx("td", { className: list.muted, children: c.peopleCount }),
58
- /* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: c.waitingSince ? waited(c.waitingSince) : EMPTY }),
59
- /* @__PURE__ */ jsx("td", { className: list.muted, children: flags.length ? flags.join(" \xB7 ") : EMPTY }),
60
- /* @__PURE__ */ jsx("td", { className: rows.menuCell, children: /* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", asChild: true, children: /* @__PURE__ */ jsx(Link, { href: `/admin/tenants/${c.tenantId}?tab=verification`, children: "Review" }) }) })
61
- ] }, c.tenantId);
62
- })
63
- }
64
- );
28
+ const [previewing, setPreviewing] = useState(null);
29
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
30
+ /* @__PURE__ */ jsx(
31
+ ListCard,
32
+ {
33
+ title: "Businesses waiting for review",
34
+ count: data?.total,
35
+ columns: COLUMNS,
36
+ minWidth: 720,
37
+ isLoading,
38
+ isError,
39
+ onRetry: () => void refetch(),
40
+ errorTitle: caseErrorText(error, "load"),
41
+ isEmpty: items.length === 0,
42
+ emptyTitle: "No business is waiting for review.",
43
+ head: /* @__PURE__ */ jsxs("tr", { children: [
44
+ /* @__PURE__ */ jsx(Th, { children: "Business" }),
45
+ /* @__PURE__ */ jsx(Th, { children: "People" }),
46
+ /* @__PURE__ */ jsx(Th, { children: "Waiting" }),
47
+ /* @__PURE__ */ jsx(Th, { children: "Flags" }),
48
+ /* @__PURE__ */ jsx(Th, { align: "right", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Actions" }) })
49
+ ] }),
50
+ children: items.map((c) => {
51
+ const flags = flagWords(c.flags);
52
+ return /* @__PURE__ */ jsxs(TableRow, { children: [
53
+ /* @__PURE__ */ jsx("td", { className: list.nowrap, children: /* @__PURE__ */ jsx(
54
+ Link,
55
+ {
56
+ href: `/admin/tenants/${c.tenantId}?tab=verification`,
57
+ className: "text-brand-500 hover:underline",
58
+ children: c.businessName ?? "Unnamed business"
59
+ }
60
+ ) }),
61
+ /* @__PURE__ */ jsx("td", { className: list.muted, children: c.peopleCount }),
62
+ /* @__PURE__ */ jsx("td", { className: `${list.nowrap} ${list.muted}`, children: c.waitingSince ? waited(c.waitingSince) : EMPTY }),
63
+ /* @__PURE__ */ jsx("td", { className: list.muted, children: flags.length ? flags.join(" \xB7 ") : EMPTY }),
64
+ /* @__PURE__ */ jsx("td", { className: rows.menuCell, children: /* @__PURE__ */ jsx(
65
+ Button,
66
+ {
67
+ size: "sm",
68
+ variant: "secondary",
69
+ onClick: () => setPreviewing({
70
+ id: c.tenantId,
71
+ name: c.businessName ?? "Unnamed business"
72
+ }),
73
+ children: "Preview"
74
+ }
75
+ ) })
76
+ ] }, c.tenantId);
77
+ })
78
+ }
79
+ ),
80
+ previewing && /* @__PURE__ */ jsx(
81
+ PreviewDialog,
82
+ {
83
+ tenantId: previewing.id,
84
+ business: previewing.name,
85
+ onClose: () => setPreviewing(null)
86
+ }
87
+ )
88
+ ] });
65
89
  }
66
90
  export {
67
91
  WAITING_LIST_KEY,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/verification/waiting-cases.tsx"],"sourcesContent":["'use client';\n\nimport Link from 'next/link';\nimport { useQuery } from '@tanstack/react-query';\nimport { Button, TableRow, Th } from '@withpotter/ui-kit';\nimport { adminCaseApi } from '@withpotter/lib/admin-case-api';\nimport { EMPTY, ListCard } from '../_ui/list-card';\nimport list from '../_ui/list-card.module.css';\nimport rows from '../accounts/rows.module.css';\nimport { flagWords, waited } from '../tenants/[id]/verification/case-words';\nimport { caseErrorText } from '../tenants/[id]/verification/case-rules';\n\nexport const WAITING_LIST_KEY = [\n 'platform-admin',\n 'compliance',\n 'cases',\n 'waiting',\n];\n\nconst COLUMNS = 5;\n\n/**\n * Businesses whose checks are back and wait for a decision, oldest first.\n * Each row opens the business's Verification tab, where the admin sees what\n * the merchant sent before Approve or Deny: there is no decision from the list.\n */\nexport function WaitingCases() {\n const { data, isLoading, isError, error, refetch } = useQuery({\n queryKey: WAITING_LIST_KEY,\n queryFn: () => adminCaseApi.list({ status: 'WAITING_REVIEW', limit: 100 }),\n retry: false,\n });\n const items = data?.items ?? [];\n\n return (\n <ListCard\n title=\"Businesses waiting for review\"\n count={data?.total}\n columns={COLUMNS}\n minWidth={720}\n isLoading={isLoading}\n isError={isError}\n onRetry={() => void refetch()}\n errorTitle={caseErrorText(error, 'load')}\n isEmpty={items.length === 0}\n emptyTitle=\"No business is waiting for review.\"\n head={\n <tr>\n <Th>Business</Th>\n <Th>People</Th>\n <Th>Waiting</Th>\n <Th>Flags</Th>\n <Th align=\"right\">\n <span className=\"sr-only\">Actions</span>\n </Th>\n </tr>\n }\n >\n {items.map((c) => {\n const flags = flagWords(c.flags);\n\n return (\n <TableRow key={c.tenantId}>\n <td className={list.nowrap}>\n <Link\n href={`/admin/tenants/${c.tenantId}?tab=verification`}\n className=\"text-brand-500 hover:underline\"\n >\n {c.businessName ?? 'Unnamed business'}\n </Link>\n </td>\n <td className={list.muted}>{c.peopleCount}</td>\n <td className={`${list.nowrap} ${list.muted}`}>\n {c.waitingSince ? waited(c.waitingSince) : EMPTY}\n </td>\n <td className={list.muted}>\n {flags.length ? flags.join(' · ') : EMPTY}\n </td>\n <td className={rows.menuCell}>\n <Button size=\"sm\" variant=\"secondary\" asChild>\n <Link href={`/admin/tenants/${c.tenantId}?tab=verification`}>\n Review\n </Link>\n </Button>\n </td>\n </TableRow>\n );\n })}\n </ListCard>\n );\n}\n"],"mappings":";AA+CQ,SACE,KADF;AA7CR,OAAO,UAAU;AACjB,SAAS,gBAAgB;AACzB,SAAS,QAAQ,UAAU,UAAU;AACrC,SAAS,oBAAoB;AAC7B,SAAS,OAAO,gBAAgB;AAChC,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,SAAS,WAAW,cAAc;AAClC,SAAS,qBAAqB;AAEvB,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,UAAU;AAOT,SAAS,eAAe;AAC7B,QAAM,EAAE,MAAM,WAAW,SAAS,OAAO,QAAQ,IAAI,SAAS;AAAA,IAC5D,UAAU;AAAA,IACV,SAAS,MAAM,aAAa,KAAK,EAAE,QAAQ,kBAAkB,OAAO,IAAI,CAAC;AAAA,IACzE,OAAO;AAAA,EACT,CAAC;AACD,QAAM,QAAQ,MAAM,SAAS,CAAC;AAE9B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,OAAO,MAAM;AAAA,MACb,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,SAAS,MAAM,KAAK,QAAQ;AAAA,MAC5B,YAAY,cAAc,OAAO,MAAM;AAAA,MACvC,SAAS,MAAM,WAAW;AAAA,MAC1B,YAAW;AAAA,MACX,MACE,qBAAC,QACC;AAAA,4BAAC,MAAG,sBAAQ;AAAA,QACZ,oBAAC,MAAG,oBAAM;AAAA,QACV,oBAAC,MAAG,qBAAO;AAAA,QACX,oBAAC,MAAG,mBAAK;AAAA,QACT,oBAAC,MAAG,OAAM,SACR,8BAAC,UAAK,WAAU,WAAU,qBAAO,GACnC;AAAA,SACF;AAAA,MAGD,gBAAM,IAAI,CAAC,MAAM;AAChB,cAAM,QAAQ,UAAU,EAAE,KAAK;AAE/B,eACE,qBAAC,YACC;AAAA,8BAAC,QAAG,WAAW,KAAK,QAClB;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,kBAAkB,EAAE,QAAQ;AAAA,cAClC,WAAU;AAAA,cAET,YAAE,gBAAgB;AAAA;AAAA,UACrB,GACF;AAAA,UACA,oBAAC,QAAG,WAAW,KAAK,OAAQ,YAAE,aAAY;AAAA,UAC1C,oBAAC,QAAG,WAAW,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,IACxC,YAAE,eAAe,OAAO,EAAE,YAAY,IAAI,OAC7C;AAAA,UACA,oBAAC,QAAG,WAAW,KAAK,OACjB,gBAAM,SAAS,MAAM,KAAK,QAAK,IAAI,OACtC;AAAA,UACA,oBAAC,QAAG,WAAW,KAAK,UAClB,8BAAC,UAAO,MAAK,MAAK,SAAQ,aAAY,SAAO,MAC3C,8BAAC,QAAK,MAAM,kBAAkB,EAAE,QAAQ,qBAAqB,oBAE7D,GACF,GACF;AAAA,aAtBa,EAAE,QAuBjB;AAAA,MAEJ,CAAC;AAAA;AAAA,EACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/admin/verification/waiting-cases.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"next/link\";\nimport { useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { Button, TableRow, Th } from \"@withpotter/ui-kit\";\nimport { adminCaseApi } from \"@withpotter/lib/admin-case-api\";\nimport { EMPTY, ListCard } from \"../_ui/list-card\";\nimport list from \"../_ui/list-card.module.css\";\nimport rows from \"../accounts/rows.module.css\";\nimport { flagWords, waited } from \"../tenants/[id]/verification/case-words\";\nimport { caseErrorText } from \"../tenants/[id]/verification/case-rules\";\nimport { PreviewDialog } from \"./preview-dialog\";\n\nexport const WAITING_LIST_KEY = [\n \"platform-admin\",\n \"compliance\",\n \"cases\",\n \"waiting\",\n];\n\nconst COLUMNS = 5;\n\n/**\n * Businesses whose checks are back and wait for a decision, oldest first.\n * Preview opens a popup with what the merchant sent and Approve / Deny; the\n * business name opens its full Verification tab.\n */\nexport function WaitingCases() {\n const { data, isLoading, isError, error, refetch } = useQuery({\n queryKey: WAITING_LIST_KEY,\n queryFn: () => adminCaseApi.list({ status: \"WAITING_REVIEW\", limit: 100 }),\n retry: false,\n });\n const items = data?.items ?? [];\n const [previewing, setPreviewing] = useState<{\n id: string;\n name: string;\n } | null>(null);\n\n return (\n <>\n <ListCard\n title=\"Businesses waiting for review\"\n count={data?.total}\n columns={COLUMNS}\n minWidth={720}\n isLoading={isLoading}\n isError={isError}\n onRetry={() => void refetch()}\n errorTitle={caseErrorText(error, \"load\")}\n isEmpty={items.length === 0}\n emptyTitle=\"No business is waiting for review.\"\n head={\n <tr>\n <Th>Business</Th>\n <Th>People</Th>\n <Th>Waiting</Th>\n <Th>Flags</Th>\n <Th align=\"right\">\n <span className=\"sr-only\">Actions</span>\n </Th>\n </tr>\n }\n >\n {items.map((c) => {\n const flags = flagWords(c.flags);\n\n return (\n <TableRow key={c.tenantId}>\n <td className={list.nowrap}>\n <Link\n href={`/admin/tenants/${c.tenantId}?tab=verification`}\n className=\"text-brand-500 hover:underline\"\n >\n {c.businessName ?? \"Unnamed business\"}\n </Link>\n </td>\n <td className={list.muted}>{c.peopleCount}</td>\n <td className={`${list.nowrap} ${list.muted}`}>\n {c.waitingSince ? waited(c.waitingSince) : EMPTY}\n </td>\n <td className={list.muted}>\n {flags.length ? flags.join(\" · \") : EMPTY}\n </td>\n <td className={rows.menuCell}>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() =>\n setPreviewing({\n id: c.tenantId,\n name: c.businessName ?? \"Unnamed business\",\n })\n }\n >\n Preview\n </Button>\n </td>\n </TableRow>\n );\n })}\n </ListCard>\n {previewing && (\n <PreviewDialog\n tenantId={previewing.id}\n business={previewing.name}\n onClose={() => setPreviewing(null)}\n />\n )}\n </>\n );\n}\n"],"mappings":";AAyCI,mBAcQ,KADF,YAbN;AAvCJ,OAAO,UAAU;AACjB,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAS,QAAQ,UAAU,UAAU;AACrC,SAAS,oBAAoB;AAC7B,SAAS,OAAO,gBAAgB;AAChC,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,SAAS,WAAW,cAAc;AAClC,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAEvB,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,UAAU;AAOT,SAAS,eAAe;AAC7B,QAAM,EAAE,MAAM,WAAW,SAAS,OAAO,QAAQ,IAAI,SAAS;AAAA,IAC5D,UAAU;AAAA,IACV,SAAS,MAAM,aAAa,KAAK,EAAE,QAAQ,kBAAkB,OAAO,IAAI,CAAC;AAAA,IACzE,OAAO;AAAA,EACT,CAAC;AACD,QAAM,QAAQ,MAAM,SAAS,CAAC;AAC9B,QAAM,CAAC,YAAY,aAAa,IAAI,SAG1B,IAAI;AAEd,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,OAAO,MAAM;AAAA,QACb,SAAS;AAAA,QACT,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,SAAS,MAAM,KAAK,QAAQ;AAAA,QAC5B,YAAY,cAAc,OAAO,MAAM;AAAA,QACvC,SAAS,MAAM,WAAW;AAAA,QAC1B,YAAW;AAAA,QACX,MACE,qBAAC,QACC;AAAA,8BAAC,MAAG,sBAAQ;AAAA,UACZ,oBAAC,MAAG,oBAAM;AAAA,UACV,oBAAC,MAAG,qBAAO;AAAA,UACX,oBAAC,MAAG,mBAAK;AAAA,UACT,oBAAC,MAAG,OAAM,SACR,8BAAC,UAAK,WAAU,WAAU,qBAAO,GACnC;AAAA,WACF;AAAA,QAGD,gBAAM,IAAI,CAAC,MAAM;AAChB,gBAAM,QAAQ,UAAU,EAAE,KAAK;AAE/B,iBACE,qBAAC,YACC;AAAA,gCAAC,QAAG,WAAW,KAAK,QAClB;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM,kBAAkB,EAAE,QAAQ;AAAA,gBAClC,WAAU;AAAA,gBAET,YAAE,gBAAgB;AAAA;AAAA,YACrB,GACF;AAAA,YACA,oBAAC,QAAG,WAAW,KAAK,OAAQ,YAAE,aAAY;AAAA,YAC1C,oBAAC,QAAG,WAAW,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,IACxC,YAAE,eAAe,OAAO,EAAE,YAAY,IAAI,OAC7C;AAAA,YACA,oBAAC,QAAG,WAAW,KAAK,OACjB,gBAAM,SAAS,MAAM,KAAK,QAAK,IAAI,OACtC;AAAA,YACA,oBAAC,QAAG,WAAW,KAAK,UAClB;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAQ;AAAA,gBACR,SAAS,MACP,cAAc;AAAA,kBACZ,IAAI,EAAE;AAAA,kBACN,MAAM,EAAE,gBAAgB;AAAA,gBAC1B,CAAC;AAAA,gBAEJ;AAAA;AAAA,YAED,GACF;AAAA,eA7Ba,EAAE,QA8BjB;AAAA,QAEJ,CAAC;AAAA;AAAA,IACH;AAAA,IACC,cACC;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,WAAW;AAAA,QACrB,UAAU,WAAW;AAAA,QACrB,SAAS,MAAM,cAAc,IAAI;AAAA;AAAA,IACnC;AAAA,KAEJ;AAEJ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withpotter/pages-admin",
3
- "version": "0.13.0-next.61",
3
+ "version": "0.13.0-next.62",
4
4
  "description": "Box console platform-admin routes: overview, revenue, accounts, tenants, admins, roles, audit.",
5
5
  "license": "UNLICENSED",
6
6
  "sideEffects": false,
@@ -31,9 +31,9 @@
31
31
  "dependencies": {
32
32
  "@radix-ui/react-popover": "^1.1.23",
33
33
  "@tanstack/react-query": "^5.90.20",
34
- "@withpotter/lib": "^0.13.0-next.61",
35
- "@withpotter/platform-admin": "^0.13.0-next.61",
36
- "@withpotter/ui-kit": "^0.13.0-next.61",
34
+ "@withpotter/lib": "^0.13.0-next.62",
35
+ "@withpotter/platform-admin": "^0.13.0-next.62",
36
+ "@withpotter/ui-kit": "^0.13.0-next.62",
37
37
  "lucide-react": "^0.562.0",
38
38
  "motion": "^12.42.2"
39
39
  },