@burdenoff/microfe-proserviceworld 2026.1013.1 → 2026.1015.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/generated/wspace-types.d.ts +98750 -26838
  2. package/dist/generated/wspace-types.d.ts.map +1 -1
  3. package/dist/proserviceworld/ProServiceWorldRoot.d.ts.map +1 -1
  4. package/dist/proserviceworld/ProServiceWorldRoot.js +6 -0
  5. package/dist/proserviceworld/ProServiceWorldRoot.js.map +1 -1
  6. package/dist/proserviceworld/ProServiceWorldRoutes.d.ts.map +1 -1
  7. package/dist/proserviceworld/ProServiceWorldRoutes.js +42 -35
  8. package/dist/proserviceworld/ProServiceWorldRoutes.js.map +1 -1
  9. package/dist/proserviceworld/components/CredentialDirectory.d.ts +3 -0
  10. package/dist/proserviceworld/components/CredentialDirectory.d.ts.map +1 -0
  11. package/dist/proserviceworld/components/CredentialDirectory.js +253 -0
  12. package/dist/proserviceworld/components/CredentialDirectory.js.map +1 -0
  13. package/dist/proserviceworld/components/CredentialEvidencePicker.d.ts +9 -0
  14. package/dist/proserviceworld/components/CredentialEvidencePicker.d.ts.map +1 -0
  15. package/dist/proserviceworld/components/CredentialEvidencePicker.js +161 -0
  16. package/dist/proserviceworld/components/CredentialEvidencePicker.js.map +1 -0
  17. package/dist/proserviceworld/components/CredentialRecordForm.d.ts +24 -0
  18. package/dist/proserviceworld/components/CredentialRecordForm.d.ts.map +1 -0
  19. package/dist/proserviceworld/components/CredentialRecordForm.js +251 -0
  20. package/dist/proserviceworld/components/CredentialRecordForm.js.map +1 -0
  21. package/dist/proserviceworld/components/CredentialReferencePicker.d.ts +22 -0
  22. package/dist/proserviceworld/components/CredentialReferencePicker.d.ts.map +1 -0
  23. package/dist/proserviceworld/components/CredentialReferencePicker.js +122 -0
  24. package/dist/proserviceworld/components/CredentialReferencePicker.js.map +1 -0
  25. package/dist/proserviceworld/components/CredentialReminderPanel.d.ts +5 -0
  26. package/dist/proserviceworld/components/CredentialReminderPanel.d.ts.map +1 -0
  27. package/dist/proserviceworld/components/CredentialReminderPanel.js +141 -0
  28. package/dist/proserviceworld/components/CredentialReminderPanel.js.map +1 -0
  29. package/dist/proserviceworld/components/credentialFormDefinitions.d.ts +4 -0
  30. package/dist/proserviceworld/components/credentialFormDefinitions.d.ts.map +1 -0
  31. package/dist/proserviceworld/components/credentialFormDefinitions.js +344 -0
  32. package/dist/proserviceworld/components/credentialFormDefinitions.js.map +1 -0
  33. package/dist/proserviceworld/hooks/credentialWrites.d.ts +16 -0
  34. package/dist/proserviceworld/hooks/credentialWrites.d.ts.map +1 -0
  35. package/dist/proserviceworld/hooks/credentialWrites.js +38 -0
  36. package/dist/proserviceworld/hooks/credentialWrites.js.map +1 -0
  37. package/dist/proserviceworld/hooks/usePractitionerCredentials.d.ts +41 -0
  38. package/dist/proserviceworld/hooks/usePractitionerCredentials.d.ts.map +1 -0
  39. package/dist/proserviceworld/hooks/usePractitionerCredentials.js +105 -0
  40. package/dist/proserviceworld/hooks/usePractitionerCredentials.js.map +1 -0
  41. package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts +9 -0
  42. package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts.map +1 -1
  43. package/dist/proserviceworld/hooks/useProServiceWorldApi.js +24 -15
  44. package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -1
  45. package/dist/proserviceworld/pages/CompliancePage.d.ts.map +1 -1
  46. package/dist/proserviceworld/pages/CompliancePage.js +136 -118
  47. package/dist/proserviceworld/pages/CompliancePage.js.map +1 -1
  48. package/dist/proserviceworld/pages/ConflictsPage.d.ts.map +1 -1
  49. package/dist/proserviceworld/pages/ConflictsPage.js +87 -71
  50. package/dist/proserviceworld/pages/ConflictsPage.js.map +1 -1
  51. package/dist/proserviceworld/pages/DocumentsPage.d.ts.map +1 -1
  52. package/dist/proserviceworld/pages/DocumentsPage.js +104 -86
  53. package/dist/proserviceworld/pages/DocumentsPage.js.map +1 -1
  54. package/dist/proserviceworld/pages/InvoicesPage.d.ts.map +1 -1
  55. package/dist/proserviceworld/pages/InvoicesPage.js +122 -104
  56. package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -1
  57. package/dist/proserviceworld/pages/PractitionerCredentialsPage.d.ts +2 -0
  58. package/dist/proserviceworld/pages/PractitionerCredentialsPage.d.ts.map +1 -0
  59. package/dist/proserviceworld/pages/PractitionerCredentialsPage.js +268 -0
  60. package/dist/proserviceworld/pages/PractitionerCredentialsPage.js.map +1 -0
  61. package/dist/proserviceworld/pages/TimePage.d.ts.map +1 -1
  62. package/dist/proserviceworld/pages/TimePage.js +132 -114
  63. package/dist/proserviceworld/pages/TimePage.js.map +1 -1
  64. package/dist/proserviceworld/pages/TrustPage.d.ts.map +1 -1
  65. package/dist/proserviceworld/pages/TrustPage.js +226 -207
  66. package/dist/proserviceworld/pages/TrustPage.js.map +1 -1
  67. package/dist/proserviceworld/utils/credentialSourceLink.d.ts +3 -0
  68. package/dist/proserviceworld/utils/credentialSourceLink.d.ts.map +1 -0
  69. package/dist/proserviceworld/utils/credentialSourceLink.js +17 -0
  70. package/dist/proserviceworld/utils/credentialSourceLink.js.map +1 -0
  71. package/package.json +21 -5
@@ -0,0 +1,268 @@
1
+ import { useProServiceWorld as e } from "../providers/ProServiceWorldProvider.js";
2
+ import { Banner as t, Empty as n, ErrorState as r, LoadingBlock as i, PageHeader as a, SectionCard as o, TableWrap as s, Td as c, Th as l, humanize as u } from "../components/ui.js";
3
+ import { CredentialReminderPanel as d } from "../components/CredentialReminderPanel.js";
4
+ import { useCredentialReviews as f, usePractitionerCredentials as p } from "../hooks/usePractitionerCredentials.js";
5
+ import { credentialSourceLink as m } from "../utils/credentialSourceLink.js";
6
+ import { CredentialDirectory as h } from "../components/CredentialDirectory.js";
7
+ import { CredentialRecordForm as g } from "../components/CredentialRecordForm.js";
8
+ import { CREDENTIAL_FORMS as _ } from "../components/credentialFormDefinitions.js";
9
+ import { useState as v } from "react";
10
+ import { BadgeCheck as y, RefreshCw as b } from "lucide-react";
11
+ import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
12
+ import { Button as w } from "@burdenoff/fe-libs/ui";
13
+ //#region src/proserviceworld/pages/PractitionerCredentialsPage.tsx
14
+ function T() {
15
+ let { workspaceId: T, tenantId: E, currentUser: D } = e(), O = JSON.stringify([
16
+ E,
17
+ T,
18
+ D?.id
19
+ ]), [k, A] = v({
20
+ scope: O,
21
+ offset: 0
22
+ }), [j, M] = v(null), N = k.scope === O ? k.offset : 0, P = p(N), F = P.data?.items ?? [], I = j?.scope === O ? F.find((e) => e.id === j.id) : void 0, [L, R] = v(null), z = L?.scope === O && L.credentialId === I?.id ? L.offset : 0, B = f(I?.id, z, j?.scope === O ? j.asOf : void 0), V = B.data?.items ?? [], H = !!(E && T && D?.id), [U, W] = v(0), [G, K] = v(null), q = _[U] ?? _[0];
23
+ return /* @__PURE__ */ C("div", {
24
+ className: "space-y-6",
25
+ children: [
26
+ /* @__PURE__ */ S(a, {
27
+ title: "Practitioner credentials",
28
+ subtitle: "Issuers, jurisdictions and source observations recorded by your firm.",
29
+ icon: /* @__PURE__ */ S(y, { className: "h-6 w-6" }),
30
+ actions: /* @__PURE__ */ C(w, {
31
+ variant: "outline",
32
+ disabled: !H || P.isFetching,
33
+ onClick: () => void P.refetch(),
34
+ children: [/* @__PURE__ */ S(b, { className: "mr-2 h-4 w-4" }), "Refresh"]
35
+ })
36
+ }),
37
+ /* @__PURE__ */ S(t, {
38
+ tone: "info",
39
+ children: "Recorded evidence and source reviews do not certify legal authority to practise."
40
+ }),
41
+ H && /* @__PURE__ */ C(x, { children: [
42
+ /* @__PURE__ */ S(h, {}, `directory:${O}`),
43
+ /* @__PURE__ */ S(d, { preparedId: G?.scope === O ? G.id : void 0 }, `reminder:${O}:${G?.scope === O ? G.id : ""}`),
44
+ /* @__PURE__ */ C("label", {
45
+ className: "block text-sm font-medium",
46
+ children: ["Record an action", /* @__PURE__ */ S("select", {
47
+ className: "mt-1 block w-full rounded border border-border bg-bg-surface p-2",
48
+ value: U,
49
+ onChange: (e) => W(Number(e.target.value)),
50
+ children: _.map((e, t) => /* @__PURE__ */ S("option", {
51
+ value: t,
52
+ children: e.title
53
+ }, e.operation))
54
+ })]
55
+ }),
56
+ q && /* @__PURE__ */ S(g, {
57
+ scope: O,
58
+ definition: q,
59
+ onPreparedReminder: (e) => K({
60
+ scope: O,
61
+ id: e
62
+ })
63
+ }, `${O}:${q.operation}`)
64
+ ] }),
65
+ H ? P.isLoading ? /* @__PURE__ */ S(i, {}) : P.error ? /* @__PURE__ */ S(r, {
66
+ error: P.error,
67
+ onRetry: () => void P.refetch()
68
+ }) : F.length === 0 ? /* @__PURE__ */ S(n, {
69
+ title: "No credential records",
70
+ description: "This firm has no recorded practitioner credentials on this page."
71
+ }) : /* @__PURE__ */ C(o, {
72
+ title: `${P.data?.totalCount ?? F.length} recorded credentials`,
73
+ children: [/* @__PURE__ */ C(s, { children: [/* @__PURE__ */ S("thead", { children: /* @__PURE__ */ C("tr", { children: [
74
+ /* @__PURE__ */ S(l, { children: "Credential" }),
75
+ /* @__PURE__ */ S(l, { children: "Jurisdiction" }),
76
+ /* @__PURE__ */ S(l, { children: "Practice scope" }),
77
+ /* @__PURE__ */ S(l, { children: "Recorded validity" }),
78
+ /* @__PURE__ */ S(l, { children: "Recorded expiry" }),
79
+ /* @__PURE__ */ S(l, { children: "Reviews" })
80
+ ] }) }), /* @__PURE__ */ S("tbody", { children: F.map((e) => /* @__PURE__ */ C("tr", { children: [
81
+ /* @__PURE__ */ C(c, { children: [e.identifier, /* @__PURE__ */ C("span", {
82
+ className: "block break-all text-xs",
83
+ children: [
84
+ "ID: ",
85
+ e.id,
86
+ " · Revision ",
87
+ e.revision
88
+ ]
89
+ })] }),
90
+ /* @__PURE__ */ S(c, { children: e.jurisdiction }),
91
+ /* @__PURE__ */ S(c, { children: e.practiceScope }),
92
+ /* @__PURE__ */ S(c, { children: u(e.validityKind) }),
93
+ /* @__PURE__ */ C(c, { children: [e.expiresAt ?? (e.validityKind === "NO_EXPIRY_REPORTED" ? "No expiry reported" : "Unknown"), /* @__PURE__ */ C("span", {
94
+ className: "block text-xs text-text-tertiary",
95
+ children: ["Source zone: ", e.sourceTimezone]
96
+ })] }),
97
+ /* @__PURE__ */ S(c, { children: /* @__PURE__ */ S(w, {
98
+ size: "sm",
99
+ variant: "outline",
100
+ onClick: () => M({
101
+ scope: O,
102
+ id: e.id,
103
+ asOf: (/* @__PURE__ */ new Date()).toISOString()
104
+ }),
105
+ children: "Status and history"
106
+ }) })
107
+ ] }, e.id)) })] }), /* @__PURE__ */ C("div", {
108
+ className: "mt-4 flex flex-wrap items-center justify-between gap-3",
109
+ children: [
110
+ /* @__PURE__ */ S(w, {
111
+ variant: "outline",
112
+ disabled: N === 0 || P.isFetching,
113
+ onClick: () => A({
114
+ scope: O,
115
+ offset: Math.max(0, N - 25)
116
+ }),
117
+ children: "Previous"
118
+ }),
119
+ /* @__PURE__ */ C("span", {
120
+ className: "text-sm text-text-secondary",
121
+ children: ["Page ", Math.floor(N / 25) + 1]
122
+ }),
123
+ /* @__PURE__ */ S(w, {
124
+ variant: "outline",
125
+ disabled: !P.data?.hasMore || P.isFetching,
126
+ onClick: () => A({
127
+ scope: O,
128
+ offset: N + 25
129
+ }),
130
+ children: "Next"
131
+ })
132
+ ]
133
+ })]
134
+ }) : /* @__PURE__ */ S(n, {
135
+ title: "Choose a workspace",
136
+ description: "Sign in and choose the firm workspace to view its credential records."
137
+ }),
138
+ I && /* @__PURE__ */ C(o, {
139
+ title: `Recorded status and history: ${I.identifier}`,
140
+ children: [
141
+ B.data?.readiness && /* @__PURE__ */ C("div", {
142
+ className: "mb-4 space-y-2",
143
+ children: [
144
+ /* @__PURE__ */ S("p", {
145
+ className: "font-semibold",
146
+ children: u(B.data.readiness.recordedState)
147
+ }),
148
+ /* @__PURE__ */ C("p", {
149
+ className: "text-sm",
150
+ children: [
151
+ "As of ",
152
+ B.data.readiness.asOf,
153
+ " · Credential revision",
154
+ " ",
155
+ B.data.readiness.revision
156
+ ]
157
+ }),
158
+ /* @__PURE__ */ C("p", { children: [
159
+ "Source observation: ",
160
+ u(B.data.readiness.observation),
161
+ " ·",
162
+ " ",
163
+ B.data.readiness.reviewIsForCurrentRevision ? "Review matches current recorded facts" : "Current facts need a source review"
164
+ ] }),
165
+ /* @__PURE__ */ S("p", {
166
+ className: "text-sm",
167
+ children: "Legal authorization is not certified. No automatic source-freshness interval is assumed."
168
+ }),
169
+ /* @__PURE__ */ S(w, {
170
+ variant: "outline",
171
+ disabled: B.isFetching,
172
+ onClick: () => M({
173
+ scope: O,
174
+ id: I.id,
175
+ asOf: (/* @__PURE__ */ new Date()).toISOString()
176
+ }),
177
+ children: "Refresh recorded status"
178
+ })
179
+ ]
180
+ }),
181
+ B.isLoading ? /* @__PURE__ */ S(i, {}) : B.error ? /* @__PURE__ */ S(r, {
182
+ error: B.error,
183
+ onRetry: () => void B.refetch()
184
+ }) : V.length === 0 ? /* @__PURE__ */ S("p", { children: "No source review has been recorded. Authority remains unknown." }) : /* @__PURE__ */ S("div", {
185
+ className: "space-y-4",
186
+ children: V.map((e) => {
187
+ let t = m(e.sourceUrl);
188
+ return /* @__PURE__ */ C("article", {
189
+ className: "min-w-0 rounded-xl border border-border p-4",
190
+ children: [
191
+ /* @__PURE__ */ S("h3", {
192
+ className: "font-semibold",
193
+ children: u(e.observation)
194
+ }),
195
+ /* @__PURE__ */ C("p", {
196
+ className: "text-sm text-text-secondary",
197
+ children: [
198
+ "Observed ",
199
+ e.checkedAt,
200
+ " · Revision ",
201
+ e.credentialRevision,
202
+ e.credentialRevision === I.revision ? "" : " · Previous credential facts"
203
+ ]
204
+ }),
205
+ /* @__PURE__ */ S("p", {
206
+ className: "mt-2 whitespace-pre-wrap break-words",
207
+ children: e.note
208
+ }),
209
+ t ? /* @__PURE__ */ C("a", {
210
+ href: t,
211
+ target: "_blank",
212
+ rel: "noopener noreferrer",
213
+ className: "mt-2 block break-all underline",
214
+ children: ["Source reference: ", new URL(t).hostname]
215
+ }) : /* @__PURE__ */ S("p", {
216
+ className: "mt-2 text-sm",
217
+ children: "Source reference unavailable."
218
+ }),
219
+ /* @__PURE__ */ C("p", {
220
+ className: "mt-2 break-all text-xs text-text-secondary",
221
+ children: ["Evidence version: ", e.evidenceVersionId]
222
+ }),
223
+ /* @__PURE__ */ C("p", {
224
+ className: "break-all text-xs text-text-secondary",
225
+ children: ["SHA-256: ", e.evidenceSha256]
226
+ })
227
+ ]
228
+ }, e.id);
229
+ })
230
+ }),
231
+ /* @__PURE__ */ C("div", {
232
+ className: "mt-4 flex flex-wrap items-center justify-between gap-3",
233
+ children: [
234
+ /* @__PURE__ */ S(w, {
235
+ variant: "outline",
236
+ disabled: z === 0 || B.isFetching,
237
+ onClick: () => R({
238
+ scope: O,
239
+ credentialId: I.id,
240
+ offset: Math.max(0, z - 25)
241
+ }),
242
+ children: "Previous reviews"
243
+ }),
244
+ /* @__PURE__ */ C("span", {
245
+ className: "text-sm text-text-secondary",
246
+ children: ["Review page ", Math.floor(z / 25) + 1]
247
+ }),
248
+ /* @__PURE__ */ S(w, {
249
+ variant: "outline",
250
+ disabled: !B.data?.hasMore || B.isFetching,
251
+ onClick: () => R({
252
+ scope: O,
253
+ credentialId: I.id,
254
+ offset: z + 25
255
+ }),
256
+ children: "Next reviews"
257
+ })
258
+ ]
259
+ })
260
+ ]
261
+ })
262
+ ]
263
+ });
264
+ }
265
+ //#endregion
266
+ export { T as PractitionerCredentialsPage };
267
+
268
+ //# sourceMappingURL=PractitionerCredentialsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PractitionerCredentialsPage.js","names":[],"sources":["../../../src/proserviceworld/pages/PractitionerCredentialsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { BadgeCheck, RefreshCw } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { CredentialReminderPanel } from '../components/CredentialReminderPanel';\nimport { CredentialDirectory } from '../components/CredentialDirectory';\nimport { CredentialRecordForm } from '../components/CredentialRecordForm';\nimport { CREDENTIAL_FORMS } from '../components/credentialFormDefinitions';\nimport { credentialSourceLink } from '../utils/credentialSourceLink';\nimport { useProServiceWorld } from '../providers/ProServiceWorldProvider';\nimport {\n usePractitionerCredentials,\n useCredentialReviews,\n} from '../hooks/usePractitionerCredentials';\nimport {\n Banner,\n Empty,\n ErrorState,\n LoadingBlock,\n PageHeader,\n SectionCard,\n TableWrap,\n Th,\n Td,\n humanize,\n} from '../components/ui';\n\nexport function PractitionerCredentialsPage() {\n const { workspaceId, tenantId, currentUser } = useProServiceWorld();\n const scope = JSON.stringify([tenantId, workspaceId, currentUser?.id]);\n const [page, setPage] = useState({ scope, offset: 0 });\n const [selection, setSelection] = useState<{ scope: string; id: string; asOf: string } | null>(\n null\n );\n const offset = page.scope === scope ? page.offset : 0;\n const query = usePractitionerCredentials(offset);\n const items = query.data?.items ?? [];\n const selected =\n selection?.scope === scope ? items.find((item) => item.id === selection.id) : undefined;\n const [reviewPage, setReviewPage] = useState<{\n scope: string;\n credentialId: string;\n offset: number;\n } | null>(null);\n const reviewOffset =\n reviewPage?.scope === scope && reviewPage.credentialId === selected?.id ? reviewPage.offset : 0;\n const history = useCredentialReviews(\n selected?.id,\n reviewOffset,\n selection?.scope === scope ? selection.asOf : undefined\n );\n const reviews = history.data?.items ?? [];\n const ready = Boolean(tenantId && workspaceId && currentUser?.id);\n const [formSelection, setFormSelection] = useState(0);\n const [preparedReminder, setPreparedReminder] = useState<{ scope: string; id: string } | null>(\n null\n );\n const definition = CREDENTIAL_FORMS[formSelection] ?? CREDENTIAL_FORMS[0];\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title=\"Practitioner credentials\"\n subtitle=\"Issuers, jurisdictions and source observations recorded by your firm.\"\n icon={<BadgeCheck className=\"h-6 w-6\" />}\n actions={\n <Button\n variant=\"outline\"\n disabled={!ready || query.isFetching}\n onClick={() => void query.refetch()}\n >\n <RefreshCw className=\"mr-2 h-4 w-4\" />\n Refresh\n </Button>\n }\n />\n <Banner tone=\"info\">\n Recorded evidence and source reviews do not certify legal authority to practise.\n </Banner>\n {ready && (\n <>\n <CredentialDirectory key={`directory:${scope}`} />\n <CredentialReminderPanel\n key={`reminder:${scope}:${preparedReminder?.scope === scope ? preparedReminder.id : ''}`}\n preparedId={preparedReminder?.scope === scope ? preparedReminder.id : undefined}\n />\n <label className=\"block text-sm font-medium\">\n Record an action\n <select\n className=\"mt-1 block w-full rounded border border-border bg-bg-surface p-2\"\n value={formSelection}\n onChange={(event) => setFormSelection(Number(event.target.value))}\n >\n {CREDENTIAL_FORMS.map((form, index) => (\n <option key={form.operation} value={index}>\n {form.title}\n </option>\n ))}\n </select>\n </label>\n {definition && (\n <CredentialRecordForm\n key={`${scope}:${definition.operation}`}\n scope={scope}\n definition={definition}\n onPreparedReminder={(id) => setPreparedReminder({ scope, id })}\n />\n )}\n </>\n )}\n {!ready ? (\n <Empty\n title=\"Choose a workspace\"\n description=\"Sign in and choose the firm workspace to view its credential records.\"\n />\n ) : query.isLoading ? (\n <LoadingBlock />\n ) : query.error ? (\n <ErrorState error={query.error} onRetry={() => void query.refetch()} />\n ) : items.length === 0 ? (\n <Empty\n title=\"No credential records\"\n description=\"This firm has no recorded practitioner credentials on this page.\"\n />\n ) : (\n <SectionCard title={`${query.data?.totalCount ?? items.length} recorded credentials`}>\n <TableWrap>\n <thead>\n <tr>\n <Th>Credential</Th>\n <Th>Jurisdiction</Th>\n <Th>Practice scope</Th>\n <Th>Recorded validity</Th>\n <Th>Recorded expiry</Th>\n <Th>Reviews</Th>\n </tr>\n </thead>\n <tbody>\n {items.map((item) => (\n <tr key={item.id}>\n <Td>\n {item.identifier}\n <span className=\"block break-all text-xs\">\n ID: {item.id} · Revision {item.revision}\n </span>\n </Td>\n <Td>{item.jurisdiction}</Td>\n <Td>{item.practiceScope}</Td>\n <Td>{humanize(item.validityKind)}</Td>\n <Td>\n {item.expiresAt ??\n (item.validityKind === 'NO_EXPIRY_REPORTED'\n ? 'No expiry reported'\n : 'Unknown')}\n <span className=\"block text-xs text-text-tertiary\">\n Source zone: {item.sourceTimezone}\n </span>\n </Td>\n <Td>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() =>\n setSelection({ scope, id: item.id, asOf: new Date().toISOString() })\n }\n >\n Status and history\n </Button>\n </Td>\n </tr>\n ))}\n </tbody>\n </TableWrap>\n <div className=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <Button\n variant=\"outline\"\n disabled={offset === 0 || query.isFetching}\n onClick={() => setPage({ scope, offset: Math.max(0, offset - 25) })}\n >\n Previous\n </Button>\n <span className=\"text-sm text-text-secondary\">Page {Math.floor(offset / 25) + 1}</span>\n <Button\n variant=\"outline\"\n disabled={!query.data?.hasMore || query.isFetching}\n onClick={() => setPage({ scope, offset: offset + 25 })}\n >\n Next\n </Button>\n </div>\n </SectionCard>\n )}\n {selected && (\n <SectionCard title={`Recorded status and history: ${selected.identifier}`}>\n {history.data?.readiness && (\n <div className=\"mb-4 space-y-2\">\n <p className=\"font-semibold\">{humanize(history.data.readiness.recordedState)}</p>\n <p className=\"text-sm\">\n As of {history.data.readiness.asOf} · Credential revision{' '}\n {history.data.readiness.revision}\n </p>\n <p>\n Source observation: {humanize(history.data.readiness.observation)} ·{' '}\n {history.data.readiness.reviewIsForCurrentRevision\n ? 'Review matches current recorded facts'\n : 'Current facts need a source review'}\n </p>\n <p className=\"text-sm\">\n Legal authorization is not certified. No automatic source-freshness interval is\n assumed.\n </p>\n <Button\n variant=\"outline\"\n disabled={history.isFetching}\n onClick={() =>\n setSelection({ scope, id: selected.id, asOf: new Date().toISOString() })\n }\n >\n Refresh recorded status\n </Button>\n </div>\n )}\n {history.isLoading ? (\n <LoadingBlock />\n ) : history.error ? (\n <ErrorState error={history.error} onRetry={() => void history.refetch()} />\n ) : reviews.length === 0 ? (\n <p>No source review has been recorded. Authority remains unknown.</p>\n ) : (\n <div className=\"space-y-4\">\n {reviews.map((review) => {\n const href = credentialSourceLink(review.sourceUrl);\n return (\n <article key={review.id} className=\"min-w-0 rounded-xl border border-border p-4\">\n <h3 className=\"font-semibold\">{humanize(review.observation)}</h3>\n <p className=\"text-sm text-text-secondary\">\n Observed {review.checkedAt} · Revision {review.credentialRevision}\n {review.credentialRevision !== selected.revision\n ? ' · Previous credential facts'\n : ''}\n </p>\n <p className=\"mt-2 whitespace-pre-wrap break-words\">{review.note}</p>\n {href ? (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-2 block break-all underline\"\n >\n Source reference: {new URL(href).hostname}\n </a>\n ) : (\n <p className=\"mt-2 text-sm\">Source reference unavailable.</p>\n )}\n <p className=\"mt-2 break-all text-xs text-text-secondary\">\n Evidence version: {review.evidenceVersionId}\n </p>\n <p className=\"break-all text-xs text-text-secondary\">\n SHA-256: {review.evidenceSha256}\n </p>\n </article>\n );\n })}\n </div>\n )}\n <div className=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <Button\n variant=\"outline\"\n disabled={reviewOffset === 0 || history.isFetching}\n onClick={() =>\n setReviewPage({\n scope,\n credentialId: selected.id,\n offset: Math.max(0, reviewOffset - 25),\n })\n }\n >\n Previous reviews\n </Button>\n <span className=\"text-sm text-text-secondary\">\n Review page {Math.floor(reviewOffset / 25) + 1}\n </span>\n <Button\n variant=\"outline\"\n disabled={!history.data?.hasMore || history.isFetching}\n onClick={() =>\n setReviewPage({ scope, credentialId: selected.id, offset: reviewOffset + 25 })\n }\n >\n Next reviews\n </Button>\n </div>\n </SectionCard>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TimePage.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/pages/TimePage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAmDhC,eAAO,MAAM,QAAQ,EAAE,EAuKtB,CAAC"}
1
+ {"version":3,"file":"TimePage.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/pages/TimePage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA6DhC,eAAO,MAAM,QAAQ,EAAE,EA8LtB,CAAC"}