uhc-portal-components-react 0.1.22 → 0.1.23

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.23
4
+
5
+ - Add a shared vital-sign editor with an explicit measurement-type selector.
6
+ - Capture systolic and diastolic blood pressure as two components of one typed measurement, ready for the canonical flat observation graph and one composite FHIR `Observation` at the projection boundary.
7
+ - Keep persistence, authorization and provider readback in the host portal.
8
+
3
9
  ## 0.1.22
4
10
 
5
11
  - Preserve complete FHIR date and dateTime values in the shared clinical editor instead of silently truncating timezone-bearing values through an HTML calendar-date input.
@@ -0,0 +1,29 @@
1
+ import { type VitalSignKind, type VitalSignMeasurement } from 'fhir-data-utils-ts';
2
+ import type { ClinicalResourceBundleLike } from 'gdc-common-utils-ts/utils/clinical-resource-view';
3
+ export type VitalSignArtifactEditorCopy = Readonly<{
4
+ title: string;
5
+ description: string;
6
+ kind: string;
7
+ measuredAt: string;
8
+ value: string;
9
+ systolic: string;
10
+ diastolic: string;
11
+ save: string;
12
+ saving: string;
13
+ cancel: string;
14
+ close: string;
15
+ readbackMissing: string;
16
+ }>;
17
+ export type VitalSignKindLabels = Readonly<Record<VitalSignKind, string>>;
18
+ export type VitalSignArtifactEditorProps = Readonly<{
19
+ entryId: string;
20
+ subjectReference: string;
21
+ copy: VitalSignArtifactEditorCopy;
22
+ kindLabels: VitalSignKindLabels;
23
+ saveMeasurement: (measurement: VitalSignMeasurement) => Promise<ClinicalResourceBundleLike | undefined>;
24
+ onCancel: () => void;
25
+ onReadback: (bundle: ClinicalResourceBundleLike) => void;
26
+ }>;
27
+ /** Shared vital-sign capture. Composite values remain one typed measurement. */
28
+ export declare function VitalSignArtifactEditor({ entryId, subjectReference, copy, kindLabels, saveMeasurement, onCancel, onReadback, }: VitalSignArtifactEditorProps): import("react").JSX.Element;
29
+ //# sourceMappingURL=VitalSignArtifactEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VitalSignArtifactEditor.d.ts","sourceRoot":"","sources":["../src/VitalSignArtifactEditor.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kDAAkD,CAAA;AAElG,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,EAAE,MAAM,CAAA;CACxB,CAAC,CAAA;AAEF,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAA;AAEzE,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,EAAE,MAAM,CAAA;IACxB,IAAI,EAAE,2BAA2B,CAAA;IACjC,UAAU,EAAE,mBAAmB,CAAA;IAC/B,eAAe,EAAE,CAAC,WAAW,EAAE,oBAAoB,KAAK,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAAA;IACvG,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAA;CACzD,CAAC,CAAA;AAWF,gFAAgF;AAChF,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,gBAAgB,EAChB,IAAI,EACJ,UAAU,EACV,eAAe,EACf,QAAQ,EACR,UAAU,GACX,EAAE,4BAA4B,+BA+C9B"}
@@ -0,0 +1,54 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useId, useState } from 'react';
4
+ import { VitalSignUnit, } from 'fhir-data-utils-ts';
5
+ const VITAL_SIGN_KINDS = Object.freeze([
6
+ 'blood-pressure',
7
+ 'temperature',
8
+ 'heart-rate',
9
+ 'oxygen-saturation',
10
+ 'respiratory-rate',
11
+ 'body-weight',
12
+ ]);
13
+ /** Shared vital-sign capture. Composite values remain one typed measurement. */
14
+ export function VitalSignArtifactEditor({ entryId, subjectReference, copy, kindLabels, saveMeasurement, onCancel, onReadback, }) {
15
+ const titleId = useId();
16
+ const descriptionId = useId();
17
+ const [kind, setKind] = useState('oxygen-saturation');
18
+ const [measuredAt, setMeasuredAt] = useState('');
19
+ const [value, setValue] = useState('');
20
+ const [systolic, setSystolic] = useState('');
21
+ const [diastolic, setDiastolic] = useState('');
22
+ const [saving, setSaving] = useState(false);
23
+ const [error, setError] = useState('');
24
+ async function submit() {
25
+ setSaving(true);
26
+ setError('');
27
+ try {
28
+ const common = { entryId, subjectReference, kind, measuredAt, status: 'final' };
29
+ const measurement = kind === 'blood-pressure'
30
+ ? { ...common, kind, systolic: Number(systolic), diastolic: Number(diastolic) }
31
+ : { ...common, kind, value: Number(value), unit: unitFor(kind) };
32
+ const readback = await saveMeasurement(measurement);
33
+ if (!readback)
34
+ throw new Error(copy.readbackMissing);
35
+ onReadback(readback);
36
+ }
37
+ catch (reason) {
38
+ setError(reason instanceof Error ? reason.message : String(reason));
39
+ }
40
+ finally {
41
+ setSaving(false);
42
+ }
43
+ }
44
+ return _jsxs("section", { className: "uhcp-clinical-editor", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, "aria-describedby": descriptionId, children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("h2", { id: titleId, children: copy.title }), _jsx("p", { id: descriptionId, children: copy.description })] }), _jsx("button", { type: "button", onClick: onCancel, "aria-label": copy.close, children: "\u00D7" })] }), _jsxs("form", { onSubmit: (event) => { event.preventDefault(); void submit(); }, children: [_jsxs("label", { children: [_jsxs("span", { children: [copy.kind, " *"] }), _jsx("select", { "aria-label": copy.kind, value: kind, onChange: (event) => setKind(event.target.value), children: VITAL_SIGN_KINDS.map((option) => _jsx("option", { value: option, children: kindLabels[option] }, option)) })] }), _jsxs("label", { children: [_jsxs("span", { children: [copy.measuredAt, " *"] }), _jsx("input", { "aria-label": copy.measuredAt, required: true, value: measuredAt, onChange: (event) => setMeasuredAt(event.target.value) })] }), kind === 'blood-pressure' ? _jsxs(_Fragment, { children: [_jsxs("label", { children: [_jsxs("span", { children: [copy.systolic, " *"] }), _jsx("input", { "aria-label": copy.systolic, required: true, type: "number", value: systolic, onChange: (event) => setSystolic(event.target.value) })] }), _jsxs("label", { children: [_jsxs("span", { children: [copy.diastolic, " *"] }), _jsx("input", { "aria-label": copy.diastolic, required: true, type: "number", value: diastolic, onChange: (event) => setDiastolic(event.target.value) })] })] }) : _jsxs("label", { children: [_jsxs("span", { children: [copy.value, " *"] }), _jsx("input", { "aria-label": copy.value, required: true, type: "number", value: value, onChange: (event) => setValue(event.target.value) })] }), error ? _jsx("p", { className: "uhcp-clinical-editor-error", role: "alert", children: error }) : null, _jsxs("footer", { children: [_jsx("button", { type: "button", onClick: onCancel, children: copy.cancel }), _jsx("button", { type: "submit", disabled: saving, children: saving ? copy.saving : copy.save })] })] })] });
45
+ }
46
+ function unitFor(kind) {
47
+ switch (kind) {
48
+ case 'temperature': return VitalSignUnit.temperature;
49
+ case 'heart-rate': return VitalSignUnit.heartRate;
50
+ case 'oxygen-saturation': return VitalSignUnit.oxygenSaturation;
51
+ case 'respiratory-rate': return VitalSignUnit.respiratoryRate;
52
+ case 'body-weight': return VitalSignUnit.bodyWeight;
53
+ }
54
+ }
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export * from './PortalLoadingSkeleton.js';
9
9
  export * from './ClinicalSectionSummary.js';
10
10
  export * from './IpsBundleSummary.js';
11
11
  export * from './ClinicalArtifactEditor.js';
12
+ export * from './VitalSignArtifactEditor.js';
12
13
  export * from './InvitationAcceptancePanel.js';
13
14
  export * from './SubjectAccessRequestPanel.js';
14
15
  export * from './SoschainWorkspace.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,sCAAsC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,sCAAsC,CAAA"}
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ export * from './PortalLoadingSkeleton.js';
9
9
  export * from './ClinicalSectionSummary.js';
10
10
  export * from './IpsBundleSummary.js';
11
11
  export * from './ClinicalArtifactEditor.js';
12
+ export * from './VitalSignArtifactEditor.js';
12
13
  export * from './InvitationAcceptancePanel.js';
13
14
  export * from './SubjectAccessRequestPanel.js';
14
15
  export * from './SoschainWorkspace.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uhc-portal-components-react",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "Brand-neutral React portal shell, account preferences and protected-profile UI for UHC and VetChain portals.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -31,6 +31,7 @@
31
31
  "react-dom": ">=18.3.0"
32
32
  },
33
33
  "dependencies": {
34
+ "fhir-data-utils-ts": "0.6.7",
34
35
  "gdc-common-utils-ts": "^2.3.12"
35
36
  },
36
37
  "devDependencies": {