@burdenoff/microfe-proserviceworld 2026.1013.1 → 2026.1014.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.
- package/dist/generated/wspace-types.d.ts +98750 -26838
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/proserviceworld/ProServiceWorldRoot.d.ts.map +1 -1
- package/dist/proserviceworld/ProServiceWorldRoot.js +6 -0
- package/dist/proserviceworld/ProServiceWorldRoot.js.map +1 -1
- package/dist/proserviceworld/ProServiceWorldRoutes.d.ts.map +1 -1
- package/dist/proserviceworld/ProServiceWorldRoutes.js +42 -35
- package/dist/proserviceworld/ProServiceWorldRoutes.js.map +1 -1
- package/dist/proserviceworld/components/CredentialDirectory.d.ts +3 -0
- package/dist/proserviceworld/components/CredentialDirectory.d.ts.map +1 -0
- package/dist/proserviceworld/components/CredentialDirectory.js +253 -0
- package/dist/proserviceworld/components/CredentialDirectory.js.map +1 -0
- package/dist/proserviceworld/components/CredentialEvidencePicker.d.ts +9 -0
- package/dist/proserviceworld/components/CredentialEvidencePicker.d.ts.map +1 -0
- package/dist/proserviceworld/components/CredentialEvidencePicker.js +161 -0
- package/dist/proserviceworld/components/CredentialEvidencePicker.js.map +1 -0
- package/dist/proserviceworld/components/CredentialRecordForm.d.ts +24 -0
- package/dist/proserviceworld/components/CredentialRecordForm.d.ts.map +1 -0
- package/dist/proserviceworld/components/CredentialRecordForm.js +251 -0
- package/dist/proserviceworld/components/CredentialRecordForm.js.map +1 -0
- package/dist/proserviceworld/components/CredentialReferencePicker.d.ts +22 -0
- package/dist/proserviceworld/components/CredentialReferencePicker.d.ts.map +1 -0
- package/dist/proserviceworld/components/CredentialReferencePicker.js +122 -0
- package/dist/proserviceworld/components/CredentialReferencePicker.js.map +1 -0
- package/dist/proserviceworld/components/CredentialReminderPanel.d.ts +5 -0
- package/dist/proserviceworld/components/CredentialReminderPanel.d.ts.map +1 -0
- package/dist/proserviceworld/components/CredentialReminderPanel.js +141 -0
- package/dist/proserviceworld/components/CredentialReminderPanel.js.map +1 -0
- package/dist/proserviceworld/components/credentialFormDefinitions.d.ts +4 -0
- package/dist/proserviceworld/components/credentialFormDefinitions.d.ts.map +1 -0
- package/dist/proserviceworld/components/credentialFormDefinitions.js +344 -0
- package/dist/proserviceworld/components/credentialFormDefinitions.js.map +1 -0
- package/dist/proserviceworld/hooks/credentialWrites.d.ts +16 -0
- package/dist/proserviceworld/hooks/credentialWrites.d.ts.map +1 -0
- package/dist/proserviceworld/hooks/credentialWrites.js +38 -0
- package/dist/proserviceworld/hooks/credentialWrites.js.map +1 -0
- package/dist/proserviceworld/hooks/usePractitionerCredentials.d.ts +41 -0
- package/dist/proserviceworld/hooks/usePractitionerCredentials.d.ts.map +1 -0
- package/dist/proserviceworld/hooks/usePractitionerCredentials.js +105 -0
- package/dist/proserviceworld/hooks/usePractitionerCredentials.js.map +1 -0
- package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts +1 -0
- package/dist/proserviceworld/hooks/useProServiceWorldApi.d.ts.map +1 -1
- package/dist/proserviceworld/hooks/useProServiceWorldApi.js +3 -2
- package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -1
- package/dist/proserviceworld/pages/PractitionerCredentialsPage.d.ts +2 -0
- package/dist/proserviceworld/pages/PractitionerCredentialsPage.d.ts.map +1 -0
- package/dist/proserviceworld/pages/PractitionerCredentialsPage.js +268 -0
- package/dist/proserviceworld/pages/PractitionerCredentialsPage.js.map +1 -0
- package/dist/proserviceworld/utils/credentialSourceLink.d.ts +3 -0
- package/dist/proserviceworld/utils/credentialSourceLink.d.ts.map +1 -0
- package/dist/proserviceworld/utils/credentialSourceLink.js +17 -0
- package/dist/proserviceworld/utils/credentialSourceLink.js.map +1 -0
- package/package.json +21 -5
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { useProServiceWorld as e } from "../providers/ProServiceWorldProvider.js";
|
|
2
|
+
import { pswQuery as t } from "../hooks/useProServiceWorldApi.js";
|
|
3
|
+
import { useState as n } from "react";
|
|
4
|
+
import { useQuery as r } from "@tanstack/react-query";
|
|
5
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
6
|
+
import { Button as o } from "@burdenoff/fe-libs/ui";
|
|
7
|
+
//#region src/proserviceworld/components/CredentialEvidencePicker.tsx
|
|
8
|
+
function s({ disabled: s, onChange: c }) {
|
|
9
|
+
let { tenantId: l, workspaceId: u, currentUser: d } = e(), [f, p] = n(0), [m, h] = n(0), [g, _] = n(""), [v, y] = n(""), b = !!(l && u && d?.id), x = r({
|
|
10
|
+
queryKey: [
|
|
11
|
+
"proserviceworld",
|
|
12
|
+
"credentialEvidenceFiles",
|
|
13
|
+
l,
|
|
14
|
+
u,
|
|
15
|
+
d?.id,
|
|
16
|
+
f
|
|
17
|
+
],
|
|
18
|
+
enabled: b,
|
|
19
|
+
queryFn: async () => (await t("query PswReadableEvidenceFiles($pagination: PaginationInput!) {\n getFiles(filter: { status: ACTIVE }, pagination: $pagination) {\n files { id name workspaceId status canRead } hasMore\n }\n }", { pagination: {
|
|
20
|
+
limit: 25,
|
|
21
|
+
offset: f
|
|
22
|
+
} })).getFiles
|
|
23
|
+
}), S = (x.data?.files ?? []).filter((e) => e.workspaceId === u && e.status === "ACTIVE" && e.canRead === !0), C = S.find((e) => e.id === g), w = r({
|
|
24
|
+
queryKey: [
|
|
25
|
+
"proserviceworld",
|
|
26
|
+
"credentialEvidenceVersions",
|
|
27
|
+
l,
|
|
28
|
+
u,
|
|
29
|
+
d?.id,
|
|
30
|
+
g,
|
|
31
|
+
m
|
|
32
|
+
],
|
|
33
|
+
enabled: b && !!C,
|
|
34
|
+
queryFn: async () => (await t("query PswReadableEvidenceVersions($fileId: ID!, $pagination: PaginationInput!) {\n getFileVersions(fileId: $fileId, pagination: $pagination) {\n versions { id fileId versionNumber versionLabel sha256Hash isCurrentVersion } hasMore\n }\n }", {
|
|
35
|
+
fileId: g,
|
|
36
|
+
pagination: {
|
|
37
|
+
limit: 25,
|
|
38
|
+
offset: m
|
|
39
|
+
}
|
|
40
|
+
})).getFileVersions
|
|
41
|
+
}), T = (w.data?.versions ?? []).filter((e) => e.fileId === g);
|
|
42
|
+
function E() {
|
|
43
|
+
y(""), c({
|
|
44
|
+
fileId: "",
|
|
45
|
+
versionId: "",
|
|
46
|
+
sha256: ""
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return /* @__PURE__ */ a("fieldset", {
|
|
50
|
+
className: "space-y-3 rounded border border-border p-3 sm:col-span-2",
|
|
51
|
+
disabled: s,
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ i("legend", {
|
|
54
|
+
className: "px-1 font-medium",
|
|
55
|
+
children: "Evidence from Files"
|
|
56
|
+
}),
|
|
57
|
+
/* @__PURE__ */ i("p", {
|
|
58
|
+
className: "text-sm",
|
|
59
|
+
children: "Choose a readable file and its exact version. Historical versions are allowed; evidence does not certify legal authority."
|
|
60
|
+
}),
|
|
61
|
+
/* @__PURE__ */ a("label", {
|
|
62
|
+
className: "block text-sm",
|
|
63
|
+
children: ["Evidence file", /* @__PURE__ */ a("select", {
|
|
64
|
+
className: "mt-1 w-full rounded border border-border bg-bg-surface p-2",
|
|
65
|
+
required: !0,
|
|
66
|
+
value: C ? g : "",
|
|
67
|
+
disabled: !b || x.isFetching || x.isError,
|
|
68
|
+
onChange: (e) => {
|
|
69
|
+
_(e.target.value), h(0), E();
|
|
70
|
+
},
|
|
71
|
+
children: [/* @__PURE__ */ i("option", {
|
|
72
|
+
value: "",
|
|
73
|
+
children: "Choose a readable file…"
|
|
74
|
+
}), S.map((e) => /* @__PURE__ */ i("option", {
|
|
75
|
+
value: e.id,
|
|
76
|
+
children: e.name
|
|
77
|
+
}, e.id))]
|
|
78
|
+
})]
|
|
79
|
+
}),
|
|
80
|
+
/* @__PURE__ */ a("div", {
|
|
81
|
+
className: "flex gap-2",
|
|
82
|
+
children: [/* @__PURE__ */ i(o, {
|
|
83
|
+
type: "button",
|
|
84
|
+
variant: "outline",
|
|
85
|
+
disabled: x.isFetching || f === 0,
|
|
86
|
+
onClick: () => {
|
|
87
|
+
_(""), E(), p((e) => Math.max(0, e - 25));
|
|
88
|
+
},
|
|
89
|
+
children: "Previous files"
|
|
90
|
+
}), /* @__PURE__ */ i(o, {
|
|
91
|
+
type: "button",
|
|
92
|
+
variant: "outline",
|
|
93
|
+
disabled: x.isFetching || x.isError || !x.data?.hasMore,
|
|
94
|
+
onClick: () => {
|
|
95
|
+
_(""), E(), p((e) => e + 25);
|
|
96
|
+
},
|
|
97
|
+
children: "Next files"
|
|
98
|
+
})]
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ a("label", {
|
|
101
|
+
className: "block text-sm",
|
|
102
|
+
children: ["Evidence version", /* @__PURE__ */ a("select", {
|
|
103
|
+
className: "mt-1 w-full rounded border border-border bg-bg-surface p-2",
|
|
104
|
+
required: !0,
|
|
105
|
+
value: T.some((e) => e.id === v) ? v : "",
|
|
106
|
+
disabled: !C || w.isFetching || w.isError,
|
|
107
|
+
onChange: (e) => {
|
|
108
|
+
let t = T.find((t) => t.id === e.target.value);
|
|
109
|
+
y(t?.id ?? ""), c({
|
|
110
|
+
fileId: t ? g : "",
|
|
111
|
+
versionId: t?.id ?? "",
|
|
112
|
+
sha256: t?.sha256Hash ?? ""
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
children: [/* @__PURE__ */ i("option", {
|
|
116
|
+
value: "",
|
|
117
|
+
children: "Choose an exact version…"
|
|
118
|
+
}), T.map((e) => /* @__PURE__ */ a("option", {
|
|
119
|
+
value: e.id,
|
|
120
|
+
disabled: !e.sha256Hash || !/^[a-fA-F0-9]{64}$/.test(e.sha256Hash),
|
|
121
|
+
children: [
|
|
122
|
+
"Version ",
|
|
123
|
+
e.versionNumber,
|
|
124
|
+
e.versionLabel ? ` · ${e.versionLabel}` : "",
|
|
125
|
+
e.isCurrentVersion ? " · current" : " · historical",
|
|
126
|
+
e.sha256Hash ? "" : " · hash unavailable"
|
|
127
|
+
]
|
|
128
|
+
}, e.id))]
|
|
129
|
+
})]
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ a("div", {
|
|
132
|
+
className: "flex gap-2",
|
|
133
|
+
children: [/* @__PURE__ */ i(o, {
|
|
134
|
+
type: "button",
|
|
135
|
+
variant: "outline",
|
|
136
|
+
disabled: !C || w.isFetching || m === 0,
|
|
137
|
+
onClick: () => {
|
|
138
|
+
E(), h((e) => Math.max(0, e - 25));
|
|
139
|
+
},
|
|
140
|
+
children: "Previous versions"
|
|
141
|
+
}), /* @__PURE__ */ i(o, {
|
|
142
|
+
type: "button",
|
|
143
|
+
variant: "outline",
|
|
144
|
+
disabled: !C || w.isFetching || w.isError || !w.data?.hasMore,
|
|
145
|
+
onClick: () => {
|
|
146
|
+
E(), h((e) => e + 25);
|
|
147
|
+
},
|
|
148
|
+
children: "Next versions"
|
|
149
|
+
})]
|
|
150
|
+
}),
|
|
151
|
+
(x.isError || w.isError) && /* @__PURE__ */ i("p", {
|
|
152
|
+
role: "alert",
|
|
153
|
+
children: "Evidence unavailable. Refresh this form before selecting evidence."
|
|
154
|
+
})
|
|
155
|
+
]
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { s as CredentialEvidencePicker };
|
|
160
|
+
|
|
161
|
+
//# sourceMappingURL=CredentialEvidencePicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialEvidencePicker.js","names":[],"sources":["../../../src/proserviceworld/components/CredentialEvidencePicker.tsx"],"sourcesContent":["import type {\n File as SchemaFile,\n FileVersion as SchemaFileVersion,\n} from '../../generated/wspace-types';\nimport { useState } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { useProServiceWorld } from '../providers/ProServiceWorldProvider';\nimport { pswQuery } from '../hooks/useProServiceWorldApi';\n\ntype EvidenceFile = Pick<SchemaFile, 'id' | 'name' | 'workspaceId' | 'status' | 'canRead'>;\ntype EvidenceVersion = Pick<\n SchemaFileVersion,\n 'id' | 'fileId' | 'versionNumber' | 'versionLabel' | 'sha256Hash' | 'isCurrentVersion'\n>;\nexport function CredentialEvidencePicker({\n disabled,\n onChange,\n}: {\n disabled: boolean;\n onChange: (evidence: { fileId: string; versionId: string; sha256: string }) => void;\n}) {\n const { tenantId, workspaceId, currentUser } = useProServiceWorld();\n const [fileOffset, setFileOffset] = useState(0);\n const [versionOffset, setVersionOffset] = useState(0);\n const [fileId, setFileId] = useState('');\n const [versionId, setVersionId] = useState('');\n const ready = Boolean(tenantId && workspaceId && currentUser?.id);\n const files = useQuery({\n queryKey: [\n 'proserviceworld',\n 'credentialEvidenceFiles',\n tenantId,\n workspaceId,\n currentUser?.id,\n fileOffset,\n ],\n enabled: ready,\n queryFn: async () =>\n (\n await pswQuery<{ getFiles: { files: EvidenceFile[]; hasMore: boolean } }>(\n `query PswReadableEvidenceFiles($pagination: PaginationInput!) {\n getFiles(filter: { status: ACTIVE }, pagination: $pagination) {\n files { id name workspaceId status canRead } hasMore\n }\n }`,\n { pagination: { limit: 25, offset: fileOffset } }\n )\n ).getFiles,\n });\n const choices = (files.data?.files ?? []).filter(\n (file) => file.workspaceId === workspaceId && file.status === 'ACTIVE' && file.canRead === true\n );\n const selectedFile = choices.find((file) => file.id === fileId);\n const versions = useQuery({\n queryKey: [\n 'proserviceworld',\n 'credentialEvidenceVersions',\n tenantId,\n workspaceId,\n currentUser?.id,\n fileId,\n versionOffset,\n ],\n enabled: ready && Boolean(selectedFile),\n queryFn: async () =>\n (\n await pswQuery<{ getFileVersions: { versions: EvidenceVersion[]; hasMore: boolean } }>(\n `query PswReadableEvidenceVersions($fileId: ID!, $pagination: PaginationInput!) {\n getFileVersions(fileId: $fileId, pagination: $pagination) {\n versions { id fileId versionNumber versionLabel sha256Hash isCurrentVersion } hasMore\n }\n }`,\n { fileId, pagination: { limit: 25, offset: versionOffset } }\n )\n ).getFileVersions,\n });\n const versionChoices = (versions.data?.versions ?? []).filter(\n (version) => version.fileId === fileId\n );\n function clearVersion() {\n setVersionId('');\n onChange({ fileId: '', versionId: '', sha256: '' });\n }\n return (\n <fieldset\n className=\"space-y-3 rounded border border-border p-3 sm:col-span-2\"\n disabled={disabled}\n >\n <legend className=\"px-1 font-medium\">Evidence from Files</legend>\n <p className=\"text-sm\">\n Choose a readable file and its exact version. Historical versions are allowed; evidence does\n not certify legal authority.\n </p>\n <label className=\"block text-sm\">\n Evidence file\n <select\n className=\"mt-1 w-full rounded border border-border bg-bg-surface p-2\"\n required\n value={selectedFile ? fileId : ''}\n disabled={!ready || files.isFetching || files.isError}\n onChange={(event) => {\n setFileId(event.target.value);\n setVersionOffset(0);\n clearVersion();\n }}\n >\n <option value=\"\">Choose a readable file…</option>\n {choices.map((file) => (\n <option key={file.id} value={file.id}>\n {file.name}\n </option>\n ))}\n </select>\n </label>\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={files.isFetching || fileOffset === 0}\n onClick={() => {\n setFileId('');\n clearVersion();\n setFileOffset((old) => Math.max(0, old - 25));\n }}\n >\n Previous files\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={files.isFetching || files.isError || !files.data?.hasMore}\n onClick={() => {\n setFileId('');\n clearVersion();\n setFileOffset((old) => old + 25);\n }}\n >\n Next files\n </Button>\n </div>\n <label className=\"block text-sm\">\n Evidence version\n <select\n className=\"mt-1 w-full rounded border border-border bg-bg-surface p-2\"\n required\n value={versionChoices.some((version) => version.id === versionId) ? versionId : ''}\n disabled={!selectedFile || versions.isFetching || versions.isError}\n onChange={(event) => {\n const version = versionChoices.find((item) => item.id === event.target.value);\n setVersionId(version?.id ?? '');\n onChange({\n fileId: version ? fileId : '',\n versionId: version?.id ?? '',\n sha256: version?.sha256Hash ?? '',\n });\n }}\n >\n <option value=\"\">Choose an exact version…</option>\n {versionChoices.map((version) => (\n <option\n key={version.id}\n value={version.id}\n disabled={!version.sha256Hash || !/^[a-fA-F0-9]{64}$/.test(version.sha256Hash)}\n >\n Version {version.versionNumber}\n {version.versionLabel ? ` · ${version.versionLabel}` : ''}\n {version.isCurrentVersion ? ' · current' : ' · historical'}\n {!version.sha256Hash ? ' · hash unavailable' : ''}\n </option>\n ))}\n </select>\n </label>\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={!selectedFile || versions.isFetching || versionOffset === 0}\n onClick={() => {\n clearVersion();\n setVersionOffset((old) => Math.max(0, old - 25));\n }}\n >\n Previous versions\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={\n !selectedFile || versions.isFetching || versions.isError || !versions.data?.hasMore\n }\n onClick={() => {\n clearVersion();\n setVersionOffset((old) => old + 25);\n }}\n >\n Next versions\n </Button>\n </div>\n {(files.isError || versions.isError) && (\n <p role=\"alert\">Evidence unavailable. Refresh this form before selecting evidence.</p>\n )}\n </fieldset>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CredentialWriteOperation } from '../hooks/credentialWrites';
|
|
2
|
+
|
|
3
|
+
export interface CredentialFormField {
|
|
4
|
+
name: string;
|
|
5
|
+
label: string;
|
|
6
|
+
optional?: boolean;
|
|
7
|
+
kind?: 'integer' | 'boolean' | 'datetime';
|
|
8
|
+
options?: readonly string[];
|
|
9
|
+
initial?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CredentialFormDefinition {
|
|
12
|
+
title: string;
|
|
13
|
+
operation: CredentialWriteOperation;
|
|
14
|
+
fields: readonly CredentialFormField[];
|
|
15
|
+
query: string;
|
|
16
|
+
variables: (values: Record<string, string | number | boolean | null>, requestKey: string) => Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
/** Key this component by actor/tenant/workspace so values never survive a context switch. */
|
|
19
|
+
export declare function CredentialRecordForm({ definition, scope, onPreparedReminder, }: {
|
|
20
|
+
definition: CredentialFormDefinition;
|
|
21
|
+
scope: string;
|
|
22
|
+
onPreparedReminder?: (id: string) => void;
|
|
23
|
+
}): import("react").JSX.Element;
|
|
24
|
+
//# sourceMappingURL=CredentialRecordForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialRecordForm.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/components/CredentialRecordForm.tsx"],"names":[],"mappings":"AAOA,OAAO,EAGL,KAAK,wBAAwB,EAE9B,MAAM,2BAA2B,CAAC;AASnC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IAC1C,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,wBAAwB,CAAC;IACpC,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,CACT,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EACxD,UAAU,EAAE,MAAM,KACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,6FAA6F;AAC7F,wBAAgB,oBAAoB,CAAC,EACnC,UAAU,EACV,KAAK,EACL,kBAAkB,GACnB,EAAE;IACD,UAAU,EAAE,wBAAwB,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C,+BA0VA"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { useProServiceWorld as e } from "../providers/ProServiceWorldProvider.js";
|
|
2
|
+
import { pswQuery as t } from "../hooks/useProServiceWorldApi.js";
|
|
3
|
+
import { Banner as n, SectionCard as r } from "./ui.js";
|
|
4
|
+
import { isPendingCredentialWrite as i, writeCredential as a } from "../hooks/credentialWrites.js";
|
|
5
|
+
import { CredentialReferencePicker as o } from "./CredentialReferencePicker.js";
|
|
6
|
+
import { CredentialEvidencePicker as s } from "./CredentialEvidencePicker.js";
|
|
7
|
+
import { useRef as c, useState as l } from "react";
|
|
8
|
+
import { useQueryClient as u } from "@tanstack/react-query";
|
|
9
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
10
|
+
import { clearGraphqlFetchResponseCache as p } from "@burdenoff/fe-libs/shared/graphql/fetch";
|
|
11
|
+
import { Button as m } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
import { useSessionStorage as h } from "@burdenoff/fe-libs/shared/hooks";
|
|
13
|
+
//#region src/proserviceworld/components/CredentialRecordForm.tsx
|
|
14
|
+
function g({ definition: g, scope: _, onPreparedReminder: v }) {
|
|
15
|
+
let { workspaceId: y, tenantId: b, currentUser: x } = e(), S = u(), C = `psw-credential-request:${_}`, [w, T, E] = h(C, null), [D, O] = l({}), [k, A] = l(""), [j, M] = l(""), [N, P] = l(!1), [F, I] = l(!1), L = c(!1), R = i(w) ? w : null, z = w !== null && !R, B = !!(b && y && x?.id), V = g.operation === "REVIEW_EDUCATION_CREDIT" || g.operation === "ARCHIVE_EDUCATION_CREDIT", H = g.fields.some((e) => e.name === "fileId");
|
|
16
|
+
function U(e) {
|
|
17
|
+
if (e === "practitionerId") return "practitioner";
|
|
18
|
+
if (e === "issuingBodyId") return "issuer";
|
|
19
|
+
if (e === "credentialId") return "credential";
|
|
20
|
+
if (e === "obligationId") return "obligation";
|
|
21
|
+
if (e === "predecessorId") return "credit";
|
|
22
|
+
if (e === "id") return g.operation.includes("PRACTITIONER") && !g.operation.includes("CREDENTIAL") ? "practitioner" : g.operation.includes("ISSUING_BODY") ? "issuer" : g.operation.includes("OBLIGATION") ? "obligation" : V ? "credit" : "credential";
|
|
23
|
+
}
|
|
24
|
+
function W(e, t) {
|
|
25
|
+
O((n) => {
|
|
26
|
+
let r = {
|
|
27
|
+
...n,
|
|
28
|
+
[e]: t?.id ?? ""
|
|
29
|
+
}, i = e === "predecessorId" ? "expectedPredecessorRevision" : e === "obligationId" && g.operation === "RECORD_EDUCATION_CREDIT" ? "expectedObligationRevision" : e === "id" || e === "obligationId" && g.operation === "PREPARE_REMINDER" ? "expectedRevision" : null;
|
|
30
|
+
if (i && (r[i] = t ? String(t.revision) : ""), e === "obligationId" && (r.predecessorId = "", r.expectedPredecessorRevision = ""), e === "id" && (g.operation === "UPDATE_CREDENTIAL" || g.operation === "UPDATE_OBLIGATION")) for (let e of g.fields) {
|
|
31
|
+
if (e.name === "id" || e.name === "expectedRevision") continue;
|
|
32
|
+
let n = t?.[e.name];
|
|
33
|
+
r[e.name] = typeof n == "string" || typeof n == "number" ? String(n) : "";
|
|
34
|
+
}
|
|
35
|
+
return r;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async function G(e) {
|
|
39
|
+
if (e.preventDefault(), !B || w !== null || L.current) return;
|
|
40
|
+
try {
|
|
41
|
+
if (sessionStorage.getItem(C) !== null) {
|
|
42
|
+
A("An earlier save exists in this tab. Reload to reconcile its save status.");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
} catch {
|
|
46
|
+
A("Save-status storage is unavailable. No request was sent.");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
let t = {};
|
|
50
|
+
for (let e of g.fields) {
|
|
51
|
+
let n = (D[e.name] ?? e.initial ?? "").trim();
|
|
52
|
+
if (!n && e.optional) {
|
|
53
|
+
t[e.name] = null;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (!n) {
|
|
57
|
+
A(`${e.label} is required.`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (e.options && !e.options.includes(n)) {
|
|
61
|
+
A(`Choose ${e.label}.`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (e.kind === "integer") {
|
|
65
|
+
if (!/^[1-9]\d{0,8}$/.test(n)) {
|
|
66
|
+
A(`${e.label} must be a positive revision number.`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
t[e.name] = Number(n);
|
|
70
|
+
} else if (e.kind === "boolean") {
|
|
71
|
+
if (n !== "true" && n !== "false") {
|
|
72
|
+
A(`Choose ${e.label}.`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
t[e.name] = n === "true";
|
|
76
|
+
} else if (e.kind === "datetime") {
|
|
77
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z$/.test(n) || !Number.isFinite(Date.parse(n))) {
|
|
78
|
+
A(`${e.label} needs an ISO UTC instant, for example 2026-10-14T12:00:00Z.`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
t[e.name] = n;
|
|
82
|
+
} else t[e.name] = n;
|
|
83
|
+
}
|
|
84
|
+
g.operation === "PREPARE_REMINDER" && (t.recipientId = x?.id ?? null);
|
|
85
|
+
let n = {
|
|
86
|
+
operation: g.operation,
|
|
87
|
+
requestKey: crypto.randomUUID()
|
|
88
|
+
};
|
|
89
|
+
T(n);
|
|
90
|
+
try {
|
|
91
|
+
if (sessionStorage.getItem(C) !== JSON.stringify(n)) throw Error("storage");
|
|
92
|
+
} catch {
|
|
93
|
+
A("Could not retain save status in this tab. No request was sent.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
L.current = !0, P(!0), I(!1);
|
|
97
|
+
try {
|
|
98
|
+
let e = await a(g.query, g.variables(t, n.requestKey)), r = Object.values(e), i = r.length === 1 ? r[0] : null, o = g.operation.startsWith("ARCHIVE_") && i === !0;
|
|
99
|
+
if (!o && (!i || typeof i != "object" || !("id" in i) || typeof i.id != "string")) throw Error("Missing owning record acknowledgment");
|
|
100
|
+
g.operation === "PREPARE_REMINDER" && i && typeof i == "object" && "id" in i && typeof i.id == "string" && v?.(i.id), I(!0), A(o ? "Archive acknowledged. Refresh records to verify retained history." : "Save acknowledged. Check save status for the record ID and refresh its current revision."), await S.invalidateQueries({ queryKey: ["proserviceworld"] });
|
|
101
|
+
} catch {
|
|
102
|
+
A("Save outcome unconfirmed. Check save status; this form will not replay the request.");
|
|
103
|
+
} finally {
|
|
104
|
+
P(!1), L.current = !1;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function K() {
|
|
108
|
+
if (!(!B || !R || L.current)) {
|
|
109
|
+
L.current = !0, P(!0);
|
|
110
|
+
try {
|
|
111
|
+
let e = (await t("query PswCredentialRequestOutcome($operation: PswCredentialWriteOperation!, $requestKey: String!) {\n pswCredentialRequestOutcome(operation: $operation, requestKey: $requestKey) {\n operation requestKey status receiptId recordId committedAt zeroEffectsCertified\n }\n }", {
|
|
112
|
+
operation: R.operation,
|
|
113
|
+
requestKey: R.requestKey
|
|
114
|
+
})).pswCredentialRequestOutcome;
|
|
115
|
+
if (e.operation !== R.operation || e.requestKey !== R.requestKey) throw Error("receipt mismatch");
|
|
116
|
+
let n = e.status === "COMMITTED" && !!(e.receiptId && e.recordId && e.committedAt);
|
|
117
|
+
I(n), A(n ? `Committed record: ${e.recordId}. Refresh to review its current revision.` : "Outcome remains unconfirmed. Absence of a receipt does not prove that no changes occurred."), n && (R.operation === "PREPARE_REMINDER" && e.recordId && v?.(e.recordId), p(), await S.invalidateQueries({ queryKey: ["proserviceworld"] }));
|
|
118
|
+
} catch {
|
|
119
|
+
A("Save status unavailable. Outcome remains unconfirmed.");
|
|
120
|
+
} finally {
|
|
121
|
+
L.current = !1, P(!1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return /* @__PURE__ */ f(r, {
|
|
126
|
+
title: g.title,
|
|
127
|
+
children: [
|
|
128
|
+
z && /* @__PURE__ */ d(n, {
|
|
129
|
+
tone: "danger",
|
|
130
|
+
children: "Stored save status cannot be read. Reconcile the earlier request before making another save."
|
|
131
|
+
}),
|
|
132
|
+
R && /* @__PURE__ */ f("div", {
|
|
133
|
+
className: "mb-4 space-y-2",
|
|
134
|
+
children: [
|
|
135
|
+
/* @__PURE__ */ f("p", {
|
|
136
|
+
className: "break-all text-sm",
|
|
137
|
+
children: ["Save reference: ", R.requestKey]
|
|
138
|
+
}),
|
|
139
|
+
/* @__PURE__ */ d(m, {
|
|
140
|
+
variant: "outline",
|
|
141
|
+
disabled: !B || N,
|
|
142
|
+
onClick: () => void K(),
|
|
143
|
+
children: "Check save status"
|
|
144
|
+
}),
|
|
145
|
+
F && /* @__PURE__ */ d(m, {
|
|
146
|
+
variant: "outline",
|
|
147
|
+
disabled: N,
|
|
148
|
+
onClick: () => {
|
|
149
|
+
E(), I(!1), O({}), M(""), A("");
|
|
150
|
+
},
|
|
151
|
+
children: "Start another record"
|
|
152
|
+
})
|
|
153
|
+
]
|
|
154
|
+
}),
|
|
155
|
+
k && /* @__PURE__ */ d("p", {
|
|
156
|
+
role: "status",
|
|
157
|
+
className: "mb-4 break-words",
|
|
158
|
+
children: k
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ f("form", {
|
|
161
|
+
onSubmit: (e) => void G(e),
|
|
162
|
+
className: "grid gap-4 sm:grid-cols-2",
|
|
163
|
+
children: [
|
|
164
|
+
V && /* @__PURE__ */ d(o, {
|
|
165
|
+
kind: "obligation",
|
|
166
|
+
label: "Credit obligation",
|
|
167
|
+
value: j,
|
|
168
|
+
disabled: N || w !== null,
|
|
169
|
+
onSelect: (e) => {
|
|
170
|
+
M(e?.id ?? ""), O((e) => ({
|
|
171
|
+
...e,
|
|
172
|
+
id: "",
|
|
173
|
+
expectedRevision: ""
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
}),
|
|
177
|
+
H && /* @__PURE__ */ d(s, {
|
|
178
|
+
disabled: N || w !== null,
|
|
179
|
+
onChange: (e) => O((t) => ({
|
|
180
|
+
...t,
|
|
181
|
+
...e
|
|
182
|
+
}))
|
|
183
|
+
}, R?.requestKey ?? "new-evidence"),
|
|
184
|
+
g.fields.filter((e) => ![
|
|
185
|
+
"fileId",
|
|
186
|
+
"versionId",
|
|
187
|
+
"sha256",
|
|
188
|
+
"expectedRevision",
|
|
189
|
+
"expectedObligationRevision",
|
|
190
|
+
"expectedPredecessorRevision"
|
|
191
|
+
].includes(e.name)).map((e) => {
|
|
192
|
+
let t = U(e.name);
|
|
193
|
+
return t ? /* @__PURE__ */ d(o, {
|
|
194
|
+
kind: t,
|
|
195
|
+
label: e.label.replace(/ ID$/, ""),
|
|
196
|
+
value: D[e.name] ?? "",
|
|
197
|
+
optional: e.optional,
|
|
198
|
+
disabled: N || w !== null,
|
|
199
|
+
obligationId: D.obligationId ?? j,
|
|
200
|
+
onSelect: (t) => W(e.name, t)
|
|
201
|
+
}, `${e.name}:${t === "credit" ? D.obligationId ?? j : ""}`) : /* @__PURE__ */ f("label", {
|
|
202
|
+
className: "min-w-0 text-sm",
|
|
203
|
+
children: [/* @__PURE__ */ f("span", {
|
|
204
|
+
className: "mb-1 block font-medium",
|
|
205
|
+
children: [e.label, e.optional ? " (optional)" : ""]
|
|
206
|
+
}), e.options ? /* @__PURE__ */ f("select", {
|
|
207
|
+
className: "w-full rounded border border-border bg-bg-surface p-2",
|
|
208
|
+
required: !e.optional,
|
|
209
|
+
disabled: N || w !== null,
|
|
210
|
+
value: D[e.name] ?? e.initial ?? "",
|
|
211
|
+
onChange: (t) => O((n) => ({
|
|
212
|
+
...n,
|
|
213
|
+
[e.name]: t.target.value
|
|
214
|
+
})),
|
|
215
|
+
children: [/* @__PURE__ */ d("option", {
|
|
216
|
+
value: "",
|
|
217
|
+
children: "Choose…"
|
|
218
|
+
}), e.options.map((e) => /* @__PURE__ */ d("option", {
|
|
219
|
+
value: e,
|
|
220
|
+
children: e.replaceAll("_", " ")
|
|
221
|
+
}, e))]
|
|
222
|
+
}) : /* @__PURE__ */ d("input", {
|
|
223
|
+
className: "w-full rounded border border-border bg-bg-surface p-2",
|
|
224
|
+
required: !e.optional,
|
|
225
|
+
maxLength: e.name.toLowerCase().includes("url") ? 2048 : 4e3,
|
|
226
|
+
disabled: N || w !== null,
|
|
227
|
+
value: D[e.name] ?? e.initial ?? "",
|
|
228
|
+
onChange: (t) => O((n) => ({
|
|
229
|
+
...n,
|
|
230
|
+
[e.name]: t.target.value
|
|
231
|
+
}))
|
|
232
|
+
})]
|
|
233
|
+
}, e.name);
|
|
234
|
+
}),
|
|
235
|
+
/* @__PURE__ */ d("div", {
|
|
236
|
+
className: "sm:col-span-2",
|
|
237
|
+
children: /* @__PURE__ */ d(m, {
|
|
238
|
+
type: "submit",
|
|
239
|
+
disabled: !B || N || w !== null,
|
|
240
|
+
children: N ? "Saving…" : "Save record"
|
|
241
|
+
})
|
|
242
|
+
})
|
|
243
|
+
]
|
|
244
|
+
})
|
|
245
|
+
]
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
//#endregion
|
|
249
|
+
export { g as CredentialRecordForm };
|
|
250
|
+
|
|
251
|
+
//# sourceMappingURL=CredentialRecordForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialRecordForm.js","names":[],"sources":["../../../src/proserviceworld/components/CredentialRecordForm.tsx"],"sourcesContent":["import { useRef, useState, type FormEvent } from 'react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { clearGraphqlFetchResponseCache } from '@burdenoff/fe-libs/shared/graphql/fetch';\nimport { useSessionStorage } from '@burdenoff/fe-libs/shared/hooks';\nimport { useProServiceWorld } from '../providers/ProServiceWorldProvider';\nimport { pswQuery } from '../hooks/useProServiceWorldApi';\nimport {\n isPendingCredentialWrite,\n writeCredential,\n type CredentialWriteOperation,\n type CredentialRequestOutcome,\n} from '../hooks/credentialWrites';\nimport { Banner, SectionCard } from './ui';\nimport {\n CredentialReferencePicker,\n type CredentialReferenceKind,\n type CredentialReference,\n} from './CredentialReferencePicker';\nimport { CredentialEvidencePicker } from './CredentialEvidencePicker';\n\nexport interface CredentialFormField {\n name: string;\n label: string;\n optional?: boolean;\n kind?: 'integer' | 'boolean' | 'datetime';\n options?: readonly string[];\n initial?: string;\n}\nexport interface CredentialFormDefinition {\n title: string;\n operation: CredentialWriteOperation;\n fields: readonly CredentialFormField[];\n query: string;\n variables: (\n values: Record<string, string | number | boolean | null>,\n requestKey: string\n ) => Record<string, unknown>;\n}\n\n/** Key this component by actor/tenant/workspace so values never survive a context switch. */\nexport function CredentialRecordForm({\n definition,\n scope,\n onPreparedReminder,\n}: {\n definition: CredentialFormDefinition;\n scope: string;\n onPreparedReminder?: (id: string) => void;\n}) {\n const { workspaceId, tenantId, currentUser } = useProServiceWorld();\n const client = useQueryClient();\n const storageKey = `psw-credential-request:${scope}`;\n // The shared session hook persists only operation/key, never form data or identity tokens.\n const [stored, setStored, clearStored] = useSessionStorage<unknown>(storageKey, null);\n const [values, setValues] = useState<Record<string, string>>({});\n const [message, setMessage] = useState('');\n const [creditObligationId, setCreditObligationId] = useState('');\n const [busy, setBusy] = useState(false);\n const [confirmed, setConfirmed] = useState(false);\n const attemptLock = useRef(false);\n const pending = isPendingCredentialWrite(stored) ? stored : null;\n const corrupt = stored !== null && !pending;\n const ready = Boolean(tenantId && workspaceId && currentUser?.id);\n\n const needsCredit =\n definition.operation === 'REVIEW_EDUCATION_CREDIT' ||\n definition.operation === 'ARCHIVE_EDUCATION_CREDIT';\n const hasEvidence = definition.fields.some((field) => field.name === 'fileId');\n function referenceKind(name: string): CredentialReferenceKind | undefined {\n if (name === 'practitionerId') return 'practitioner';\n if (name === 'issuingBodyId') return 'issuer';\n if (name === 'credentialId') return 'credential';\n if (name === 'obligationId') return 'obligation';\n if (name === 'predecessorId') return 'credit';\n if (name !== 'id') return undefined;\n if (\n definition.operation.includes('PRACTITIONER') &&\n !definition.operation.includes('CREDENTIAL')\n )\n return 'practitioner';\n if (definition.operation.includes('ISSUING_BODY')) return 'issuer';\n if (definition.operation.includes('OBLIGATION')) return 'obligation';\n return needsCredit ? 'credit' : 'credential';\n }\n function selectReference(name: string, record: CredentialReference | null) {\n setValues((old) => {\n const next = { ...old, [name]: record?.id ?? '' };\n const revisionField =\n name === 'predecessorId'\n ? 'expectedPredecessorRevision'\n : name === 'obligationId' && definition.operation === 'RECORD_EDUCATION_CREDIT'\n ? 'expectedObligationRevision'\n : name === 'id' ||\n (name === 'obligationId' && definition.operation === 'PREPARE_REMINDER')\n ? 'expectedRevision'\n : null;\n if (revisionField) next[revisionField] = record ? String(record.revision) : '';\n if (name === 'obligationId') {\n next.predecessorId = '';\n next.expectedPredecessorRevision = '';\n }\n // Correction forms load the selected owning facts; notes/review decisions remain explicit.\n if (\n name === 'id' &&\n (definition.operation === 'UPDATE_CREDENTIAL' ||\n definition.operation === 'UPDATE_OBLIGATION')\n ) {\n for (const field of definition.fields) {\n if (field.name === 'id' || field.name === 'expectedRevision') continue;\n const value = record?.[field.name];\n next[field.name] =\n typeof value === 'string' || typeof value === 'number' ? String(value) : '';\n }\n }\n return next;\n });\n }\n\n async function submit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n if (!ready || stored !== null || attemptLock.current) return;\n try {\n if (sessionStorage.getItem(storageKey) !== null) {\n setMessage('An earlier save exists in this tab. Reload to reconcile its save status.');\n return;\n }\n } catch {\n setMessage('Save-status storage is unavailable. No request was sent.');\n return;\n }\n const input: Record<string, string | number | boolean | null> = {};\n for (const field of definition.fields) {\n const value = (values[field.name] ?? field.initial ?? '').trim();\n if (!value && field.optional) {\n input[field.name] = null;\n continue;\n }\n if (!value) {\n setMessage(`${field.label} is required.`);\n return;\n }\n if (field.options && !field.options.includes(value)) {\n setMessage(`Choose ${field.label}.`);\n return;\n }\n if (field.kind === 'integer') {\n if (!/^[1-9]\\d{0,8}$/.test(value)) {\n setMessage(`${field.label} must be a positive revision number.`);\n return;\n }\n input[field.name] = Number(value);\n } else if (field.kind === 'boolean') {\n if (value !== 'true' && value !== 'false') {\n setMessage(`Choose ${field.label}.`);\n return;\n }\n input[field.name] = value === 'true';\n } else if (field.kind === 'datetime') {\n if (\n !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,3})?Z$/.test(value) ||\n !Number.isFinite(Date.parse(value))\n ) {\n setMessage(`${field.label} needs an ISO UTC instant, for example 2026-10-14T12:00:00Z.`);\n return;\n }\n input[field.name] = value;\n } else {\n input[field.name] = value;\n }\n }\n if (definition.operation === 'PREPARE_REMINDER') input.recipientId = currentUser?.id ?? null;\n const metadata = { operation: definition.operation, requestKey: crypto.randomUUID() };\n // Shared hook swallows storage failures. Verify its exact write before allocating any request.\n setStored(metadata);\n try {\n if (sessionStorage.getItem(storageKey) !== JSON.stringify(metadata))\n throw new Error('storage');\n } catch {\n setMessage('Could not retain save status in this tab. No request was sent.');\n return;\n }\n attemptLock.current = true;\n setBusy(true);\n setConfirmed(false);\n try {\n const acknowledgment = await writeCredential<Record<string, unknown>>(\n definition.query,\n definition.variables(input, metadata.requestKey)\n );\n const records = Object.values(acknowledgment);\n const record = records.length === 1 ? records[0] : null;\n const archived = definition.operation.startsWith('ARCHIVE_') && record === true;\n if (\n !archived &&\n (!record ||\n typeof record !== 'object' ||\n !('id' in record) ||\n typeof record.id !== 'string')\n ) {\n throw new Error('Missing owning record acknowledgment');\n }\n if (\n definition.operation === 'PREPARE_REMINDER' &&\n record &&\n typeof record === 'object' &&\n 'id' in record &&\n typeof record.id === 'string'\n )\n onPreparedReminder?.(record.id);\n setConfirmed(true);\n setMessage(\n archived\n ? 'Archive acknowledged. Refresh records to verify retained history.'\n : 'Save acknowledged. Check save status for the record ID and refresh its current revision.'\n );\n await client.invalidateQueries({ queryKey: ['proserviceworld'] });\n } catch {\n setMessage(\n 'Save outcome unconfirmed. Check save status; this form will not replay the request.'\n );\n } finally {\n setBusy(false);\n attemptLock.current = false;\n }\n }\n\n async function checkOutcome() {\n if (!ready || !pending || attemptLock.current) return;\n attemptLock.current = true;\n setBusy(true);\n try {\n const data = await pswQuery<{ pswCredentialRequestOutcome: CredentialRequestOutcome }>(\n `query PswCredentialRequestOutcome($operation: PswCredentialWriteOperation!, $requestKey: String!) {\n pswCredentialRequestOutcome(operation: $operation, requestKey: $requestKey) {\n operation requestKey status receiptId recordId committedAt zeroEffectsCertified\n }\n }`,\n { operation: pending.operation, requestKey: pending.requestKey }\n );\n const outcome = data.pswCredentialRequestOutcome;\n if (outcome.operation !== pending.operation || outcome.requestKey !== pending.requestKey)\n throw new Error('receipt mismatch');\n const committed =\n outcome.status === 'COMMITTED' &&\n Boolean(outcome.receiptId && outcome.recordId && outcome.committedAt);\n setConfirmed(committed);\n setMessage(\n committed\n ? `Committed record: ${outcome.recordId}. Refresh to review its current revision.`\n : 'Outcome remains unconfirmed. Absence of a receipt does not prove that no changes occurred.'\n );\n if (committed) {\n if (pending.operation === 'PREPARE_REMINDER' && outcome.recordId)\n onPreparedReminder?.(outcome.recordId);\n clearGraphqlFetchResponseCache();\n await client.invalidateQueries({ queryKey: ['proserviceworld'] });\n }\n } catch {\n setMessage('Save status unavailable. Outcome remains unconfirmed.');\n } finally {\n attemptLock.current = false;\n setBusy(false);\n }\n }\n\n return (\n <SectionCard title={definition.title}>\n {corrupt && (\n <Banner tone=\"danger\">\n Stored save status cannot be read. Reconcile the earlier request before making another\n save.\n </Banner>\n )}\n {pending && (\n <div className=\"mb-4 space-y-2\">\n <p className=\"break-all text-sm\">Save reference: {pending.requestKey}</p>\n <Button variant=\"outline\" disabled={!ready || busy} onClick={() => void checkOutcome()}>\n Check save status\n </Button>\n {confirmed && (\n <Button\n variant=\"outline\"\n disabled={busy}\n onClick={() => {\n clearStored();\n setConfirmed(false);\n setValues({});\n setCreditObligationId('');\n setMessage('');\n }}\n >\n Start another record\n </Button>\n )}\n </div>\n )}\n {message && (\n <p role=\"status\" className=\"mb-4 break-words\">\n {message}\n </p>\n )}\n <form onSubmit={(event) => void submit(event)} className=\"grid gap-4 sm:grid-cols-2\">\n {needsCredit && (\n <CredentialReferencePicker\n kind=\"obligation\"\n label=\"Credit obligation\"\n value={creditObligationId}\n disabled={busy || stored !== null}\n onSelect={(record) => {\n setCreditObligationId(record?.id ?? '');\n setValues((old) => ({ ...old, id: '', expectedRevision: '' }));\n }}\n />\n )}\n {hasEvidence && (\n <CredentialEvidencePicker\n key={pending?.requestKey ?? 'new-evidence'}\n disabled={busy || stored !== null}\n onChange={(evidence) => setValues((old) => ({ ...old, ...evidence }))}\n />\n )}\n {definition.fields\n .filter(\n (field) =>\n ![\n 'fileId',\n 'versionId',\n 'sha256',\n 'expectedRevision',\n 'expectedObligationRevision',\n 'expectedPredecessorRevision',\n ].includes(field.name)\n )\n .map((field) => {\n const kind = referenceKind(field.name);\n if (kind)\n return (\n <CredentialReferencePicker\n key={`${field.name}:${kind === 'credit' ? (values.obligationId ?? creditObligationId) : ''}`}\n kind={kind}\n label={field.label.replace(/ ID$/, '')}\n value={values[field.name] ?? ''}\n optional={field.optional}\n disabled={busy || stored !== null}\n obligationId={values.obligationId ?? creditObligationId}\n onSelect={(record) => selectReference(field.name, record)}\n />\n );\n return (\n <label key={field.name} className=\"min-w-0 text-sm\">\n <span className=\"mb-1 block font-medium\">\n {field.label}\n {field.optional ? ' (optional)' : ''}\n </span>\n {field.options ? (\n <select\n className=\"w-full rounded border border-border bg-bg-surface p-2\"\n required={!field.optional}\n disabled={busy || stored !== null}\n value={values[field.name] ?? field.initial ?? ''}\n onChange={(event) =>\n setValues((old) => ({ ...old, [field.name]: event.target.value }))\n }\n >\n <option value=\"\">Choose…</option>\n {field.options.map((value) => (\n <option key={value} value={value}>\n {value.replaceAll('_', ' ')}\n </option>\n ))}\n </select>\n ) : (\n <input\n className=\"w-full rounded border border-border bg-bg-surface p-2\"\n required={!field.optional}\n maxLength={field.name.toLowerCase().includes('url') ? 2048 : 4000}\n disabled={busy || stored !== null}\n value={values[field.name] ?? field.initial ?? ''}\n onChange={(event) =>\n setValues((old) => ({ ...old, [field.name]: event.target.value }))\n }\n />\n )}\n </label>\n );\n })}\n <div className=\"sm:col-span-2\">\n <Button type=\"submit\" disabled={!ready || busy || stored !== null}>\n {busy ? 'Saving…' : 'Save record'}\n </Button>\n </div>\n </form>\n </SectionCard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAyCA,SAAgB,EAAqB,EACnC,eACA,UACA,yBAKC;CACD,IAAM,EAAE,gBAAa,aAAU,mBAAgB,EAAmB,GAC5D,IAAS,EAAe,GACxB,IAAa,0BAA0B,KAEvC,CAAC,GAAQ,GAAW,KAAe,EAA2B,GAAY,IAAI,GAC9E,CAAC,GAAQ,KAAa,EAAiC,CAAC,CAAC,GACzD,CAAC,GAAS,KAAc,EAAS,EAAE,GACnC,CAAC,GAAoB,KAAyB,EAAS,EAAE,GACzD,CAAC,GAAM,KAAW,EAAS,EAAK,GAChC,CAAC,GAAW,KAAgB,EAAS,EAAK,GAC1C,IAAc,EAAO,EAAK,GAC1B,IAAU,EAAyB,CAAM,IAAI,IAAS,MACtD,IAAU,MAAW,QAAQ,CAAC,GAC9B,IAAQ,GAAQ,KAAY,KAAe,GAAa,KAExD,IACJ,EAAW,cAAc,6BACzB,EAAW,cAAc,4BACrB,IAAc,EAAW,OAAO,MAAM,MAAU,EAAM,SAAS,QAAQ;CAC7E,SAAS,EAAc,GAAmD;EACxE,IAAI,MAAS,kBAAkB,OAAO;EACtC,IAAI,MAAS,iBAAiB,OAAO;EACrC,IAAI,MAAS,gBAAgB,OAAO;EACpC,IAAI,MAAS,gBAAgB,OAAO;EACpC,IAAI,MAAS,iBAAiB,OAAO;EACjC,UAAS,MAQb,OANE,EAAW,UAAU,SAAS,cAAc,KAC5C,CAAC,EAAW,UAAU,SAAS,YAAY,IAEpC,iBACL,EAAW,UAAU,SAAS,cAAc,IAAU,WACtD,EAAW,UAAU,SAAS,YAAY,IAAU,eACjD,IAAc,WAAW;CAClC;CACA,SAAS,EAAgB,GAAc,GAAoC;EACzE,GAAW,MAAQ;GACjB,IAAM,IAAO;IAAE,GAAG;KAAM,IAAO,GAAQ,MAAM;GAAG,GAC1C,IACJ,MAAS,kBACL,gCACA,MAAS,kBAAkB,EAAW,cAAc,4BAClD,+BACA,MAAS,QACN,MAAS,kBAAkB,EAAW,cAAc,qBACrD,qBACA;GAOV,IANI,MAAe,EAAK,KAAiB,IAAS,OAAO,EAAO,QAAQ,IAAI,KACxE,MAAS,mBACX,EAAK,gBAAgB,IACrB,EAAK,8BAA8B,KAInC,MAAS,SACR,EAAW,cAAc,uBACxB,EAAW,cAAc,sBAE3B,KAAK,IAAM,KAAS,EAAW,QAAQ;IACrC,IAAI,EAAM,SAAS,QAAQ,EAAM,SAAS,oBAAoB;IAC9D,IAAM,IAAQ,IAAS,EAAM;IAC7B,EAAK,EAAM,QACT,OAAO,KAAU,YAAY,OAAO,KAAU,WAAW,OAAO,CAAK,IAAI;GAC7E;GAEF,OAAO;EACT,CAAC;CACH;CAEA,eAAe,EAAO,GAAmC;EAEvD,IADA,EAAM,eAAe,GACjB,CAAC,KAAS,MAAW,QAAQ,EAAY,SAAS;EACtD,IAAI;GACF,IAAI,eAAe,QAAQ,CAAU,MAAM,MAAM;IAC/C,EAAW,0EAA0E;IACrF;GACF;EACF,QAAQ;GACN,EAAW,0DAA0D;GACrE;EACF;EACA,IAAM,IAA0D,CAAC;EACjE,KAAK,IAAM,KAAS,EAAW,QAAQ;GACrC,IAAM,KAAS,EAAO,EAAM,SAAS,EAAM,WAAW,GAAA,CAAI,KAAK;GAC/D,IAAI,CAAC,KAAS,EAAM,UAAU;IAC5B,EAAM,EAAM,QAAQ;IACpB;GACF;GACA,IAAI,CAAC,GAAO;IACV,EAAW,GAAG,EAAM,MAAM,cAAc;IACxC;GACF;GACA,IAAI,EAAM,WAAW,CAAC,EAAM,QAAQ,SAAS,CAAK,GAAG;IACnD,EAAW,UAAU,EAAM,MAAM,EAAE;IACnC;GACF;GACA,IAAI,EAAM,SAAS,WAAW;IAC5B,IAAI,CAAC,iBAAiB,KAAK,CAAK,GAAG;KACjC,EAAW,GAAG,EAAM,MAAM,qCAAqC;KAC/D;IACF;IACA,EAAM,EAAM,QAAQ,OAAO,CAAK;GAClC,OAAO,IAAI,EAAM,SAAS,WAAW;IACnC,IAAI,MAAU,UAAU,MAAU,SAAS;KACzC,EAAW,UAAU,EAAM,MAAM,EAAE;KACnC;IACF;IACA,EAAM,EAAM,QAAQ,MAAU;GAChC,OAAO,IAAI,EAAM,SAAS,YAAY;IACpC,IACE,CAAC,uDAAuD,KAAK,CAAK,KAClE,CAAC,OAAO,SAAS,KAAK,MAAM,CAAK,CAAC,GAClC;KACA,EAAW,GAAG,EAAM,MAAM,6DAA6D;KACvF;IACF;IACA,EAAM,EAAM,QAAQ;GACtB,OACE,EAAM,EAAM,QAAQ;EAExB;EACA,AAAI,EAAW,cAAc,uBAAoB,EAAM,cAAc,GAAa,MAAM;EACxF,IAAM,IAAW;GAAE,WAAW,EAAW;GAAW,YAAY,OAAO,WAAW;EAAE;EAEpF,EAAU,CAAQ;EAClB,IAAI;GACF,IAAI,eAAe,QAAQ,CAAU,MAAM,KAAK,UAAU,CAAQ,GAChE,MAAU,MAAM,SAAS;EAC7B,QAAQ;GACN,EAAW,gEAAgE;GAC3E;EACF;EAGA,AAFA,EAAY,UAAU,IACtB,EAAQ,EAAI,GACZ,EAAa,EAAK;EAClB,IAAI;GACF,IAAM,IAAiB,MAAM,EAC3B,EAAW,OACX,EAAW,UAAU,GAAO,EAAS,UAAU,CACjD,GACM,IAAU,OAAO,OAAO,CAAc,GACtC,IAAS,EAAQ,WAAW,IAAI,EAAQ,KAAK,MAC7C,IAAW,EAAW,UAAU,WAAW,UAAU,KAAK,MAAW;GAC3E,IACE,CAAC,MACA,CAAC,KACA,OAAO,KAAW,YAClB,EAAE,QAAQ,MACV,OAAO,EAAO,MAAO,WAEvB,MAAU,MAAM,sCAAsC;GAgBxD,AAbE,EAAW,cAAc,sBACzB,KACA,OAAO,KAAW,YAClB,QAAQ,KACR,OAAO,EAAO,MAAO,YAErB,IAAqB,EAAO,EAAE,GAChC,EAAa,EAAI,GACjB,EACE,IACI,sEACA,0FACN,GACA,MAAM,EAAO,kBAAkB,EAAE,UAAU,CAAC,iBAAiB,EAAE,CAAC;EAClE,QAAQ;GACN,EACE,qFACF;EACF,UAAU;GAER,AADA,EAAQ,EAAK,GACb,EAAY,UAAU;EACxB;CACF;CAEA,eAAe,IAAe;EACxB,OAAC,KAAS,CAAC,KAAW,EAAY,UAEtC;GADA,EAAY,UAAU,IACtB,EAAQ,EAAI;GACZ,IAAI;IASF,IAAM,KAAU,MARG,EACjB,qTAKA;KAAE,WAAW,EAAQ;KAAW,YAAY,EAAQ;IAAW,CACjE,EAAA,CACqB;IACrB,IAAI,EAAQ,cAAc,EAAQ,aAAa,EAAQ,eAAe,EAAQ,YAC5E,MAAU,MAAM,kBAAkB;IACpC,IAAM,IACJ,EAAQ,WAAW,eACnB,GAAQ,EAAQ,aAAa,EAAQ,YAAY,EAAQ;IAO3D,AANA,EAAa,CAAS,GACtB,EACE,IACI,qBAAqB,EAAQ,SAAS,6CACtC,4FACN,GACI,MACE,EAAQ,cAAc,sBAAsB,EAAQ,YACtD,IAAqB,EAAQ,QAAQ,GACvC,EAA+B,GAC/B,MAAM,EAAO,kBAAkB,EAAE,UAAU,CAAC,iBAAiB,EAAE,CAAC;GAEpE,QAAQ;IACN,EAAW,uDAAuD;GACpE,UAAU;IAER,AADA,EAAY,UAAU,IACtB,EAAQ,EAAK;GACf;EAjCY;CAkCd;CAEA,OACE,kBAAC,GAAD;EAAa,OAAO,EAAW;YAA/B;GACG,KACC,kBAAC,GAAD;IAAQ,MAAK;cAAS;GAGd,CAAA;GAET,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,KAAD;MAAG,WAAU;gBAAb,CAAiC,oBAAiB,EAAQ,UAAc;;KACxE,kBAAC,GAAD;MAAQ,SAAQ;MAAU,UAAU,CAAC,KAAS;MAAM,eAAe,KAAK,EAAa;gBAAG;KAEhF,CAAA;KACP,KACC,kBAAC,GAAD;MACE,SAAQ;MACR,UAAU;MACV,eAAe;OAKb,AAJA,EAAY,GACZ,EAAa,EAAK,GAClB,EAAU,CAAC,CAAC,GACZ,EAAsB,EAAE,GACxB,EAAW,EAAE;MACf;gBACD;KAEO,CAAA;IAEP;;GAEN,KACC,kBAAC,KAAD;IAAG,MAAK;IAAS,WAAU;cACxB;GACA,CAAA;GAEL,kBAAC,QAAD;IAAM,WAAW,MAAU,KAAK,EAAO,CAAK;IAAG,WAAU;cAAzD;KACG,KACC,kBAAC,GAAD;MACE,MAAK;MACL,OAAM;MACN,OAAO;MACP,UAAU,KAAQ,MAAW;MAC7B,WAAW,MAAW;OAEpB,AADA,EAAsB,GAAQ,MAAM,EAAE,GACtC,GAAW,OAAS;QAAE,GAAG;QAAK,IAAI;QAAI,kBAAkB;OAAG,EAAE;MAC/D;KACD,CAAA;KAEF,KACC,kBAAC,GAAD;MAEE,UAAU,KAAQ,MAAW;MAC7B,WAAW,MAAa,GAAW,OAAS;OAAE,GAAG;OAAK,GAAG;MAAS,EAAE;KACrE,GAHM,GAAS,cAAc,cAG7B;KAEF,EAAW,OACT,QACE,MACC,CAAC;MACC;MACA;MACA;MACA;MACA;MACA;KACF,CAAC,CAAC,SAAS,EAAM,IAAI,CACzB,CAAC,CACA,KAAK,MAAU;MACd,IAAM,IAAO,EAAc,EAAM,IAAI;MAcrC,OAbI,IAEA,kBAAC,GAAD;OAEQ;OACN,OAAO,EAAM,MAAM,QAAQ,QAAQ,EAAE;OACrC,OAAO,EAAO,EAAM,SAAS;OAC7B,UAAU,EAAM;OAChB,UAAU,KAAQ,MAAW;OAC7B,cAAc,EAAO,gBAAgB;OACrC,WAAW,MAAW,EAAgB,EAAM,MAAM,CAAM;MACzD,GARM,GAAG,EAAM,KAAK,GAAG,MAAS,WAAY,EAAO,gBAAgB,IAAsB,IAQzF,IAGH,kBAAC,SAAD;OAAwB,WAAU;iBAAlC,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACG,EAAM,OACN,EAAM,WAAW,gBAAgB,EAC9B;WACL,EAAM,UACL,kBAAC,UAAD;QACE,WAAU;QACV,UAAU,CAAC,EAAM;QACjB,UAAU,KAAQ,MAAW;QAC7B,OAAO,EAAO,EAAM,SAAS,EAAM,WAAW;QAC9C,WAAW,MACT,GAAW,OAAS;SAAE,GAAG;UAAM,EAAM,OAAO,EAAM,OAAO;QAAM,EAAE;kBANrE,CASE,kBAAC,UAAD;SAAQ,OAAM;mBAAG;QAAe,CAAA,GAC/B,EAAM,QAAQ,KAAK,MAClB,kBAAC,UAAD;SAA2B;mBACxB,EAAM,WAAW,KAAK,GAAG;QACpB,GAFK,CAEL,CACT,CACK;YAER,kBAAC,SAAD;QACE,WAAU;QACV,UAAU,CAAC,EAAM;QACjB,WAAW,EAAM,KAAK,YAAY,CAAC,CAAC,SAAS,KAAK,IAAI,OAAO;QAC7D,UAAU,KAAQ,MAAW;QAC7B,OAAO,EAAO,EAAM,SAAS,EAAM,WAAW;QAC9C,WAAW,MACT,GAAW,OAAS;SAAE,GAAG;UAAM,EAAM,OAAO,EAAM,OAAO;QAAM,EAAE;OAEpE,CAAA,CAEE;SAlCK,EAAM,IAkCX;KAEX,CAAC;KACH,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAQ,MAAK;OAAS,UAAU,CAAC,KAAS,KAAQ,MAAW;iBAC1D,IAAO,YAAY;MACd,CAAA;KACL,CAAA;IACD;;EACK;;AAEjB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type CredentialReferenceKind = 'practitioner' | 'issuer' | 'credential' | 'obligation' | 'credit';
|
|
2
|
+
export interface CredentialReference {
|
|
3
|
+
id: string;
|
|
4
|
+
revision: number;
|
|
5
|
+
displayName?: string;
|
|
6
|
+
identifier?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
provider?: string;
|
|
9
|
+
activityReference?: string;
|
|
10
|
+
[field: string]: string | number | boolean | null | undefined;
|
|
11
|
+
}
|
|
12
|
+
/** Choices come from the owning gateway query; callers never supply a GraphQL field name. */
|
|
13
|
+
export declare function CredentialReferencePicker({ kind, label, value, optional, disabled, obligationId, onSelect, }: {
|
|
14
|
+
kind: CredentialReferenceKind;
|
|
15
|
+
label: string;
|
|
16
|
+
value: string;
|
|
17
|
+
optional?: boolean;
|
|
18
|
+
disabled: boolean;
|
|
19
|
+
obligationId?: string;
|
|
20
|
+
onSelect: (record: CredentialReference | null) => void;
|
|
21
|
+
}): import("react").JSX.Element;
|
|
22
|
+
//# sourceMappingURL=CredentialReferencePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CredentialReferencePicker.d.ts","sourceRoot":"","sources":["../../../src/proserviceworld/components/CredentialReferencePicker.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,uBAAuB,GAC/B,cAAc,GACd,QAAQ,GACR,YAAY,GACZ,YAAY,GACZ,QAAQ,CAAC;AACb,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;CAC/D;AAuBD,6FAA6F;AAC7F,wBAAgB,yBAAyB,CAAC,EACxC,IAAI,EACJ,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,uBAAuB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,KAAK,IAAI,CAAC;CACxD,+BAqGA"}
|