@eka-care/medical-records-ui 1.0.55 → 1.0.57
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/{OriginalRecordPanel-PR35G6KV.js → OriginalRecordPanel-DCGRXQST.js} +6 -4
- package/dist/{OriginalRecordPanel-QYGV744W.mjs.map → OriginalRecordPanel-DCGRXQST.js.map} +1 -1
- package/dist/{OriginalRecordPanel-QYGV744W.mjs → OriginalRecordPanel-NGLSSJLE.mjs} +6 -4
- package/dist/OriginalRecordPanel-NGLSSJLE.mjs.map +1 -0
- package/dist/{VitalHistoryPanel-76GSKJPJ.mjs → VitalHistoryPanel-FT5VMJ37.mjs} +2 -2
- package/dist/VitalHistoryPanel-VQQ27P6Q.js +10 -0
- package/dist/{VitalHistoryPanel-7GT3GZEJ.js.map → VitalHistoryPanel-VQQ27P6Q.js.map} +1 -1
- package/dist/{chunk-IIAX5R33.mjs → chunk-5TPILQYM.mjs} +8 -5
- package/dist/chunk-5TPILQYM.mjs.map +1 -0
- package/dist/{chunk-636WE5XC.js → chunk-KTHLLAAG.js} +8 -5
- package/dist/chunk-KTHLLAAG.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/package.json +1 -1
- package/dist/OriginalRecordPanel-PR35G6KV.js.map +0 -1
- package/dist/VitalHistoryPanel-7GT3GZEJ.js +0 -10
- package/dist/chunk-636WE5XC.js.map +0 -1
- package/dist/chunk-IIAX5R33.mjs.map +0 -1
- /package/dist/{VitalHistoryPanel-76GSKJPJ.mjs.map → VitalHistoryPanel-FT5VMJ37.mjs.map} +0 -0
|
@@ -137,19 +137,21 @@ function OriginalRecordPanel({
|
|
|
137
137
|
srAllSelected ? /* @__PURE__ */ new Set() : new Set(filteredRows.map((r) => r.key))
|
|
138
138
|
);
|
|
139
139
|
}, [srAllSelected, filteredRows]);
|
|
140
|
-
const handleSrCopyToNote = _react.useCallback.call(void 0, () => {
|
|
140
|
+
const handleSrCopyToNote = _react.useCallback.call(void 0, async () => {
|
|
141
141
|
const selectedRows = filteredRows.filter((r) => srSelected.has(r.key));
|
|
142
142
|
if (!selectedRows.length) return;
|
|
143
143
|
const text = buildVitalsText(selectedRows);
|
|
144
144
|
if (onCopyVitalsToNote) {
|
|
145
|
-
|
|
145
|
+
await onCopyVitalsToNote(text);
|
|
146
|
+
setSrSelected(/* @__PURE__ */ new Set());
|
|
146
147
|
} else if (onCopyToNote) {
|
|
147
148
|
const rect = _optionalChain([srCopyBtnRef, 'access', _4 => _4.current, 'optionalAccess', _5 => _5.getBoundingClientRect, 'call', _6 => _6()]);
|
|
148
|
-
|
|
149
|
+
const result = await onCopyToNote(
|
|
149
150
|
text,
|
|
150
151
|
rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : void 0,
|
|
151
152
|
_chunkQYUEKKMVjs.toVitalNoteRows.call(void 0, selectedRows)
|
|
152
153
|
);
|
|
154
|
+
if (result !== false) setSrSelected(/* @__PURE__ */ new Set());
|
|
153
155
|
}
|
|
154
156
|
}, [filteredRows, srSelected, onCopyVitalsToNote, onCopyToNote]);
|
|
155
157
|
const htmlCopyBtnRef = _react.useRef.call(void 0, null);
|
|
@@ -487,4 +489,4 @@ function VitalReadingsExpanded({ vitalName, ekaId }) {
|
|
|
487
489
|
|
|
488
490
|
|
|
489
491
|
exports.OriginalRecordPanel = OriginalRecordPanel;
|
|
490
|
-
//# sourceMappingURL=OriginalRecordPanel-
|
|
492
|
+
//# sourceMappingURL=OriginalRecordPanel-DCGRXQST.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/views/components/shared/OriginalRecordPanel.tsx"],"sourcesContent":["\"use client\";\n\nimport { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { ChevronLeft, ChevronRight, ChevronDown, ExternalLink, Check, File, LoaderCircle } from \"lucide-react\";\nimport { useStore } from \"zustand\";\nimport { useSdk } from \"../../../connection/useSdk\";\nimport { useRecordPreview } from \"../../../connection/useRecordPreview\";\nimport { useRecordPanelTable } from \"../../hooks/care-panel/useRecordPanelTable\";\nimport { useParameterTrend } from \"../../hooks/care-panel/useParameterTrend\";\nimport { epochToDisplay } from \"../../../helpers/formatters\";\nimport type { ParameterTrendResponse } from \"@eka-care/medical-records-ts-sdk\";\nimport { useSmartRecordsActions } from \"../../context/SmartRecordsActionsContext\";\nimport { IconButton, Typography, SearchInput, Tooltip } from \"widgets\";\nimport type { RecordItem } from \"../../../helpers\";\nimport type { PanelRow } from \"../../../helpers/vitalsPanel\";\nimport { toVitalNoteRows } from \"../../../helpers/vitalsPanel\";\nimport SmartSparkles from \"icons/SmartSparkles\";\n\nconst DocumentViewer = lazy(() =>\n import(\"../../RecordPreview/DocumentViewer\").then((m) => ({\n default: m.DocumentViewer,\n })),\n);\n\ninterface OriginalRecordPanelProps {\n recordId: string;\n caseId?: string;\n onBack: () => void;\n}\n\ntype SrTab = \"all\" | \"oor\" | \"none\";\n\nfunction buildVitalsText(rows: PanelRow[]): string {\n return rows\n .map((r) => {\n const cell = r.cells[0];\n const ref = cell?.refRange ? ` (Ref: ${cell.refRange})` : \"\";\n return `${r.name}: ${cell?.value ?? \"—\"} ${r.unit}${ref}`;\n })\n .join(\"\\n\");\n}\n\nexport function OriginalRecordPanel({\n recordId,\n caseId,\n onBack,\n}: OriginalRecordPanelProps) {\n const { store } = useSdk();\n const record = useStore(store, (s) => s.records.byId[recordId]);\n const recordsById = useStore(store, (s) => s.records.byId);\n const preview = useRecordPreview(recordId);\n const { replaceOriginal, onCopyToNote, onCopyVitalsToNote, hasCopyToNote, onToast } =\n useSmartRecordsActions();\n\n // Smart report vitals (only fetched when record.isSmart)\n const { status: vitalsStatus, table } = useRecordPanelTable(\n record?.isSmart ? recordId : null,\n );\n const [smartPanelOpen, setSmartPanelOpen] = useState(true);\n const [srSearch, setSrSearch] = useState(\"\");\n const [srTab, setSrTab] = useState<SrTab>(\"all\");\n const [expandedVital, setExpandedVital] = useState<string | null>(null);\n const toggleExpand = useCallback((key: string) => {\n setExpandedVital((prev) => (prev === key ? null : key));\n }, []);\n const [srSelected, setSrSelected] = useState<Set<string>>(new Set());\n const srCopyBtnRef = useRef<HTMLButtonElement>(null);\n\n // Dropdown state\n const [dropdownOpen, setDropdownOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!dropdownOpen) return;\n const handler = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setDropdownOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [dropdownOpen]);\n\n const caseRecords = useMemo<RecordItem[]>(() => {\n if (!caseId) return [];\n return Object.values(recordsById)\n .filter(\n (r): r is RecordItem =>\n r != null &&\n (caseId === \"__ungrouped__\" ? r.cases.length === 0 : r.cases.includes(caseId)),\n )\n .sort((a, b) => b.createdAtEpoch - a.createdAtEpoch);\n }, [recordsById, caseId]);\n\n const currentIndex = caseRecords.findIndex((r) => r.id === recordId);\n const total = caseRecords.length;\n const isUngrouped = caseId === \"__ungrouped__\";\n\n const goTo = useCallback(\n (r: RecordItem) => {\n setDropdownOpen(false);\n replaceOriginal(r.id, caseId);\n },\n [replaceOriginal, caseId],\n );\n\n const goPrev = useCallback(() => {\n if (currentIndex > 0) goTo(caseRecords[currentIndex - 1]);\n }, [currentIndex, caseRecords, goTo]);\n\n const goNext = useCallback(() => {\n if (currentIndex < total - 1) goTo(caseRecords[currentIndex + 1]);\n }, [currentIndex, total, caseRecords, goTo]);\n\n const showNavPicker = caseId && total > 0;\n\n // Smart report vitals filtering\n const allRows = table.rows;\n const oorRows = useMemo(\n () => allRows.filter((r) => r.latestStatus === \"high\" || r.latestStatus === \"low\"),\n [allRows],\n );\n const noInterpRows = useMemo(\n () => allRows.filter((r) => r.latestStatus === \"unknown\"),\n [allRows],\n );\n\n const baseRows = srTab === \"oor\" ? oorRows : srTab === \"none\" ? noInterpRows : allRows;\n\n const filteredRows = useMemo(() => {\n if (!srSearch) return baseRows;\n const q = srSearch.toLowerCase();\n return baseRows.filter((r) => r.name.toLowerCase().includes(q));\n }, [baseRows, srSearch]);\n\n const tabCounts = useMemo(() => {\n if (!srSearch) return { all: allRows.length, oor: oorRows.length, none: noInterpRows.length };\n const q = srSearch.toLowerCase();\n return {\n all: allRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n oor: oorRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n none: noInterpRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n };\n }, [srSearch, allRows, oorRows, noInterpRows]);\n\n useEffect(() => {\n setSrSelected(new Set());\n }, [srTab, srSearch]);\n\n useEffect(() => {\n if (srTab === \"oor\" && oorRows.length === 0) setSrTab(\"all\");\n if (srTab === \"none\" && noInterpRows.length === 0) setSrTab(\"all\");\n }, [srTab, oorRows.length, noInterpRows.length]);\n\n const srAllSelected =\n filteredRows.length > 0 && filteredRows.every((r) => srSelected.has(r.key));\n const srSomeSelected = srSelected.size > 0;\n\n const toggleSrRow = useCallback((key: string) => {\n setSrSelected((prev) => {\n const next = new Set(prev);\n next.has(key) ? next.delete(key) : next.add(key);\n return next;\n });\n }, []);\n\n const toggleSrAll = useCallback(() => {\n setSrSelected(\n srAllSelected ? new Set() : new Set(filteredRows.map((r) => r.key)),\n );\n }, [srAllSelected, filteredRows]);\n\n const handleSrCopyToNote = useCallback(() => {\n const selectedRows = filteredRows.filter((r) => srSelected.has(r.key));\n if (!selectedRows.length) return;\n const text = buildVitalsText(selectedRows);\n if (onCopyVitalsToNote) {\n void onCopyVitalsToNote(text);\n } else if (onCopyToNote) {\n const rect = srCopyBtnRef.current?.getBoundingClientRect();\n void onCopyToNote(\n text,\n rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : undefined,\n toVitalNoteRows(selectedRows),\n );\n }\n }, [filteredRows, srSelected, onCopyVitalsToNote, onCopyToNote]);\n\n const htmlCopyBtnRef = useRef<HTMLButtonElement>(null);\n const [isHtmlCopying, setIsHtmlCopying] = useState(false);\n\n const handleHtmlCopyToNote = useCallback(async () => {\n const url = preview.files[0]?.url;\n if (!url) return;\n setIsHtmlCopying(true);\n try {\n const res = await fetch(url);\n const html = await res.text();\n const doc = new DOMParser().parseFromString(html, \"text/html\");\n const text = doc.body.textContent?.trim() ?? \"\";\n if (!text) return;\n if (onCopyVitalsToNote) {\n void onCopyVitalsToNote(text);\n } else if (onCopyToNote) {\n const rect = htmlCopyBtnRef.current?.getBoundingClientRect();\n void onCopyToNote(\n text,\n rect ? { x: rect.left, y: rect.bottom } : undefined,\n );\n }\n } catch {\n onToast?.(\"Failed to copy document text\", \"error\");\n } finally {\n setIsHtmlCopying(false);\n }\n }, [preview.files, onCopyVitalsToNote, onCopyToNote, onToast]);\n\n const isSmart = record?.isSmart ?? false;\n const hasPreview = preview.status === \"loaded\" && preview.files.length > 0;\n\n return (\n <div className=\"mr-sv__panel\">\n <div className=\"mr-sv__panel-header\">\n <button type=\"button\" className=\"mr-sv__back-btn\" onClick={onBack}>\n <ChevronLeft size={16} aria-hidden />\n Back\n </button>\n\n {/* Prev/next record carousel + dropdown — temporarily disabled, will re-enable later.\n {showNavPicker ? (\n <div className=\"mr-orig__nav-wrap\" ref={dropdownRef}>\n <div\n className={`mr-orig__nav-pill${dropdownOpen ? \" mr-orig__nav-pill--open\" : \"\"}`}\n role=\"button\"\n tabIndex={0}\n onClick={() => setDropdownOpen((v) => !v)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setDropdownOpen((v) => !v);\n }\n }}\n >\n <button\n type=\"button\"\n className=\"mr-orig__nav-chevron\"\n onClick={(e) => { e.stopPropagation(); goPrev(); }}\n aria-label=\"Previous record\"\n disabled={currentIndex <= 0}\n >\n <ChevronLeft size={14} aria-hidden />\n </button>\n <div className=\"mr-orig__nav-text\">\n <span className=\"mr-orig__nav-title\">{record?.title ?? \"Record\"}</span>\n <span className=\"mr-orig__nav-counter\">\n {currentIndex + 1} of {total}\n </span>\n </div>\n <button\n type=\"button\"\n className=\"mr-orig__nav-chevron\"\n onClick={(e) => { e.stopPropagation(); goNext(); }}\n aria-label=\"Next record\"\n disabled={currentIndex >= total - 1}\n >\n <ChevronRight size={14} aria-hidden />\n </button>\n </div>\n\n {dropdownOpen && (\n <div className=\"mr-orig__dropdown\">\n <div className=\"mr-orig__dropdown-eyebrow\">\n {total} RECORD{total !== 1 ? \"S\" : \"\"}{\" \"}\n {isUngrouped ? \"WITH NO CARE CONTEXT\" : \"FOUND IN THIS ENCOUNTER\"}\n </div>\n <div className=\"mr-orig__dropdown-list\">\n {caseRecords.map((r) => {\n const isActive = r.id === recordId;\n return (\n <button\n key={r.id}\n type=\"button\"\n className={`mr-orig__dropdown-item${isActive ? \" mr-orig__dropdown-item--active\" : \"\"}`}\n onClick={() => goTo(r)}\n >\n <div className=\"mr-orig__dropdown-icon\">\n <File size={16} aria-hidden />\n {r.isSmart && (\n <SmartSparkles\n className=\"mr-orig__dropdown-smart-dot\"\n aria-label=\"Smart report\"\n />\n )}\n </div>\n <div className=\"mr-orig__dropdown-info\">\n <div className=\"mr-orig__dropdown-title-row\">\n <span className=\"mr-orig__dropdown-title\">{r.title}</span>\n {r.isSmart && (\n <span className=\"mr-orig__dropdown-smart-badge\">\n <SmartSparkles aria-hidden />\n Smart Report\n </span>\n )}\n {r.fileType?.toUpperCase() === \"HTML\" && (\n <span className=\"mr-tag-chip mr-tag-chip--html\">\n <span className=\"mr-tag-chip__label\">HTML</span>\n </span>\n )}\n </div>\n <div className=\"mr-orig__dropdown-meta\">\n <span>{epochToDisplay(r.createdAtEpoch)}</span>\n {r.isSmart && r.totalVitals > 0 && (\n <>\n <span className=\"mr-orig__dropdown-dot\">·</span>\n <span>{r.totalVitals} vitals</span>\n </>\n )}\n </div>\n </div>\n {isActive && (\n <Check\n size={14}\n className=\"mr-orig__dropdown-check\"\n aria-hidden\n />\n )}\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n ) : record ? (\n */}\n {record ? (\n <div className=\"mr-sv__panel-info\">\n <Typography variant=\"label\" as=\"span\" className=\"mr-sv__panel-name\">\n {record.title}\n </Typography>\n <Typography variant=\"hint\" as=\"span\" className=\"mr-sv__panel-meta-text\">\n {epochToDisplay(record.createdAtEpoch)}\n </Typography>\n </div>\n ) : null}\n {/* } */}\n\n <div className=\"mr-orig__header-actions\">\n {preview.isHtml && hasCopyToNote && (\n <button\n ref={htmlCopyBtnRef}\n type=\"button\"\n className=\"mr-orig__html-copy-btn\"\n onClick={handleHtmlCopyToNote}\n disabled={isHtmlCopying}\n >\n {isHtmlCopying && <LoaderCircle size={12} className=\"mr-sv__loading-spinner\" aria-hidden />}\n Copy to note\n </button>\n )}\n {hasPreview && (\n <IconButton\n icon={<ExternalLink size={16} aria-hidden />}\n label=\"Open in new tab\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() =>\n window.open(preview.files[0].url, \"_blank\", \"noopener,noreferrer\")\n }\n />\n )}\n </div>\n </div>\n\n <div\n className=\"mr-sv__panel-body\"\n style={{ flex: 1, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}\n >\n {preview.status === \"loading\" && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n }}\n >\n <LoaderCircle size={44} className=\"mr-sv__loading-spinner\" aria-hidden />\n </div>\n )}\n {preview.status === \"error\" && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n Failed to load document preview.\n </Typography>\n )}\n {preview.status === \"loaded\" && preview.files.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No preview available for this record.\n </Typography>\n )}\n\n {/* Non-smart: full-width PDF */}\n {hasPreview && !isSmart && (\n <div\n className=\"mr-record-preview__body\"\n style={{ flex: 1, display: \"flex\", overflow: \"hidden\" }}\n >\n <Suspense fallback={null}>\n <DocumentViewer\n files={preview.files}\n title={record?.title ?? \"\"}\n isHtml={preview.isHtml}\n />\n </Suspense>\n </div>\n )}\n\n {/* Smart: split view — PDF left, smart report panel right */}\n {hasPreview && isSmart && (\n <div className=\"mr-orig__split\">\n <div className=\"mr-orig__pdf-side\">\n <Suspense fallback={null}>\n <DocumentViewer\n files={preview.files}\n title={record?.title ?? \"\"}\n isHtml={preview.isHtml}\n />\n </Suspense>\n </div>\n\n {smartPanelOpen ? (\n <div className=\"mr-orig__smart-side\">\n {/* Header */}\n <div className=\"mr-orig__smart-hdr\">\n <span className=\"mr-orig__smart-title-row\">\n <span className=\"mr-orig__smart-title\">Smart Report</span>\n <SmartSparkles className=\"mr-orig__smart-title-icon\" aria-hidden />\n </span>\n <button\n type=\"button\"\n className=\"mr-sv__sidebar-collapse-btn mr-orig__smart-expanded-btn\"\n aria-label=\"Collapse smart report panel\"\n aria-expanded={true}\n onClick={() => setSmartPanelOpen(false)}\n >\n <ChevronRight size={14} aria-hidden />\n </button>\n </div>\n\n {/* Search */}\n <SearchInput\n className=\"mr-orig__smart-search\"\n iconSize={16}\n placeholder=\"Search vitals\"\n value={srSearch}\n onChange={setSrSearch}\n />\n\n {/* Filter tabs — only when at least one sub-category has data */}\n {(oorRows.length > 0 || noInterpRows.length > 0) && (\n <div className=\"mr-orig__smart-tabs-wrap\">\n <div className=\"mr-orig__smart-tabs\">\n {([\"all\", \"oor\", \"none\"] as SrTab[]).map((tab) => {\n if (tab === \"oor\" && oorRows.length === 0) return null;\n if (tab === \"none\" && noInterpRows.length === 0) return null;\n const count =\n tab === \"all\"\n ? tabCounts.all\n : tab === \"oor\"\n ? tabCounts.oor\n : tabCounts.none;\n const label =\n tab === \"all\"\n ? \"All\"\n : tab === \"oor\"\n ? \"Out of range\"\n : \"No interpretation\";\n return (\n <button\n key={tab}\n type=\"button\"\n className={`mr-orig__smart-tab${srTab === tab ? \" mr-orig__smart-tab--active\" : \"\"}`}\n onClick={() => setSrTab(tab)}\n >\n {label} ({count})\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Vital list */}\n <div className=\"mr-orig__smart-list\">\n {vitalsStatus === \"loading\" && (\n <div className=\"mr-orig__smart-loading\">\n <LoaderCircle\n size={20}\n className=\"mr-sv__loading-spinner\"\n aria-hidden\n />\n </div>\n )}\n {vitalsStatus === \"loaded\" && filteredRows.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-orig__smart-empty\">\n No vitals match.\n </Typography>\n )}\n {vitalsStatus === \"loaded\" &&\n filteredRows.map((row, idx) => {\n const cell = row.cells[0];\n const isOor =\n row.latestStatus === \"high\" || row.latestStatus === \"low\";\n const isSelected = srSelected.has(row.key);\n const isLast = idx === filteredRows.length - 1;\n return (\n <div\n key={row.key}\n className={`mr-orig__vital-item${isLast ? \" mr-orig__vital-item--last\" : \"\"}`}\n >\n <div\n className={`mr-orig__vital-row mr-orig__vital-row--selectable${isSelected ? \" mr-orig__vital-row--selected\" : \"\"}`}\n onClick={() => toggleSrRow(row.key)}\n >\n <span\n className={`mr-sv__checkbox mr-cc-table__row-check${isSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n toggleSrRow(row.key);\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n toggleSrRow(row.key);\n }\n }}\n >\n {isSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <div className=\"mr-orig__vital-info\">\n <span className=\"mr-orig__vital-name\">{row.name}</span>\n {row.refRange && (\n <span className=\"mr-orig__vital-ref\">\n Ref {row.refRange}\n </span>\n )}\n </div>\n {cell && (\n <div className=\"mr-orig__vital-value\">\n <span\n className={`mr-orig__vital-val${isOor ? \" mr-orig__vital-val--oor\" : \"\"}`}\n >\n {cell.value}\n </span>\n {cell.unit && (\n <span className=\"mr-orig__vital-unit\">{cell.unit}</span>\n )}\n </div>\n )}\n {row.ekaId && (\n <button\n type=\"button\"\n className={`mr-orig__vital-expand-btn${expandedVital === row.key ? \" mr-orig__vital-expand-btn--open\" : \"\"}`}\n onClick={(e) => { e.stopPropagation(); toggleExpand(row.key); }}\n aria-label={expandedVital === row.key ? \"Collapse readings\" : \"Show latest readings\"}\n >\n <ChevronDown size={13} aria-hidden />\n </button>\n )}\n </div>\n {expandedVital === row.key && row.ekaId && (\n <VitalReadingsExpanded vitalName={row.name} ekaId={row.ekaId} />\n )}\n </div>\n );\n })}\n </div>\n\n {/* Footer */}\n <div className=\"mr-cc-table__footer\">\n <span\n className={`mr-sv__checkbox mr-cc-table__footer-check${srAllSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={srAllSelected}\n tabIndex={0}\n onClick={toggleSrAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleSrAll();\n }\n }}\n >\n {srAllSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <span className=\"mr-cc-table__footer-label\" onClick={toggleSrAll}>Select all</span>\n <span className=\"mr-cc-table__footer-count\">\n {srSelected.size} of {filteredRows.length} selected\n </span>\n <button\n ref={srCopyBtnRef}\n type=\"button\"\n className=\"mr-cc-table__copy-note-btn\"\n disabled={!srSomeSelected || !hasCopyToNote}\n onClick={handleSrCopyToNote}\n >\n Copy to note\n </button>\n </div>\n </div>\n ) : (\n <div className=\"mr-orig__smart-side mr-orig__smart-side--collapsed\">\n <Tooltip content=\"Show smart report\">\n <button\n type=\"button\"\n className=\"mr-sv__sidebar-collapse-btn mr-orig__smart-collapsed-btn\"\n aria-label=\"Expand smart report panel\"\n aria-expanded={false}\n onClick={() => setSmartPanelOpen(true)}\n >\n <span className=\"mr-orig__smart-collapsed-icon-wrap\">\n <SmartSparkles className=\"mr-orig__smart-collapsed-icon\" aria-hidden />\n </span>\n </button>\n </Tooltip>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction VitalReadingsExpanded({ vitalName, ekaId }: { vitalName: string; ekaId: string }) {\n const { data: trendData, status } = useParameterTrend(ekaId);\n\n const readings = useMemo(() => {\n const trend = trendData as ParameterTrendResponse | null;\n if (!trend?.vitals_info?.length) return [];\n return [...trend.vitals_info]\n .sort((a, b) => (b.date ?? 0) - (a.date ?? 0))\n .slice(0, 3)\n .map((info) => {\n const dr = (info.display_result ?? \"\").toLowerCase();\n const isOor = dr.includes(\"high\") || dr.includes(\"above\") || dr.includes(\"abnormal_high\") ||\n dr.includes(\"low\") || dr.includes(\"below\") || dr.includes(\"abnormal_low\");\n return {\n value: info.val != null ? String(info.val) : ((info as any).val_string ?? \"—\"),\n date: (info.display_time || \"\").replace(/['‘’]/g, \" \"),\n isOor,\n };\n });\n }, [trendData]);\n\n if (status === \"loading\") {\n return (\n <div className=\"mr-orig__vital-readings mr-orig__vital-readings--loading\">\n <LoaderCircle size={16} className=\"mr-sv__loading-spinner\" aria-hidden />\n </div>\n );\n }\n\n if (status === \"error\" || !readings.length) {\n return (\n <div className=\"mr-orig__vital-readings\">\n <Typography variant=\"muted\" className=\"mr-orig__vital-readings-empty\">\n No readings available\n </Typography>\n </div>\n );\n }\n\n return (\n <div className=\"mr-orig__vital-readings\">\n <div className=\"mr-orig__vital-readings-title\">\n LATEST READINGS FOR {vitalName.toUpperCase()}\n </div>\n <div className=\"mr-orig__vital-readings-grid\">\n {readings.map((r, i) => (\n <div key={i} className=\"mr-orig__vital-reading-item\">\n <span className={`mr-orig__vital-reading-value${r.isOor ? \" mr-orig__vital-reading-value--oor\" : \"\"}`}>{r.value}</span>\n <span className=\"mr-orig__vital-reading-date\">{r.date}</span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/medical-records-ui/medical-records-ui/dist/OriginalRecordPanel-DCGRXQST.js","../src/views/components/shared/OriginalRecordPanel.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/medical-records-ui/medical-records-ui/dist/OriginalRecordPanel-DCGRXQST.js","sourcesContent":[null,"\"use client\";\n\nimport { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { ChevronLeft, ChevronRight, ChevronDown, ExternalLink, Check, File, LoaderCircle } from \"lucide-react\";\nimport { useStore } from \"zustand\";\nimport { useSdk } from \"../../../connection/useSdk\";\nimport { useRecordPreview } from \"../../../connection/useRecordPreview\";\nimport { useRecordPanelTable } from \"../../hooks/care-panel/useRecordPanelTable\";\nimport { useParameterTrend } from \"../../hooks/care-panel/useParameterTrend\";\nimport { epochToDisplay } from \"../../../helpers/formatters\";\nimport type { ParameterTrendResponse } from \"@eka-care/medical-records-ts-sdk\";\nimport { useSmartRecordsActions } from \"../../context/SmartRecordsActionsContext\";\nimport { IconButton, Typography, SearchInput, Tooltip } from \"widgets\";\nimport type { RecordItem } from \"../../../helpers\";\nimport type { PanelRow } from \"../../../helpers/vitalsPanel\";\nimport { toVitalNoteRows } from \"../../../helpers/vitalsPanel\";\nimport SmartSparkles from \"icons/SmartSparkles\";\n\nconst DocumentViewer = lazy(() =>\n import(\"../../RecordPreview/DocumentViewer\").then((m) => ({\n default: m.DocumentViewer,\n })),\n);\n\ninterface OriginalRecordPanelProps {\n recordId: string;\n caseId?: string;\n onBack: () => void;\n}\n\ntype SrTab = \"all\" | \"oor\" | \"none\";\n\nfunction buildVitalsText(rows: PanelRow[]): string {\n return rows\n .map((r) => {\n const cell = r.cells[0];\n const ref = cell?.refRange ? ` (Ref: ${cell.refRange})` : \"\";\n return `${r.name}: ${cell?.value ?? \"—\"} ${r.unit}${ref}`;\n })\n .join(\"\\n\");\n}\n\nexport function OriginalRecordPanel({\n recordId,\n caseId,\n onBack,\n}: OriginalRecordPanelProps) {\n const { store } = useSdk();\n const record = useStore(store, (s) => s.records.byId[recordId]);\n const recordsById = useStore(store, (s) => s.records.byId);\n const preview = useRecordPreview(recordId);\n const { replaceOriginal, onCopyToNote, onCopyVitalsToNote, hasCopyToNote, onToast } =\n useSmartRecordsActions();\n\n // Smart report vitals (only fetched when record.isSmart)\n const { status: vitalsStatus, table } = useRecordPanelTable(\n record?.isSmart ? recordId : null,\n );\n const [smartPanelOpen, setSmartPanelOpen] = useState(true);\n const [srSearch, setSrSearch] = useState(\"\");\n const [srTab, setSrTab] = useState<SrTab>(\"all\");\n const [expandedVital, setExpandedVital] = useState<string | null>(null);\n const toggleExpand = useCallback((key: string) => {\n setExpandedVital((prev) => (prev === key ? null : key));\n }, []);\n const [srSelected, setSrSelected] = useState<Set<string>>(new Set());\n const srCopyBtnRef = useRef<HTMLButtonElement>(null);\n\n // Dropdown state\n const [dropdownOpen, setDropdownOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!dropdownOpen) return;\n const handler = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setDropdownOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [dropdownOpen]);\n\n const caseRecords = useMemo<RecordItem[]>(() => {\n if (!caseId) return [];\n return Object.values(recordsById)\n .filter(\n (r): r is RecordItem =>\n r != null &&\n (caseId === \"__ungrouped__\" ? r.cases.length === 0 : r.cases.includes(caseId)),\n )\n .sort((a, b) => b.createdAtEpoch - a.createdAtEpoch);\n }, [recordsById, caseId]);\n\n const currentIndex = caseRecords.findIndex((r) => r.id === recordId);\n const total = caseRecords.length;\n const isUngrouped = caseId === \"__ungrouped__\";\n\n const goTo = useCallback(\n (r: RecordItem) => {\n setDropdownOpen(false);\n replaceOriginal(r.id, caseId);\n },\n [replaceOriginal, caseId],\n );\n\n const goPrev = useCallback(() => {\n if (currentIndex > 0) goTo(caseRecords[currentIndex - 1]);\n }, [currentIndex, caseRecords, goTo]);\n\n const goNext = useCallback(() => {\n if (currentIndex < total - 1) goTo(caseRecords[currentIndex + 1]);\n }, [currentIndex, total, caseRecords, goTo]);\n\n const showNavPicker = caseId && total > 0;\n\n // Smart report vitals filtering\n const allRows = table.rows;\n const oorRows = useMemo(\n () => allRows.filter((r) => r.latestStatus === \"high\" || r.latestStatus === \"low\"),\n [allRows],\n );\n const noInterpRows = useMemo(\n () => allRows.filter((r) => r.latestStatus === \"unknown\"),\n [allRows],\n );\n\n const baseRows = srTab === \"oor\" ? oorRows : srTab === \"none\" ? noInterpRows : allRows;\n\n const filteredRows = useMemo(() => {\n if (!srSearch) return baseRows;\n const q = srSearch.toLowerCase();\n return baseRows.filter((r) => r.name.toLowerCase().includes(q));\n }, [baseRows, srSearch]);\n\n const tabCounts = useMemo(() => {\n if (!srSearch) return { all: allRows.length, oor: oorRows.length, none: noInterpRows.length };\n const q = srSearch.toLowerCase();\n return {\n all: allRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n oor: oorRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n none: noInterpRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n };\n }, [srSearch, allRows, oorRows, noInterpRows]);\n\n useEffect(() => {\n setSrSelected(new Set());\n }, [srTab, srSearch]);\n\n useEffect(() => {\n if (srTab === \"oor\" && oorRows.length === 0) setSrTab(\"all\");\n if (srTab === \"none\" && noInterpRows.length === 0) setSrTab(\"all\");\n }, [srTab, oorRows.length, noInterpRows.length]);\n\n const srAllSelected =\n filteredRows.length > 0 && filteredRows.every((r) => srSelected.has(r.key));\n const srSomeSelected = srSelected.size > 0;\n\n const toggleSrRow = useCallback((key: string) => {\n setSrSelected((prev) => {\n const next = new Set(prev);\n next.has(key) ? next.delete(key) : next.add(key);\n return next;\n });\n }, []);\n\n const toggleSrAll = useCallback(() => {\n setSrSelected(\n srAllSelected ? new Set() : new Set(filteredRows.map((r) => r.key)),\n );\n }, [srAllSelected, filteredRows]);\n\n const handleSrCopyToNote = useCallback(async () => {\n const selectedRows = filteredRows.filter((r) => srSelected.has(r.key));\n if (!selectedRows.length) return;\n const text = buildVitalsText(selectedRows);\n if (onCopyVitalsToNote) {\n await onCopyVitalsToNote(text);\n setSrSelected(new Set());\n } else if (onCopyToNote) {\n const rect = srCopyBtnRef.current?.getBoundingClientRect();\n const result = await onCopyToNote(\n text,\n rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : undefined,\n toVitalNoteRows(selectedRows),\n );\n if (result !== false) setSrSelected(new Set());\n }\n }, [filteredRows, srSelected, onCopyVitalsToNote, onCopyToNote]);\n\n const htmlCopyBtnRef = useRef<HTMLButtonElement>(null);\n const [isHtmlCopying, setIsHtmlCopying] = useState(false);\n\n const handleHtmlCopyToNote = useCallback(async () => {\n const url = preview.files[0]?.url;\n if (!url) return;\n setIsHtmlCopying(true);\n try {\n const res = await fetch(url);\n const html = await res.text();\n const doc = new DOMParser().parseFromString(html, \"text/html\");\n const text = doc.body.textContent?.trim() ?? \"\";\n if (!text) return;\n if (onCopyVitalsToNote) {\n void onCopyVitalsToNote(text);\n } else if (onCopyToNote) {\n const rect = htmlCopyBtnRef.current?.getBoundingClientRect();\n void onCopyToNote(\n text,\n rect ? { x: rect.left, y: rect.bottom } : undefined,\n );\n }\n } catch {\n onToast?.(\"Failed to copy document text\", \"error\");\n } finally {\n setIsHtmlCopying(false);\n }\n }, [preview.files, onCopyVitalsToNote, onCopyToNote, onToast]);\n\n const isSmart = record?.isSmart ?? false;\n const hasPreview = preview.status === \"loaded\" && preview.files.length > 0;\n\n return (\n <div className=\"mr-sv__panel\">\n <div className=\"mr-sv__panel-header\">\n <button type=\"button\" className=\"mr-sv__back-btn\" onClick={onBack}>\n <ChevronLeft size={16} aria-hidden />\n Back\n </button>\n\n {/* Prev/next record carousel + dropdown — temporarily disabled, will re-enable later.\n {showNavPicker ? (\n <div className=\"mr-orig__nav-wrap\" ref={dropdownRef}>\n <div\n className={`mr-orig__nav-pill${dropdownOpen ? \" mr-orig__nav-pill--open\" : \"\"}`}\n role=\"button\"\n tabIndex={0}\n onClick={() => setDropdownOpen((v) => !v)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setDropdownOpen((v) => !v);\n }\n }}\n >\n <button\n type=\"button\"\n className=\"mr-orig__nav-chevron\"\n onClick={(e) => { e.stopPropagation(); goPrev(); }}\n aria-label=\"Previous record\"\n disabled={currentIndex <= 0}\n >\n <ChevronLeft size={14} aria-hidden />\n </button>\n <div className=\"mr-orig__nav-text\">\n <span className=\"mr-orig__nav-title\">{record?.title ?? \"Record\"}</span>\n <span className=\"mr-orig__nav-counter\">\n {currentIndex + 1} of {total}\n </span>\n </div>\n <button\n type=\"button\"\n className=\"mr-orig__nav-chevron\"\n onClick={(e) => { e.stopPropagation(); goNext(); }}\n aria-label=\"Next record\"\n disabled={currentIndex >= total - 1}\n >\n <ChevronRight size={14} aria-hidden />\n </button>\n </div>\n\n {dropdownOpen && (\n <div className=\"mr-orig__dropdown\">\n <div className=\"mr-orig__dropdown-eyebrow\">\n {total} RECORD{total !== 1 ? \"S\" : \"\"}{\" \"}\n {isUngrouped ? \"WITH NO CARE CONTEXT\" : \"FOUND IN THIS ENCOUNTER\"}\n </div>\n <div className=\"mr-orig__dropdown-list\">\n {caseRecords.map((r) => {\n const isActive = r.id === recordId;\n return (\n <button\n key={r.id}\n type=\"button\"\n className={`mr-orig__dropdown-item${isActive ? \" mr-orig__dropdown-item--active\" : \"\"}`}\n onClick={() => goTo(r)}\n >\n <div className=\"mr-orig__dropdown-icon\">\n <File size={16} aria-hidden />\n {r.isSmart && (\n <SmartSparkles\n className=\"mr-orig__dropdown-smart-dot\"\n aria-label=\"Smart report\"\n />\n )}\n </div>\n <div className=\"mr-orig__dropdown-info\">\n <div className=\"mr-orig__dropdown-title-row\">\n <span className=\"mr-orig__dropdown-title\">{r.title}</span>\n {r.isSmart && (\n <span className=\"mr-orig__dropdown-smart-badge\">\n <SmartSparkles aria-hidden />\n Smart Report\n </span>\n )}\n {r.fileType?.toUpperCase() === \"HTML\" && (\n <span className=\"mr-tag-chip mr-tag-chip--html\">\n <span className=\"mr-tag-chip__label\">HTML</span>\n </span>\n )}\n </div>\n <div className=\"mr-orig__dropdown-meta\">\n <span>{epochToDisplay(r.createdAtEpoch)}</span>\n {r.isSmart && r.totalVitals > 0 && (\n <>\n <span className=\"mr-orig__dropdown-dot\">·</span>\n <span>{r.totalVitals} vitals</span>\n </>\n )}\n </div>\n </div>\n {isActive && (\n <Check\n size={14}\n className=\"mr-orig__dropdown-check\"\n aria-hidden\n />\n )}\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n ) : record ? (\n */}\n {record ? (\n <div className=\"mr-sv__panel-info\">\n <Typography variant=\"label\" as=\"span\" className=\"mr-sv__panel-name\">\n {record.title}\n </Typography>\n <Typography variant=\"hint\" as=\"span\" className=\"mr-sv__panel-meta-text\">\n {epochToDisplay(record.createdAtEpoch)}\n </Typography>\n </div>\n ) : null}\n {/* } */}\n\n <div className=\"mr-orig__header-actions\">\n {preview.isHtml && hasCopyToNote && (\n <button\n ref={htmlCopyBtnRef}\n type=\"button\"\n className=\"mr-orig__html-copy-btn\"\n onClick={handleHtmlCopyToNote}\n disabled={isHtmlCopying}\n >\n {isHtmlCopying && <LoaderCircle size={12} className=\"mr-sv__loading-spinner\" aria-hidden />}\n Copy to note\n </button>\n )}\n {hasPreview && (\n <IconButton\n icon={<ExternalLink size={16} aria-hidden />}\n label=\"Open in new tab\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() =>\n window.open(preview.files[0].url, \"_blank\", \"noopener,noreferrer\")\n }\n />\n )}\n </div>\n </div>\n\n <div\n className=\"mr-sv__panel-body\"\n style={{ flex: 1, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}\n >\n {preview.status === \"loading\" && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n }}\n >\n <LoaderCircle size={44} className=\"mr-sv__loading-spinner\" aria-hidden />\n </div>\n )}\n {preview.status === \"error\" && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n Failed to load document preview.\n </Typography>\n )}\n {preview.status === \"loaded\" && preview.files.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No preview available for this record.\n </Typography>\n )}\n\n {/* Non-smart: full-width PDF */}\n {hasPreview && !isSmart && (\n <div\n className=\"mr-record-preview__body\"\n style={{ flex: 1, display: \"flex\", overflow: \"hidden\" }}\n >\n <Suspense fallback={null}>\n <DocumentViewer\n files={preview.files}\n title={record?.title ?? \"\"}\n isHtml={preview.isHtml}\n />\n </Suspense>\n </div>\n )}\n\n {/* Smart: split view — PDF left, smart report panel right */}\n {hasPreview && isSmart && (\n <div className=\"mr-orig__split\">\n <div className=\"mr-orig__pdf-side\">\n <Suspense fallback={null}>\n <DocumentViewer\n files={preview.files}\n title={record?.title ?? \"\"}\n isHtml={preview.isHtml}\n />\n </Suspense>\n </div>\n\n {smartPanelOpen ? (\n <div className=\"mr-orig__smart-side\">\n {/* Header */}\n <div className=\"mr-orig__smart-hdr\">\n <span className=\"mr-orig__smart-title-row\">\n <span className=\"mr-orig__smart-title\">Smart Report</span>\n <SmartSparkles className=\"mr-orig__smart-title-icon\" aria-hidden />\n </span>\n <button\n type=\"button\"\n className=\"mr-sv__sidebar-collapse-btn mr-orig__smart-expanded-btn\"\n aria-label=\"Collapse smart report panel\"\n aria-expanded={true}\n onClick={() => setSmartPanelOpen(false)}\n >\n <ChevronRight size={14} aria-hidden />\n </button>\n </div>\n\n {/* Search */}\n <SearchInput\n className=\"mr-orig__smart-search\"\n iconSize={16}\n placeholder=\"Search vitals\"\n value={srSearch}\n onChange={setSrSearch}\n />\n\n {/* Filter tabs — only when at least one sub-category has data */}\n {(oorRows.length > 0 || noInterpRows.length > 0) && (\n <div className=\"mr-orig__smart-tabs-wrap\">\n <div className=\"mr-orig__smart-tabs\">\n {([\"all\", \"oor\", \"none\"] as SrTab[]).map((tab) => {\n if (tab === \"oor\" && oorRows.length === 0) return null;\n if (tab === \"none\" && noInterpRows.length === 0) return null;\n const count =\n tab === \"all\"\n ? tabCounts.all\n : tab === \"oor\"\n ? tabCounts.oor\n : tabCounts.none;\n const label =\n tab === \"all\"\n ? \"All\"\n : tab === \"oor\"\n ? \"Out of range\"\n : \"No interpretation\";\n return (\n <button\n key={tab}\n type=\"button\"\n className={`mr-orig__smart-tab${srTab === tab ? \" mr-orig__smart-tab--active\" : \"\"}`}\n onClick={() => setSrTab(tab)}\n >\n {label} ({count})\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Vital list */}\n <div className=\"mr-orig__smart-list\">\n {vitalsStatus === \"loading\" && (\n <div className=\"mr-orig__smart-loading\">\n <LoaderCircle\n size={20}\n className=\"mr-sv__loading-spinner\"\n aria-hidden\n />\n </div>\n )}\n {vitalsStatus === \"loaded\" && filteredRows.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-orig__smart-empty\">\n No vitals match.\n </Typography>\n )}\n {vitalsStatus === \"loaded\" &&\n filteredRows.map((row, idx) => {\n const cell = row.cells[0];\n const isOor =\n row.latestStatus === \"high\" || row.latestStatus === \"low\";\n const isSelected = srSelected.has(row.key);\n const isLast = idx === filteredRows.length - 1;\n return (\n <div\n key={row.key}\n className={`mr-orig__vital-item${isLast ? \" mr-orig__vital-item--last\" : \"\"}`}\n >\n <div\n className={`mr-orig__vital-row mr-orig__vital-row--selectable${isSelected ? \" mr-orig__vital-row--selected\" : \"\"}`}\n onClick={() => toggleSrRow(row.key)}\n >\n <span\n className={`mr-sv__checkbox mr-cc-table__row-check${isSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n toggleSrRow(row.key);\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n toggleSrRow(row.key);\n }\n }}\n >\n {isSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <div className=\"mr-orig__vital-info\">\n <span className=\"mr-orig__vital-name\">{row.name}</span>\n {row.refRange && (\n <span className=\"mr-orig__vital-ref\">\n Ref {row.refRange}\n </span>\n )}\n </div>\n {cell && (\n <div className=\"mr-orig__vital-value\">\n <span\n className={`mr-orig__vital-val${isOor ? \" mr-orig__vital-val--oor\" : \"\"}`}\n >\n {cell.value}\n </span>\n {cell.unit && (\n <span className=\"mr-orig__vital-unit\">{cell.unit}</span>\n )}\n </div>\n )}\n {row.ekaId && (\n <button\n type=\"button\"\n className={`mr-orig__vital-expand-btn${expandedVital === row.key ? \" mr-orig__vital-expand-btn--open\" : \"\"}`}\n onClick={(e) => { e.stopPropagation(); toggleExpand(row.key); }}\n aria-label={expandedVital === row.key ? \"Collapse readings\" : \"Show latest readings\"}\n >\n <ChevronDown size={13} aria-hidden />\n </button>\n )}\n </div>\n {expandedVital === row.key && row.ekaId && (\n <VitalReadingsExpanded vitalName={row.name} ekaId={row.ekaId} />\n )}\n </div>\n );\n })}\n </div>\n\n {/* Footer */}\n <div className=\"mr-cc-table__footer\">\n <span\n className={`mr-sv__checkbox mr-cc-table__footer-check${srAllSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={srAllSelected}\n tabIndex={0}\n onClick={toggleSrAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleSrAll();\n }\n }}\n >\n {srAllSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <span className=\"mr-cc-table__footer-label\" onClick={toggleSrAll}>Select all</span>\n <span className=\"mr-cc-table__footer-count\">\n {srSelected.size} of {filteredRows.length} selected\n </span>\n <button\n ref={srCopyBtnRef}\n type=\"button\"\n className=\"mr-cc-table__copy-note-btn\"\n disabled={!srSomeSelected || !hasCopyToNote}\n onClick={handleSrCopyToNote}\n >\n Copy to note\n </button>\n </div>\n </div>\n ) : (\n <div className=\"mr-orig__smart-side mr-orig__smart-side--collapsed\">\n <Tooltip content=\"Show smart report\">\n <button\n type=\"button\"\n className=\"mr-sv__sidebar-collapse-btn mr-orig__smart-collapsed-btn\"\n aria-label=\"Expand smart report panel\"\n aria-expanded={false}\n onClick={() => setSmartPanelOpen(true)}\n >\n <span className=\"mr-orig__smart-collapsed-icon-wrap\">\n <SmartSparkles className=\"mr-orig__smart-collapsed-icon\" aria-hidden />\n </span>\n </button>\n </Tooltip>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction VitalReadingsExpanded({ vitalName, ekaId }: { vitalName: string; ekaId: string }) {\n const { data: trendData, status } = useParameterTrend(ekaId);\n\n const readings = useMemo(() => {\n const trend = trendData as ParameterTrendResponse | null;\n if (!trend?.vitals_info?.length) return [];\n return [...trend.vitals_info]\n .sort((a, b) => (b.date ?? 0) - (a.date ?? 0))\n .slice(0, 3)\n .map((info) => {\n const dr = (info.display_result ?? \"\").toLowerCase();\n const isOor = dr.includes(\"high\") || dr.includes(\"above\") || dr.includes(\"abnormal_high\") ||\n dr.includes(\"low\") || dr.includes(\"below\") || dr.includes(\"abnormal_low\");\n return {\n value: info.val != null ? String(info.val) : ((info as any).val_string ?? \"—\"),\n date: (info.display_time || \"\").replace(/['‘’]/g, \" \"),\n isOor,\n };\n });\n }, [trendData]);\n\n if (status === \"loading\") {\n return (\n <div className=\"mr-orig__vital-readings mr-orig__vital-readings--loading\">\n <LoaderCircle size={16} className=\"mr-sv__loading-spinner\" aria-hidden />\n </div>\n );\n }\n\n if (status === \"error\" || !readings.length) {\n return (\n <div className=\"mr-orig__vital-readings\">\n <Typography variant=\"muted\" className=\"mr-orig__vital-readings-empty\">\n No readings available\n </Typography>\n </div>\n );\n }\n\n return (\n <div className=\"mr-orig__vital-readings\">\n <div className=\"mr-orig__vital-readings-title\">\n LATEST READINGS FOR {vitalName.toUpperCase()}\n </div>\n <div className=\"mr-orig__vital-readings-grid\">\n {readings.map((r, i) => (\n <div key={i} className=\"mr-orig__vital-reading-item\">\n <span className={`mr-orig__vital-reading-value${r.isOor ? \" mr-orig__vital-reading-value--oor\" : \"\"}`}>{r.value}</span>\n <span className=\"mr-orig__vital-reading-date\">{r.date}</span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -137,19 +137,21 @@ function OriginalRecordPanel({
|
|
|
137
137
|
srAllSelected ? /* @__PURE__ */ new Set() : new Set(filteredRows.map((r) => r.key))
|
|
138
138
|
);
|
|
139
139
|
}, [srAllSelected, filteredRows]);
|
|
140
|
-
const handleSrCopyToNote = useCallback(() => {
|
|
140
|
+
const handleSrCopyToNote = useCallback(async () => {
|
|
141
141
|
const selectedRows = filteredRows.filter((r) => srSelected.has(r.key));
|
|
142
142
|
if (!selectedRows.length) return;
|
|
143
143
|
const text = buildVitalsText(selectedRows);
|
|
144
144
|
if (onCopyVitalsToNote) {
|
|
145
|
-
|
|
145
|
+
await onCopyVitalsToNote(text);
|
|
146
|
+
setSrSelected(/* @__PURE__ */ new Set());
|
|
146
147
|
} else if (onCopyToNote) {
|
|
147
148
|
const rect = srCopyBtnRef.current?.getBoundingClientRect();
|
|
148
|
-
|
|
149
|
+
const result = await onCopyToNote(
|
|
149
150
|
text,
|
|
150
151
|
rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : void 0,
|
|
151
152
|
toVitalNoteRows(selectedRows)
|
|
152
153
|
);
|
|
154
|
+
if (result !== false) setSrSelected(/* @__PURE__ */ new Set());
|
|
153
155
|
}
|
|
154
156
|
}, [filteredRows, srSelected, onCopyVitalsToNote, onCopyToNote]);
|
|
155
157
|
const htmlCopyBtnRef = useRef(null);
|
|
@@ -487,4 +489,4 @@ function VitalReadingsExpanded({ vitalName, ekaId }) {
|
|
|
487
489
|
export {
|
|
488
490
|
OriginalRecordPanel
|
|
489
491
|
};
|
|
490
|
-
//# sourceMappingURL=OriginalRecordPanel-
|
|
492
|
+
//# sourceMappingURL=OriginalRecordPanel-NGLSSJLE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/views/components/shared/OriginalRecordPanel.tsx"],"sourcesContent":["\"use client\";\n\nimport { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { ChevronLeft, ChevronRight, ChevronDown, ExternalLink, Check, File, LoaderCircle } from \"lucide-react\";\nimport { useStore } from \"zustand\";\nimport { useSdk } from \"../../../connection/useSdk\";\nimport { useRecordPreview } from \"../../../connection/useRecordPreview\";\nimport { useRecordPanelTable } from \"../../hooks/care-panel/useRecordPanelTable\";\nimport { useParameterTrend } from \"../../hooks/care-panel/useParameterTrend\";\nimport { epochToDisplay } from \"../../../helpers/formatters\";\nimport type { ParameterTrendResponse } from \"@eka-care/medical-records-ts-sdk\";\nimport { useSmartRecordsActions } from \"../../context/SmartRecordsActionsContext\";\nimport { IconButton, Typography, SearchInput, Tooltip } from \"widgets\";\nimport type { RecordItem } from \"../../../helpers\";\nimport type { PanelRow } from \"../../../helpers/vitalsPanel\";\nimport { toVitalNoteRows } from \"../../../helpers/vitalsPanel\";\nimport SmartSparkles from \"icons/SmartSparkles\";\n\nconst DocumentViewer = lazy(() =>\n import(\"../../RecordPreview/DocumentViewer\").then((m) => ({\n default: m.DocumentViewer,\n })),\n);\n\ninterface OriginalRecordPanelProps {\n recordId: string;\n caseId?: string;\n onBack: () => void;\n}\n\ntype SrTab = \"all\" | \"oor\" | \"none\";\n\nfunction buildVitalsText(rows: PanelRow[]): string {\n return rows\n .map((r) => {\n const cell = r.cells[0];\n const ref = cell?.refRange ? ` (Ref: ${cell.refRange})` : \"\";\n return `${r.name}: ${cell?.value ?? \"—\"} ${r.unit}${ref}`;\n })\n .join(\"\\n\");\n}\n\nexport function OriginalRecordPanel({\n recordId,\n caseId,\n onBack,\n}: OriginalRecordPanelProps) {\n const { store } = useSdk();\n const record = useStore(store, (s) => s.records.byId[recordId]);\n const recordsById = useStore(store, (s) => s.records.byId);\n const preview = useRecordPreview(recordId);\n const { replaceOriginal, onCopyToNote, onCopyVitalsToNote, hasCopyToNote, onToast } =\n useSmartRecordsActions();\n\n // Smart report vitals (only fetched when record.isSmart)\n const { status: vitalsStatus, table } = useRecordPanelTable(\n record?.isSmart ? recordId : null,\n );\n const [smartPanelOpen, setSmartPanelOpen] = useState(true);\n const [srSearch, setSrSearch] = useState(\"\");\n const [srTab, setSrTab] = useState<SrTab>(\"all\");\n const [expandedVital, setExpandedVital] = useState<string | null>(null);\n const toggleExpand = useCallback((key: string) => {\n setExpandedVital((prev) => (prev === key ? null : key));\n }, []);\n const [srSelected, setSrSelected] = useState<Set<string>>(new Set());\n const srCopyBtnRef = useRef<HTMLButtonElement>(null);\n\n // Dropdown state\n const [dropdownOpen, setDropdownOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!dropdownOpen) return;\n const handler = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setDropdownOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [dropdownOpen]);\n\n const caseRecords = useMemo<RecordItem[]>(() => {\n if (!caseId) return [];\n return Object.values(recordsById)\n .filter(\n (r): r is RecordItem =>\n r != null &&\n (caseId === \"__ungrouped__\" ? r.cases.length === 0 : r.cases.includes(caseId)),\n )\n .sort((a, b) => b.createdAtEpoch - a.createdAtEpoch);\n }, [recordsById, caseId]);\n\n const currentIndex = caseRecords.findIndex((r) => r.id === recordId);\n const total = caseRecords.length;\n const isUngrouped = caseId === \"__ungrouped__\";\n\n const goTo = useCallback(\n (r: RecordItem) => {\n setDropdownOpen(false);\n replaceOriginal(r.id, caseId);\n },\n [replaceOriginal, caseId],\n );\n\n const goPrev = useCallback(() => {\n if (currentIndex > 0) goTo(caseRecords[currentIndex - 1]);\n }, [currentIndex, caseRecords, goTo]);\n\n const goNext = useCallback(() => {\n if (currentIndex < total - 1) goTo(caseRecords[currentIndex + 1]);\n }, [currentIndex, total, caseRecords, goTo]);\n\n const showNavPicker = caseId && total > 0;\n\n // Smart report vitals filtering\n const allRows = table.rows;\n const oorRows = useMemo(\n () => allRows.filter((r) => r.latestStatus === \"high\" || r.latestStatus === \"low\"),\n [allRows],\n );\n const noInterpRows = useMemo(\n () => allRows.filter((r) => r.latestStatus === \"unknown\"),\n [allRows],\n );\n\n const baseRows = srTab === \"oor\" ? oorRows : srTab === \"none\" ? noInterpRows : allRows;\n\n const filteredRows = useMemo(() => {\n if (!srSearch) return baseRows;\n const q = srSearch.toLowerCase();\n return baseRows.filter((r) => r.name.toLowerCase().includes(q));\n }, [baseRows, srSearch]);\n\n const tabCounts = useMemo(() => {\n if (!srSearch) return { all: allRows.length, oor: oorRows.length, none: noInterpRows.length };\n const q = srSearch.toLowerCase();\n return {\n all: allRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n oor: oorRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n none: noInterpRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n };\n }, [srSearch, allRows, oorRows, noInterpRows]);\n\n useEffect(() => {\n setSrSelected(new Set());\n }, [srTab, srSearch]);\n\n useEffect(() => {\n if (srTab === \"oor\" && oorRows.length === 0) setSrTab(\"all\");\n if (srTab === \"none\" && noInterpRows.length === 0) setSrTab(\"all\");\n }, [srTab, oorRows.length, noInterpRows.length]);\n\n const srAllSelected =\n filteredRows.length > 0 && filteredRows.every((r) => srSelected.has(r.key));\n const srSomeSelected = srSelected.size > 0;\n\n const toggleSrRow = useCallback((key: string) => {\n setSrSelected((prev) => {\n const next = new Set(prev);\n next.has(key) ? next.delete(key) : next.add(key);\n return next;\n });\n }, []);\n\n const toggleSrAll = useCallback(() => {\n setSrSelected(\n srAllSelected ? new Set() : new Set(filteredRows.map((r) => r.key)),\n );\n }, [srAllSelected, filteredRows]);\n\n const handleSrCopyToNote = useCallback(async () => {\n const selectedRows = filteredRows.filter((r) => srSelected.has(r.key));\n if (!selectedRows.length) return;\n const text = buildVitalsText(selectedRows);\n if (onCopyVitalsToNote) {\n await onCopyVitalsToNote(text);\n setSrSelected(new Set());\n } else if (onCopyToNote) {\n const rect = srCopyBtnRef.current?.getBoundingClientRect();\n const result = await onCopyToNote(\n text,\n rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : undefined,\n toVitalNoteRows(selectedRows),\n );\n if (result !== false) setSrSelected(new Set());\n }\n }, [filteredRows, srSelected, onCopyVitalsToNote, onCopyToNote]);\n\n const htmlCopyBtnRef = useRef<HTMLButtonElement>(null);\n const [isHtmlCopying, setIsHtmlCopying] = useState(false);\n\n const handleHtmlCopyToNote = useCallback(async () => {\n const url = preview.files[0]?.url;\n if (!url) return;\n setIsHtmlCopying(true);\n try {\n const res = await fetch(url);\n const html = await res.text();\n const doc = new DOMParser().parseFromString(html, \"text/html\");\n const text = doc.body.textContent?.trim() ?? \"\";\n if (!text) return;\n if (onCopyVitalsToNote) {\n void onCopyVitalsToNote(text);\n } else if (onCopyToNote) {\n const rect = htmlCopyBtnRef.current?.getBoundingClientRect();\n void onCopyToNote(\n text,\n rect ? { x: rect.left, y: rect.bottom } : undefined,\n );\n }\n } catch {\n onToast?.(\"Failed to copy document text\", \"error\");\n } finally {\n setIsHtmlCopying(false);\n }\n }, [preview.files, onCopyVitalsToNote, onCopyToNote, onToast]);\n\n const isSmart = record?.isSmart ?? false;\n const hasPreview = preview.status === \"loaded\" && preview.files.length > 0;\n\n return (\n <div className=\"mr-sv__panel\">\n <div className=\"mr-sv__panel-header\">\n <button type=\"button\" className=\"mr-sv__back-btn\" onClick={onBack}>\n <ChevronLeft size={16} aria-hidden />\n Back\n </button>\n\n {/* Prev/next record carousel + dropdown — temporarily disabled, will re-enable later.\n {showNavPicker ? (\n <div className=\"mr-orig__nav-wrap\" ref={dropdownRef}>\n <div\n className={`mr-orig__nav-pill${dropdownOpen ? \" mr-orig__nav-pill--open\" : \"\"}`}\n role=\"button\"\n tabIndex={0}\n onClick={() => setDropdownOpen((v) => !v)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setDropdownOpen((v) => !v);\n }\n }}\n >\n <button\n type=\"button\"\n className=\"mr-orig__nav-chevron\"\n onClick={(e) => { e.stopPropagation(); goPrev(); }}\n aria-label=\"Previous record\"\n disabled={currentIndex <= 0}\n >\n <ChevronLeft size={14} aria-hidden />\n </button>\n <div className=\"mr-orig__nav-text\">\n <span className=\"mr-orig__nav-title\">{record?.title ?? \"Record\"}</span>\n <span className=\"mr-orig__nav-counter\">\n {currentIndex + 1} of {total}\n </span>\n </div>\n <button\n type=\"button\"\n className=\"mr-orig__nav-chevron\"\n onClick={(e) => { e.stopPropagation(); goNext(); }}\n aria-label=\"Next record\"\n disabled={currentIndex >= total - 1}\n >\n <ChevronRight size={14} aria-hidden />\n </button>\n </div>\n\n {dropdownOpen && (\n <div className=\"mr-orig__dropdown\">\n <div className=\"mr-orig__dropdown-eyebrow\">\n {total} RECORD{total !== 1 ? \"S\" : \"\"}{\" \"}\n {isUngrouped ? \"WITH NO CARE CONTEXT\" : \"FOUND IN THIS ENCOUNTER\"}\n </div>\n <div className=\"mr-orig__dropdown-list\">\n {caseRecords.map((r) => {\n const isActive = r.id === recordId;\n return (\n <button\n key={r.id}\n type=\"button\"\n className={`mr-orig__dropdown-item${isActive ? \" mr-orig__dropdown-item--active\" : \"\"}`}\n onClick={() => goTo(r)}\n >\n <div className=\"mr-orig__dropdown-icon\">\n <File size={16} aria-hidden />\n {r.isSmart && (\n <SmartSparkles\n className=\"mr-orig__dropdown-smart-dot\"\n aria-label=\"Smart report\"\n />\n )}\n </div>\n <div className=\"mr-orig__dropdown-info\">\n <div className=\"mr-orig__dropdown-title-row\">\n <span className=\"mr-orig__dropdown-title\">{r.title}</span>\n {r.isSmart && (\n <span className=\"mr-orig__dropdown-smart-badge\">\n <SmartSparkles aria-hidden />\n Smart Report\n </span>\n )}\n {r.fileType?.toUpperCase() === \"HTML\" && (\n <span className=\"mr-tag-chip mr-tag-chip--html\">\n <span className=\"mr-tag-chip__label\">HTML</span>\n </span>\n )}\n </div>\n <div className=\"mr-orig__dropdown-meta\">\n <span>{epochToDisplay(r.createdAtEpoch)}</span>\n {r.isSmart && r.totalVitals > 0 && (\n <>\n <span className=\"mr-orig__dropdown-dot\">·</span>\n <span>{r.totalVitals} vitals</span>\n </>\n )}\n </div>\n </div>\n {isActive && (\n <Check\n size={14}\n className=\"mr-orig__dropdown-check\"\n aria-hidden\n />\n )}\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n ) : record ? (\n */}\n {record ? (\n <div className=\"mr-sv__panel-info\">\n <Typography variant=\"label\" as=\"span\" className=\"mr-sv__panel-name\">\n {record.title}\n </Typography>\n <Typography variant=\"hint\" as=\"span\" className=\"mr-sv__panel-meta-text\">\n {epochToDisplay(record.createdAtEpoch)}\n </Typography>\n </div>\n ) : null}\n {/* } */}\n\n <div className=\"mr-orig__header-actions\">\n {preview.isHtml && hasCopyToNote && (\n <button\n ref={htmlCopyBtnRef}\n type=\"button\"\n className=\"mr-orig__html-copy-btn\"\n onClick={handleHtmlCopyToNote}\n disabled={isHtmlCopying}\n >\n {isHtmlCopying && <LoaderCircle size={12} className=\"mr-sv__loading-spinner\" aria-hidden />}\n Copy to note\n </button>\n )}\n {hasPreview && (\n <IconButton\n icon={<ExternalLink size={16} aria-hidden />}\n label=\"Open in new tab\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() =>\n window.open(preview.files[0].url, \"_blank\", \"noopener,noreferrer\")\n }\n />\n )}\n </div>\n </div>\n\n <div\n className=\"mr-sv__panel-body\"\n style={{ flex: 1, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}\n >\n {preview.status === \"loading\" && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n }}\n >\n <LoaderCircle size={44} className=\"mr-sv__loading-spinner\" aria-hidden />\n </div>\n )}\n {preview.status === \"error\" && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n Failed to load document preview.\n </Typography>\n )}\n {preview.status === \"loaded\" && preview.files.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No preview available for this record.\n </Typography>\n )}\n\n {/* Non-smart: full-width PDF */}\n {hasPreview && !isSmart && (\n <div\n className=\"mr-record-preview__body\"\n style={{ flex: 1, display: \"flex\", overflow: \"hidden\" }}\n >\n <Suspense fallback={null}>\n <DocumentViewer\n files={preview.files}\n title={record?.title ?? \"\"}\n isHtml={preview.isHtml}\n />\n </Suspense>\n </div>\n )}\n\n {/* Smart: split view — PDF left, smart report panel right */}\n {hasPreview && isSmart && (\n <div className=\"mr-orig__split\">\n <div className=\"mr-orig__pdf-side\">\n <Suspense fallback={null}>\n <DocumentViewer\n files={preview.files}\n title={record?.title ?? \"\"}\n isHtml={preview.isHtml}\n />\n </Suspense>\n </div>\n\n {smartPanelOpen ? (\n <div className=\"mr-orig__smart-side\">\n {/* Header */}\n <div className=\"mr-orig__smart-hdr\">\n <span className=\"mr-orig__smart-title-row\">\n <span className=\"mr-orig__smart-title\">Smart Report</span>\n <SmartSparkles className=\"mr-orig__smart-title-icon\" aria-hidden />\n </span>\n <button\n type=\"button\"\n className=\"mr-sv__sidebar-collapse-btn mr-orig__smart-expanded-btn\"\n aria-label=\"Collapse smart report panel\"\n aria-expanded={true}\n onClick={() => setSmartPanelOpen(false)}\n >\n <ChevronRight size={14} aria-hidden />\n </button>\n </div>\n\n {/* Search */}\n <SearchInput\n className=\"mr-orig__smart-search\"\n iconSize={16}\n placeholder=\"Search vitals\"\n value={srSearch}\n onChange={setSrSearch}\n />\n\n {/* Filter tabs — only when at least one sub-category has data */}\n {(oorRows.length > 0 || noInterpRows.length > 0) && (\n <div className=\"mr-orig__smart-tabs-wrap\">\n <div className=\"mr-orig__smart-tabs\">\n {([\"all\", \"oor\", \"none\"] as SrTab[]).map((tab) => {\n if (tab === \"oor\" && oorRows.length === 0) return null;\n if (tab === \"none\" && noInterpRows.length === 0) return null;\n const count =\n tab === \"all\"\n ? tabCounts.all\n : tab === \"oor\"\n ? tabCounts.oor\n : tabCounts.none;\n const label =\n tab === \"all\"\n ? \"All\"\n : tab === \"oor\"\n ? \"Out of range\"\n : \"No interpretation\";\n return (\n <button\n key={tab}\n type=\"button\"\n className={`mr-orig__smart-tab${srTab === tab ? \" mr-orig__smart-tab--active\" : \"\"}`}\n onClick={() => setSrTab(tab)}\n >\n {label} ({count})\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Vital list */}\n <div className=\"mr-orig__smart-list\">\n {vitalsStatus === \"loading\" && (\n <div className=\"mr-orig__smart-loading\">\n <LoaderCircle\n size={20}\n className=\"mr-sv__loading-spinner\"\n aria-hidden\n />\n </div>\n )}\n {vitalsStatus === \"loaded\" && filteredRows.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-orig__smart-empty\">\n No vitals match.\n </Typography>\n )}\n {vitalsStatus === \"loaded\" &&\n filteredRows.map((row, idx) => {\n const cell = row.cells[0];\n const isOor =\n row.latestStatus === \"high\" || row.latestStatus === \"low\";\n const isSelected = srSelected.has(row.key);\n const isLast = idx === filteredRows.length - 1;\n return (\n <div\n key={row.key}\n className={`mr-orig__vital-item${isLast ? \" mr-orig__vital-item--last\" : \"\"}`}\n >\n <div\n className={`mr-orig__vital-row mr-orig__vital-row--selectable${isSelected ? \" mr-orig__vital-row--selected\" : \"\"}`}\n onClick={() => toggleSrRow(row.key)}\n >\n <span\n className={`mr-sv__checkbox mr-cc-table__row-check${isSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n toggleSrRow(row.key);\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n toggleSrRow(row.key);\n }\n }}\n >\n {isSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <div className=\"mr-orig__vital-info\">\n <span className=\"mr-orig__vital-name\">{row.name}</span>\n {row.refRange && (\n <span className=\"mr-orig__vital-ref\">\n Ref {row.refRange}\n </span>\n )}\n </div>\n {cell && (\n <div className=\"mr-orig__vital-value\">\n <span\n className={`mr-orig__vital-val${isOor ? \" mr-orig__vital-val--oor\" : \"\"}`}\n >\n {cell.value}\n </span>\n {cell.unit && (\n <span className=\"mr-orig__vital-unit\">{cell.unit}</span>\n )}\n </div>\n )}\n {row.ekaId && (\n <button\n type=\"button\"\n className={`mr-orig__vital-expand-btn${expandedVital === row.key ? \" mr-orig__vital-expand-btn--open\" : \"\"}`}\n onClick={(e) => { e.stopPropagation(); toggleExpand(row.key); }}\n aria-label={expandedVital === row.key ? \"Collapse readings\" : \"Show latest readings\"}\n >\n <ChevronDown size={13} aria-hidden />\n </button>\n )}\n </div>\n {expandedVital === row.key && row.ekaId && (\n <VitalReadingsExpanded vitalName={row.name} ekaId={row.ekaId} />\n )}\n </div>\n );\n })}\n </div>\n\n {/* Footer */}\n <div className=\"mr-cc-table__footer\">\n <span\n className={`mr-sv__checkbox mr-cc-table__footer-check${srAllSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={srAllSelected}\n tabIndex={0}\n onClick={toggleSrAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleSrAll();\n }\n }}\n >\n {srAllSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <span className=\"mr-cc-table__footer-label\" onClick={toggleSrAll}>Select all</span>\n <span className=\"mr-cc-table__footer-count\">\n {srSelected.size} of {filteredRows.length} selected\n </span>\n <button\n ref={srCopyBtnRef}\n type=\"button\"\n className=\"mr-cc-table__copy-note-btn\"\n disabled={!srSomeSelected || !hasCopyToNote}\n onClick={handleSrCopyToNote}\n >\n Copy to note\n </button>\n </div>\n </div>\n ) : (\n <div className=\"mr-orig__smart-side mr-orig__smart-side--collapsed\">\n <Tooltip content=\"Show smart report\">\n <button\n type=\"button\"\n className=\"mr-sv__sidebar-collapse-btn mr-orig__smart-collapsed-btn\"\n aria-label=\"Expand smart report panel\"\n aria-expanded={false}\n onClick={() => setSmartPanelOpen(true)}\n >\n <span className=\"mr-orig__smart-collapsed-icon-wrap\">\n <SmartSparkles className=\"mr-orig__smart-collapsed-icon\" aria-hidden />\n </span>\n </button>\n </Tooltip>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction VitalReadingsExpanded({ vitalName, ekaId }: { vitalName: string; ekaId: string }) {\n const { data: trendData, status } = useParameterTrend(ekaId);\n\n const readings = useMemo(() => {\n const trend = trendData as ParameterTrendResponse | null;\n if (!trend?.vitals_info?.length) return [];\n return [...trend.vitals_info]\n .sort((a, b) => (b.date ?? 0) - (a.date ?? 0))\n .slice(0, 3)\n .map((info) => {\n const dr = (info.display_result ?? \"\").toLowerCase();\n const isOor = dr.includes(\"high\") || dr.includes(\"above\") || dr.includes(\"abnormal_high\") ||\n dr.includes(\"low\") || dr.includes(\"below\") || dr.includes(\"abnormal_low\");\n return {\n value: info.val != null ? String(info.val) : ((info as any).val_string ?? \"—\"),\n date: (info.display_time || \"\").replace(/['‘’]/g, \" \"),\n isOor,\n };\n });\n }, [trendData]);\n\n if (status === \"loading\") {\n return (\n <div className=\"mr-orig__vital-readings mr-orig__vital-readings--loading\">\n <LoaderCircle size={16} className=\"mr-sv__loading-spinner\" aria-hidden />\n </div>\n );\n }\n\n if (status === \"error\" || !readings.length) {\n return (\n <div className=\"mr-orig__vital-readings\">\n <Typography variant=\"muted\" className=\"mr-orig__vital-readings-empty\">\n No readings available\n </Typography>\n </div>\n );\n }\n\n return (\n <div className=\"mr-orig__vital-readings\">\n <div className=\"mr-orig__vital-readings-title\">\n LATEST READINGS FOR {vitalName.toUpperCase()}\n </div>\n <div className=\"mr-orig__vital-readings-grid\">\n {readings.map((r, i) => (\n <div key={i} className=\"mr-orig__vital-reading-item\">\n <span className={`mr-orig__vital-reading-value${r.isOor ? \" mr-orig__vital-reading-value--oor\" : \"\"}`}>{r.value}</span>\n <span className=\"mr-orig__vital-reading-date\">{r.date}</span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
VitalHistoryPanel
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5TPILQYM.mjs";
|
|
5
5
|
import "./chunk-7AO6M347.mjs";
|
|
6
6
|
import "./chunk-NZNI6YJ5.mjs";
|
|
7
7
|
export {
|
|
8
8
|
VitalHistoryPanel
|
|
9
9
|
};
|
|
10
|
-
//# sourceMappingURL=VitalHistoryPanel-
|
|
10
|
+
//# sourceMappingURL=VitalHistoryPanel-FT5VMJ37.mjs.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkKTHLLAAGjs = require('./chunk-KTHLLAAG.js');
|
|
5
|
+
require('./chunk-STQYPHI3.js');
|
|
6
|
+
require('./chunk-QGGLSO4W.js');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports.VitalHistoryPanel = _chunkKTHLLAAGjs.VitalHistoryPanel;
|
|
10
|
+
//# sourceMappingURL=VitalHistoryPanel-VQQ27P6Q.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/medical-records-ui/medical-records-ui/dist/VitalHistoryPanel-
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/medical-records-ui/medical-records-ui/dist/VitalHistoryPanel-VQQ27P6Q.js"],"names":[],"mappings":"AAAA,qFAAY;AACZ;AACE;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACF,+DAAC","file":"/home/runner/work/medical-records-ui/medical-records-ui/dist/VitalHistoryPanel-VQQ27P6Q.js"}
|
|
@@ -235,6 +235,7 @@ function VitalHistoryPanel({
|
|
|
235
235
|
someSelected,
|
|
236
236
|
togglePoint,
|
|
237
237
|
toggleAll,
|
|
238
|
+
clearSelection,
|
|
238
239
|
buildHistoryText
|
|
239
240
|
} = useVitalHistoryPanel(
|
|
240
241
|
vital ?? {
|
|
@@ -248,21 +249,23 @@ function VitalHistoryPanel({
|
|
|
248
249
|
},
|
|
249
250
|
filteredPoints
|
|
250
251
|
);
|
|
251
|
-
const handleCopyToNote = useCallback2(() => {
|
|
252
|
+
const handleCopyToNote = useCallback2(async () => {
|
|
252
253
|
const chosen = points.filter((_, i) => selected.has(i));
|
|
253
254
|
if (!chosen.length) return;
|
|
254
255
|
const text = buildHistoryText(chosen);
|
|
255
256
|
if (onCopyVitalsToNote) {
|
|
256
|
-
|
|
257
|
+
await onCopyVitalsToNote(text);
|
|
258
|
+
clearSelection();
|
|
257
259
|
} else if (onCopyToNote) {
|
|
258
260
|
const rect = copyBtnRef.current?.getBoundingClientRect();
|
|
259
|
-
|
|
261
|
+
const result = await onCopyToNote(
|
|
260
262
|
text,
|
|
261
263
|
rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : void 0,
|
|
262
264
|
vital ? toHistoryNoteRows(vital, chosen) : void 0
|
|
263
265
|
);
|
|
266
|
+
if (result !== false) clearSelection();
|
|
264
267
|
}
|
|
265
|
-
}, [points, selected, buildHistoryText, onCopyVitalsToNote, onCopyToNote, vital]);
|
|
268
|
+
}, [points, selected, buildHistoryText, onCopyVitalsToNote, onCopyToNote, vital, clearSelection]);
|
|
266
269
|
const hasCopyToNote = !!(onCopyToNote || onCopyVitalsToNote);
|
|
267
270
|
if (preview.status === "loading") {
|
|
268
271
|
return /* @__PURE__ */ jsx(
|
|
@@ -440,4 +443,4 @@ function VitalHistoryPanel({
|
|
|
440
443
|
export {
|
|
441
444
|
VitalHistoryPanel
|
|
442
445
|
};
|
|
443
|
-
//# sourceMappingURL=chunk-
|
|
446
|
+
//# sourceMappingURL=chunk-5TPILQYM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/views/containers/care-panel/VitalHistoryPanel.tsx","../src/views/hooks/care-panel/useVitalHistoryPanel.ts"],"sourcesContent":["\"use client\";\n\nimport { ChevronLeft, Check, LoaderCircle } from \"lucide-react\";\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { isOutOfRange } from \"../../../helpers/smartReport\";\nimport { useSmartRecordsActions } from \"../../context/SmartRecordsActionsContext\";\nimport { useVitalHistoryPanel } from \"../../hooks/care-panel/useVitalHistoryPanel\";\nimport { useParameterTrend } from \"../../hooks/care-panel/useParameterTrend\";\nimport { invalidateRecordPanelTable } from \"../../hooks/care-panel/useRecordPanelTable\";\nimport { useRecordPreview } from \"../../../connection/useRecordPreview\";\nimport type { HistoryPoint } from \"../../types\";\nimport type {\n VitalStatus,\n Vital,\n VitalHistoryPoint,\n} from \"../../../helpers/smartReport\";\nimport type { VitalNoteRow } from \"../../../helpers/vitalsPanel\";\nimport type { ParameterTrendResponse } from \"@eka-care/medical-records-ts-sdk\";\nimport { Typography } from \"widgets\";\n\nconst HISTORY_COLS = \"2fr 2fr 88px\";\n\n// One row per reading — date is folded into `value` since the shared note\n// table has no dedicated date column (each reading needs to stay distinguishable).\nfunction toHistoryNoteRows(vital: Vital, pts: HistoryPoint[]): VitalNoteRow[] {\n return pts.map((p) => {\n const dateSuffix = p.date ? ` (${p.date}${p.caseLabel ? ` · ${p.caseLabel}` : \"\"})` : \"\";\n return {\n name: vital.name,\n value: `${p.value}${p.unit ? ` ${p.unit}` : \"\"}${dateSuffix}`,\n unit: \"\",\n refRange: vital.refRange,\n };\n });\n}\n\nfunction normalizeStatus(displayResult: string): VitalStatus {\n const s = displayResult.toLowerCase();\n if (s.includes(\"high\") || s.includes(\"above\") || s === \"abnormal_high\")\n return \"high\";\n if (s.includes(\"low\") || s.includes(\"below\") || s === \"abnormal_low\")\n return \"low\";\n if (s.includes(\"normal\") || s.includes(\"in range\") || s === \"ok\")\n return \"normal\";\n return \"unknown\";\n}\n\ninterface VitalHistoryPanelProps {\n recordId: string;\n vitalId: string;\n caseId?: string;\n returnTo?: \"smart\" | \"careContext\";\n}\n\ninterface HistoryRowProps {\n index: number;\n point: HistoryPoint;\n vital: Vital;\n isSelected: boolean;\n isLast: boolean;\n onToggle: (i: number) => void;\n onViewRecord: (\n recordId: string,\n returnTo: \"smart\" | \"history\",\n returnVitalId?: string,\n ) => void;\n}\n\nconst HistoryRow = memo(function HistoryRow({\n index,\n point,\n vital,\n isSelected,\n isLast,\n onToggle,\n onViewRecord,\n}: HistoryRowProps) {\n const oor = isOutOfRange({ ...vital, status: point.status });\n const handleToggle = useCallback(() => onToggle(index), [onToggle, index]);\n const handleViewRecord = useCallback(\n () => onViewRecord(point.recordId, \"history\", vital.id),\n [onViewRecord, point.recordId, vital.id],\n );\n\n return (\n <div className={`mr-cc-table__row-wrap${isLast ? \" mr-cc-table__row-wrap--last\" : \"\"}`}>\n <div\n className={`mr-cc-table__row${isSelected ? \" mr-cc-table__row--selected\" : \"\"}`}\n role=\"row\"\n style={{ gridTemplateColumns: HISTORY_COLS, cursor: \"pointer\" }}\n onClick={handleToggle}\n >\n <div\n className=\"mr-cc-table__reading-cell\"\n role=\"cell\"\n style={{ flexDirection: \"row\", alignItems: \"center\", gap: \"8px\" }}\n >\n <span\n className={`mr-sv__checkbox mr-cc-table__row-check${isSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n handleToggle();\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n handleToggle();\n }\n }}\n >\n {isSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <div className=\"mr-cc-table__reading-value-row\">\n {point.value ? (\n <>\n <span\n className={`mr-cc-table__rvalue${oor ? \" mr-cc-table__rvalue--oor\" : \"\"}`}\n >\n {point.value}\n </span>\n {point.unit && (\n <span className=\"mr-cc-table__runit\">{point.unit}</span>\n )}\n </>\n ) : (\n <span className=\"mr-cc-table__empty-dash\">—</span>\n )}\n </div>\n </div>\n\n <div className=\"mr-cc-table__reading-cell\" role=\"cell\">\n {point.date ? (\n <span className=\"mr-cc-table__rvalue\">{point.date}</span>\n ) : (\n <span className=\"mr-cc-table__empty-dash\">—</span>\n )}\n </div>\n\n <div\n className=\"mr-cc-table__actions\"\n role=\"cell\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n className=\"mr-sv__view-record-btn\"\n onClick={handleViewRecord}\n >\n View record\n </button>\n </div>\n </div>\n </div>\n );\n});\n\nexport function VitalHistoryPanel({\n recordId,\n vitalId,\n caseId,\n}: VitalHistoryPanelProps) {\n const { back, openOriginal: _openOriginal, onCopyToNote, onCopyVitalsToNote, onToast } =\n useSmartRecordsActions();\n\n const openOriginal = useCallback(\n (recordId: string, returnTo: \"smart\" | \"history\" | \"careContext\", returnVitalId?: string) => {\n invalidateRecordPanelTable(recordId);\n _openOriginal(recordId, caseId ? \"careContext\" : returnTo, returnVitalId, caseId);\n },\n [_openOriginal, caseId],\n );\n const preview = useRecordPreview(recordId);\n const vital = preview.vitals.find((v) => v.id === vitalId);\n const copyBtnRef = useRef<HTMLButtonElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n const { data: trendData, status: trendStatus } = useParameterTrend(\n vital?.ekaId,\n );\n\n const points = useMemo((): HistoryPoint[] => {\n const trend = trendData as ParameterTrendResponse | null;\n if (!trend?.vitals_info?.length) return [];\n return trend.vitals_info\n .sort((a, b) => (b.date ?? 0) - (a.date ?? 0))\n .map((info) => ({\n date: (info.display_time || \"\").replace(/['‘’]/g, \" \"),\n caseLabel: \"\",\n value:\n info.val !== undefined\n ? String(info.val)\n : ((info as any).val_string ?? \"\"),\n unit: trend.unit,\n status: normalizeStatus(info.display_result ?? \"\"),\n recordId: info.document_id,\n recordName: trend.name,\n }));\n }, [trendData]);\n\n type VhpTab = \"all\" | \"oor\" | \"none\";\n const [activeTab, setActiveTab] = useState<VhpTab>(\"all\");\n\n const oorCount = useMemo(\n () => points.filter((p) => p.status === \"high\" || p.status === \"low\").length,\n [points],\n );\n const noneCount = useMemo(\n () => points.filter((p) => p.status === \"unknown\").length,\n [points],\n );\n\n useEffect(() => {\n if (activeTab === \"oor\" && oorCount === 0) setActiveTab(\"all\");\n if (activeTab === \"none\" && noneCount === 0) setActiveTab(\"all\");\n }, [activeTab, oorCount, noneCount]);\n\n useEffect(() => {\n if (trendStatus === \"error\") {\n back();\n onToast?.(\"Failed to load vital history\", \"error\");\n }\n }, [trendStatus, back, onToast]);\n\n const filteredPoints = useMemo(() => {\n if (activeTab === \"oor\") return points.filter((p) => p.status === \"high\" || p.status === \"low\");\n if (activeTab === \"none\") return points.filter((p) => p.status === \"unknown\");\n return points;\n }, [points, activeTab]);\n\n const rowVirtualizer = useVirtualizer({\n count: filteredPoints.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => 50,\n overscan: 5,\n });\n\n const {\n selected,\n allSelected,\n someSelected,\n togglePoint,\n toggleAll,\n clearSelection,\n buildHistoryText,\n } = useVitalHistoryPanel(\n vital ?? {\n id: vitalId,\n name: \"\",\n value: \"\",\n unit: \"\",\n refRange: \"\",\n status: \"normal\" as VitalStatus,\n history: [] as VitalHistoryPoint[],\n },\n filteredPoints,\n );\n\n const handleCopyToNote = useCallback(async () => {\n const chosen = points.filter((_, i) => selected.has(i));\n if (!chosen.length) return;\n const text = buildHistoryText(chosen);\n if (onCopyVitalsToNote) {\n await onCopyVitalsToNote(text);\n clearSelection();\n } else if (onCopyToNote) {\n const rect = copyBtnRef.current?.getBoundingClientRect();\n const result = await onCopyToNote(\n text,\n rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : undefined,\n vital ? toHistoryNoteRows(vital, chosen) : undefined,\n );\n if (result !== false) clearSelection();\n }\n }, [points, selected, buildHistoryText, onCopyVitalsToNote, onCopyToNote, vital, clearSelection]);\n\n const hasCopyToNote = !!(onCopyToNote || onCopyVitalsToNote);\n\n if (preview.status === \"loading\") {\n return (\n <div\n className=\"mr-sv__panel\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <LoaderCircle\n size={32}\n className=\"mr-sv__loading-spinner\"\n aria-hidden\n />\n </div>\n );\n }\n\n if (!vital) {\n return (\n <div className=\"mr-sv__panel\">\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n Vital not found.\n </Typography>\n </div>\n );\n }\n\n return (\n <div className=\"mr-sv__panel\">\n <div className=\"mr-sv__back-row\">\n <button type=\"button\" className=\"mr-sv__back-btn\" onClick={back}>\n <ChevronLeft size={16} aria-hidden />\n Back\n </button>\n </div>\n {/* Header */}\n <div className=\"mr-sv__panel-header\">\n <div className=\"mr-sv__panel-left\">\n <div className=\"mr-sv__panel-info\">\n <div className=\"mr-sv__panel-name-row\">\n <Typography\n variant=\"label\"\n as=\"span\"\n className=\"mr-sv__panel-name\"\n >\n {vital.name}\n </Typography>\n {vital.refRange && (\n <span className=\"mr-sv__panel-ref-badge\">\n Ref: {vital.refRange}\n </span>\n )}\n </div>\n <div className=\"mr-sv__panel-meta\">\n {trendStatus === \"loaded\" && (\n <span>\n {points.length} reading{points.length !== 1 ? \"s\" : \"\"}\n {oorCount > 0 && (\n <>\n {\" \"}\n ·{\" \"}\n <span className=\"mr-sv__oor\">\n {oorCount} out of range\n </span>\n </>\n )}\n </span>\n )}\n </div>\n </div>\n </div>\n <span className=\"mr-cc-panel__viewing-label\">Viewing vital history</span>\n </div>\n\n {/* Filter tabs — only shown when at least one sub-category has data */}\n {trendStatus === \"loaded\" && points.length > 0 && (oorCount > 0 || noneCount > 0) && (\n <div className=\"mr-orig__smart-tabs-wrap\" style={{ padding: \"8px 16px 0\" }}>\n <div className=\"mr-orig__smart-tabs\">\n {([\"all\", \"oor\", \"none\"] as VhpTab[]).map((tab) => {\n if (tab === \"oor\" && oorCount === 0) return null;\n if (tab === \"none\" && noneCount === 0) return null;\n const count = tab === \"all\" ? points.length : tab === \"oor\" ? oorCount : noneCount;\n const label = tab === \"all\" ? \"All\" : tab === \"oor\" ? \"Out of range\" : \"No interpretation\";\n return (\n <button\n key={tab}\n type=\"button\"\n className={`mr-orig__smart-tab${activeTab === tab ? \" mr-orig__smart-tab--active\" : \"\"}`}\n onClick={() => setActiveTab(tab)}\n >\n {label} ({count})\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Body */}\n <div className=\"mr-sv__panel-body\" ref={scrollRef} style={{ overflowY: \"auto\" }}>\n {trendStatus === \"loading\" && (\n <div className=\"mr-cc-table mr-cc-table--state\">\n <LoaderCircle size={20} className=\"mr-sv__loading-spinner\" aria-hidden />\n <Typography variant=\"muted\">Loading vital history…</Typography>\n </div>\n )}\n {trendStatus === \"loaded\" && points.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No historical data available for this vital.\n </Typography>\n )}\n {points.length > 0 && (\n <div className=\"mr-vhp-table\" role=\"table\">\n <div\n className=\"mr-cc-table__row mr-cc-table__row--head\"\n role=\"row\"\n style={{ gridTemplateColumns: HISTORY_COLS, margin: 0 }}\n >\n <span className=\"mr-cc-table__head-cell\" role=\"columnheader\">READING</span>\n <span className=\"mr-cc-table__head-cell\" role=\"columnheader\">DATE</span>\n <span className=\"mr-cc-table__head-cell\" aria-hidden />\n </div>\n {filteredPoints.length === 0 ? (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No readings match this filter.\n </Typography>\n ) : (\n <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: \"relative\" }}>\n {rowVirtualizer.getVirtualItems().map((virtualRow) => (\n <div\n key={virtualRow.key}\n data-index={virtualRow.index}\n ref={rowVirtualizer.measureElement}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <HistoryRow\n index={virtualRow.index}\n point={filteredPoints[virtualRow.index]}\n vital={vital}\n isSelected={selected.has(virtualRow.index)}\n isLast={virtualRow.index === filteredPoints.length - 1}\n onToggle={togglePoint}\n onViewRecord={openOriginal}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"mr-cc-table__footer\">\n <span\n className={`mr-sv__checkbox mr-cc-table__footer-check${allSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={allSelected}\n tabIndex={0}\n onClick={toggleAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleAll();\n }\n }}\n >\n {allSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <span className=\"mr-cc-table__footer-label\" onClick={toggleAll}>Select all</span>\n <span className=\"mr-cc-table__footer-count\">{selected.size} of {points.length} selected</span>\n <button\n ref={copyBtnRef}\n type=\"button\"\n className=\"mr-cc-table__copy-note-btn\"\n disabled={!someSelected || !hasCopyToNote}\n onClick={handleCopyToNote}\n >\n Copy to note\n </button>\n </div>\n </div>\n );\n}\n","import { useState, useMemo, useCallback } from \"react\";\nimport { isOutOfRange } from \"../../../helpers/smartReport\";\nimport type { Vital, HistoryPoint } from \"../../types\";\n\nexport function useVitalHistoryPanel(vital: Vital, points: HistoryPoint[]) {\n const [selected, setSelected] = useState<Set<number>>(new Set());\n\n const outOfRangeCount = useMemo(\n () => points.filter((p) => isOutOfRange({ ...vital, status: p.status })).length,\n [points, vital],\n );\n\n const allSelected = points.length > 0 && points.every((_, i) => selected.has(i));\n const someSelected = selected.size > 0;\n\n const togglePoint = useCallback((i: number) => {\n setSelected((prev) => {\n const n = new Set(prev);\n n.has(i) ? n.delete(i) : n.add(i);\n return n;\n });\n }, []);\n\n const toggleAll = useCallback(() => {\n setSelected(allSelected ? new Set() : new Set(points.map((_, i) => i)));\n }, [allSelected, points]);\n\n const clearSelection = useCallback(() => setSelected(new Set()), []);\n\n const buildHistoryText = useCallback(\n (pts: HistoryPoint[]) => {\n const lines = pts.map(\n (p) => `${vital.name}: ${p.value} ${p.unit} (${p.date}${p.caseLabel ? ` · ${p.caseLabel}` : \"\"})`,\n );\n return [`**${vital.name} — Historical data:**`, ...lines].join(\"\\n\");\n },\n [vital.name],\n );\n\n return {\n selected,\n outOfRangeCount,\n allSelected,\n someSelected,\n togglePoint,\n toggleAll,\n clearSelection,\n buildHistoryText,\n };\n}\n"],"mappings":"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","names":["useCallback","useMemo","useState","HistoryRow","useCallback","recordId","useMemo","useState"]}
|
|
@@ -235,6 +235,7 @@ function VitalHistoryPanel({
|
|
|
235
235
|
someSelected,
|
|
236
236
|
togglePoint,
|
|
237
237
|
toggleAll,
|
|
238
|
+
clearSelection,
|
|
238
239
|
buildHistoryText
|
|
239
240
|
} = useVitalHistoryPanel(
|
|
240
241
|
_nullishCoalesce(vital, () => ( {
|
|
@@ -248,21 +249,23 @@ function VitalHistoryPanel({
|
|
|
248
249
|
})),
|
|
249
250
|
filteredPoints
|
|
250
251
|
);
|
|
251
|
-
const handleCopyToNote = _react.useCallback.call(void 0, () => {
|
|
252
|
+
const handleCopyToNote = _react.useCallback.call(void 0, async () => {
|
|
252
253
|
const chosen = points.filter((_, i) => selected.has(i));
|
|
253
254
|
if (!chosen.length) return;
|
|
254
255
|
const text = buildHistoryText(chosen);
|
|
255
256
|
if (onCopyVitalsToNote) {
|
|
256
|
-
|
|
257
|
+
await onCopyVitalsToNote(text);
|
|
258
|
+
clearSelection();
|
|
257
259
|
} else if (onCopyToNote) {
|
|
258
260
|
const rect = _optionalChain([copyBtnRef, 'access', _6 => _6.current, 'optionalAccess', _7 => _7.getBoundingClientRect, 'call', _8 => _8()]);
|
|
259
|
-
|
|
261
|
+
const result = await onCopyToNote(
|
|
260
262
|
text,
|
|
261
263
|
rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : void 0,
|
|
262
264
|
vital ? toHistoryNoteRows(vital, chosen) : void 0
|
|
263
265
|
);
|
|
266
|
+
if (result !== false) clearSelection();
|
|
264
267
|
}
|
|
265
|
-
}, [points, selected, buildHistoryText, onCopyVitalsToNote, onCopyToNote, vital]);
|
|
268
|
+
}, [points, selected, buildHistoryText, onCopyVitalsToNote, onCopyToNote, vital, clearSelection]);
|
|
266
269
|
const hasCopyToNote = !!(onCopyToNote || onCopyVitalsToNote);
|
|
267
270
|
if (preview.status === "loading") {
|
|
268
271
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
@@ -440,4 +443,4 @@ function VitalHistoryPanel({
|
|
|
440
443
|
|
|
441
444
|
|
|
442
445
|
exports.VitalHistoryPanel = VitalHistoryPanel;
|
|
443
|
-
//# sourceMappingURL=chunk-
|
|
446
|
+
//# sourceMappingURL=chunk-KTHLLAAG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/medical-records-ui/medical-records-ui/dist/chunk-KTHLLAAG.js","../src/views/containers/care-panel/VitalHistoryPanel.tsx","../src/views/hooks/care-panel/useVitalHistoryPanel.ts"],"names":[],"mappings":"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","file":"/home/runner/work/medical-records-ui/medical-records-ui/dist/chunk-KTHLLAAG.js","sourcesContent":[null,"\"use client\";\n\nimport { ChevronLeft, Check, LoaderCircle } from \"lucide-react\";\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { isOutOfRange } from \"../../../helpers/smartReport\";\nimport { useSmartRecordsActions } from \"../../context/SmartRecordsActionsContext\";\nimport { useVitalHistoryPanel } from \"../../hooks/care-panel/useVitalHistoryPanel\";\nimport { useParameterTrend } from \"../../hooks/care-panel/useParameterTrend\";\nimport { invalidateRecordPanelTable } from \"../../hooks/care-panel/useRecordPanelTable\";\nimport { useRecordPreview } from \"../../../connection/useRecordPreview\";\nimport type { HistoryPoint } from \"../../types\";\nimport type {\n VitalStatus,\n Vital,\n VitalHistoryPoint,\n} from \"../../../helpers/smartReport\";\nimport type { VitalNoteRow } from \"../../../helpers/vitalsPanel\";\nimport type { ParameterTrendResponse } from \"@eka-care/medical-records-ts-sdk\";\nimport { Typography } from \"widgets\";\n\nconst HISTORY_COLS = \"2fr 2fr 88px\";\n\n// One row per reading — date is folded into `value` since the shared note\n// table has no dedicated date column (each reading needs to stay distinguishable).\nfunction toHistoryNoteRows(vital: Vital, pts: HistoryPoint[]): VitalNoteRow[] {\n return pts.map((p) => {\n const dateSuffix = p.date ? ` (${p.date}${p.caseLabel ? ` · ${p.caseLabel}` : \"\"})` : \"\";\n return {\n name: vital.name,\n value: `${p.value}${p.unit ? ` ${p.unit}` : \"\"}${dateSuffix}`,\n unit: \"\",\n refRange: vital.refRange,\n };\n });\n}\n\nfunction normalizeStatus(displayResult: string): VitalStatus {\n const s = displayResult.toLowerCase();\n if (s.includes(\"high\") || s.includes(\"above\") || s === \"abnormal_high\")\n return \"high\";\n if (s.includes(\"low\") || s.includes(\"below\") || s === \"abnormal_low\")\n return \"low\";\n if (s.includes(\"normal\") || s.includes(\"in range\") || s === \"ok\")\n return \"normal\";\n return \"unknown\";\n}\n\ninterface VitalHistoryPanelProps {\n recordId: string;\n vitalId: string;\n caseId?: string;\n returnTo?: \"smart\" | \"careContext\";\n}\n\ninterface HistoryRowProps {\n index: number;\n point: HistoryPoint;\n vital: Vital;\n isSelected: boolean;\n isLast: boolean;\n onToggle: (i: number) => void;\n onViewRecord: (\n recordId: string,\n returnTo: \"smart\" | \"history\",\n returnVitalId?: string,\n ) => void;\n}\n\nconst HistoryRow = memo(function HistoryRow({\n index,\n point,\n vital,\n isSelected,\n isLast,\n onToggle,\n onViewRecord,\n}: HistoryRowProps) {\n const oor = isOutOfRange({ ...vital, status: point.status });\n const handleToggle = useCallback(() => onToggle(index), [onToggle, index]);\n const handleViewRecord = useCallback(\n () => onViewRecord(point.recordId, \"history\", vital.id),\n [onViewRecord, point.recordId, vital.id],\n );\n\n return (\n <div className={`mr-cc-table__row-wrap${isLast ? \" mr-cc-table__row-wrap--last\" : \"\"}`}>\n <div\n className={`mr-cc-table__row${isSelected ? \" mr-cc-table__row--selected\" : \"\"}`}\n role=\"row\"\n style={{ gridTemplateColumns: HISTORY_COLS, cursor: \"pointer\" }}\n onClick={handleToggle}\n >\n <div\n className=\"mr-cc-table__reading-cell\"\n role=\"cell\"\n style={{ flexDirection: \"row\", alignItems: \"center\", gap: \"8px\" }}\n >\n <span\n className={`mr-sv__checkbox mr-cc-table__row-check${isSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n handleToggle();\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n handleToggle();\n }\n }}\n >\n {isSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <div className=\"mr-cc-table__reading-value-row\">\n {point.value ? (\n <>\n <span\n className={`mr-cc-table__rvalue${oor ? \" mr-cc-table__rvalue--oor\" : \"\"}`}\n >\n {point.value}\n </span>\n {point.unit && (\n <span className=\"mr-cc-table__runit\">{point.unit}</span>\n )}\n </>\n ) : (\n <span className=\"mr-cc-table__empty-dash\">—</span>\n )}\n </div>\n </div>\n\n <div className=\"mr-cc-table__reading-cell\" role=\"cell\">\n {point.date ? (\n <span className=\"mr-cc-table__rvalue\">{point.date}</span>\n ) : (\n <span className=\"mr-cc-table__empty-dash\">—</span>\n )}\n </div>\n\n <div\n className=\"mr-cc-table__actions\"\n role=\"cell\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n className=\"mr-sv__view-record-btn\"\n onClick={handleViewRecord}\n >\n View record\n </button>\n </div>\n </div>\n </div>\n );\n});\n\nexport function VitalHistoryPanel({\n recordId,\n vitalId,\n caseId,\n}: VitalHistoryPanelProps) {\n const { back, openOriginal: _openOriginal, onCopyToNote, onCopyVitalsToNote, onToast } =\n useSmartRecordsActions();\n\n const openOriginal = useCallback(\n (recordId: string, returnTo: \"smart\" | \"history\" | \"careContext\", returnVitalId?: string) => {\n invalidateRecordPanelTable(recordId);\n _openOriginal(recordId, caseId ? \"careContext\" : returnTo, returnVitalId, caseId);\n },\n [_openOriginal, caseId],\n );\n const preview = useRecordPreview(recordId);\n const vital = preview.vitals.find((v) => v.id === vitalId);\n const copyBtnRef = useRef<HTMLButtonElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n const { data: trendData, status: trendStatus } = useParameterTrend(\n vital?.ekaId,\n );\n\n const points = useMemo((): HistoryPoint[] => {\n const trend = trendData as ParameterTrendResponse | null;\n if (!trend?.vitals_info?.length) return [];\n return trend.vitals_info\n .sort((a, b) => (b.date ?? 0) - (a.date ?? 0))\n .map((info) => ({\n date: (info.display_time || \"\").replace(/['‘’]/g, \" \"),\n caseLabel: \"\",\n value:\n info.val !== undefined\n ? String(info.val)\n : ((info as any).val_string ?? \"\"),\n unit: trend.unit,\n status: normalizeStatus(info.display_result ?? \"\"),\n recordId: info.document_id,\n recordName: trend.name,\n }));\n }, [trendData]);\n\n type VhpTab = \"all\" | \"oor\" | \"none\";\n const [activeTab, setActiveTab] = useState<VhpTab>(\"all\");\n\n const oorCount = useMemo(\n () => points.filter((p) => p.status === \"high\" || p.status === \"low\").length,\n [points],\n );\n const noneCount = useMemo(\n () => points.filter((p) => p.status === \"unknown\").length,\n [points],\n );\n\n useEffect(() => {\n if (activeTab === \"oor\" && oorCount === 0) setActiveTab(\"all\");\n if (activeTab === \"none\" && noneCount === 0) setActiveTab(\"all\");\n }, [activeTab, oorCount, noneCount]);\n\n useEffect(() => {\n if (trendStatus === \"error\") {\n back();\n onToast?.(\"Failed to load vital history\", \"error\");\n }\n }, [trendStatus, back, onToast]);\n\n const filteredPoints = useMemo(() => {\n if (activeTab === \"oor\") return points.filter((p) => p.status === \"high\" || p.status === \"low\");\n if (activeTab === \"none\") return points.filter((p) => p.status === \"unknown\");\n return points;\n }, [points, activeTab]);\n\n const rowVirtualizer = useVirtualizer({\n count: filteredPoints.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => 50,\n overscan: 5,\n });\n\n const {\n selected,\n allSelected,\n someSelected,\n togglePoint,\n toggleAll,\n clearSelection,\n buildHistoryText,\n } = useVitalHistoryPanel(\n vital ?? {\n id: vitalId,\n name: \"\",\n value: \"\",\n unit: \"\",\n refRange: \"\",\n status: \"normal\" as VitalStatus,\n history: [] as VitalHistoryPoint[],\n },\n filteredPoints,\n );\n\n const handleCopyToNote = useCallback(async () => {\n const chosen = points.filter((_, i) => selected.has(i));\n if (!chosen.length) return;\n const text = buildHistoryText(chosen);\n if (onCopyVitalsToNote) {\n await onCopyVitalsToNote(text);\n clearSelection();\n } else if (onCopyToNote) {\n const rect = copyBtnRef.current?.getBoundingClientRect();\n const result = await onCopyToNote(\n text,\n rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : undefined,\n vital ? toHistoryNoteRows(vital, chosen) : undefined,\n );\n if (result !== false) clearSelection();\n }\n }, [points, selected, buildHistoryText, onCopyVitalsToNote, onCopyToNote, vital, clearSelection]);\n\n const hasCopyToNote = !!(onCopyToNote || onCopyVitalsToNote);\n\n if (preview.status === \"loading\") {\n return (\n <div\n className=\"mr-sv__panel\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <LoaderCircle\n size={32}\n className=\"mr-sv__loading-spinner\"\n aria-hidden\n />\n </div>\n );\n }\n\n if (!vital) {\n return (\n <div className=\"mr-sv__panel\">\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n Vital not found.\n </Typography>\n </div>\n );\n }\n\n return (\n <div className=\"mr-sv__panel\">\n <div className=\"mr-sv__back-row\">\n <button type=\"button\" className=\"mr-sv__back-btn\" onClick={back}>\n <ChevronLeft size={16} aria-hidden />\n Back\n </button>\n </div>\n {/* Header */}\n <div className=\"mr-sv__panel-header\">\n <div className=\"mr-sv__panel-left\">\n <div className=\"mr-sv__panel-info\">\n <div className=\"mr-sv__panel-name-row\">\n <Typography\n variant=\"label\"\n as=\"span\"\n className=\"mr-sv__panel-name\"\n >\n {vital.name}\n </Typography>\n {vital.refRange && (\n <span className=\"mr-sv__panel-ref-badge\">\n Ref: {vital.refRange}\n </span>\n )}\n </div>\n <div className=\"mr-sv__panel-meta\">\n {trendStatus === \"loaded\" && (\n <span>\n {points.length} reading{points.length !== 1 ? \"s\" : \"\"}\n {oorCount > 0 && (\n <>\n {\" \"}\n ·{\" \"}\n <span className=\"mr-sv__oor\">\n {oorCount} out of range\n </span>\n </>\n )}\n </span>\n )}\n </div>\n </div>\n </div>\n <span className=\"mr-cc-panel__viewing-label\">Viewing vital history</span>\n </div>\n\n {/* Filter tabs — only shown when at least one sub-category has data */}\n {trendStatus === \"loaded\" && points.length > 0 && (oorCount > 0 || noneCount > 0) && (\n <div className=\"mr-orig__smart-tabs-wrap\" style={{ padding: \"8px 16px 0\" }}>\n <div className=\"mr-orig__smart-tabs\">\n {([\"all\", \"oor\", \"none\"] as VhpTab[]).map((tab) => {\n if (tab === \"oor\" && oorCount === 0) return null;\n if (tab === \"none\" && noneCount === 0) return null;\n const count = tab === \"all\" ? points.length : tab === \"oor\" ? oorCount : noneCount;\n const label = tab === \"all\" ? \"All\" : tab === \"oor\" ? \"Out of range\" : \"No interpretation\";\n return (\n <button\n key={tab}\n type=\"button\"\n className={`mr-orig__smart-tab${activeTab === tab ? \" mr-orig__smart-tab--active\" : \"\"}`}\n onClick={() => setActiveTab(tab)}\n >\n {label} ({count})\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Body */}\n <div className=\"mr-sv__panel-body\" ref={scrollRef} style={{ overflowY: \"auto\" }}>\n {trendStatus === \"loading\" && (\n <div className=\"mr-cc-table mr-cc-table--state\">\n <LoaderCircle size={20} className=\"mr-sv__loading-spinner\" aria-hidden />\n <Typography variant=\"muted\">Loading vital history…</Typography>\n </div>\n )}\n {trendStatus === \"loaded\" && points.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No historical data available for this vital.\n </Typography>\n )}\n {points.length > 0 && (\n <div className=\"mr-vhp-table\" role=\"table\">\n <div\n className=\"mr-cc-table__row mr-cc-table__row--head\"\n role=\"row\"\n style={{ gridTemplateColumns: HISTORY_COLS, margin: 0 }}\n >\n <span className=\"mr-cc-table__head-cell\" role=\"columnheader\">READING</span>\n <span className=\"mr-cc-table__head-cell\" role=\"columnheader\">DATE</span>\n <span className=\"mr-cc-table__head-cell\" aria-hidden />\n </div>\n {filteredPoints.length === 0 ? (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No readings match this filter.\n </Typography>\n ) : (\n <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: \"relative\" }}>\n {rowVirtualizer.getVirtualItems().map((virtualRow) => (\n <div\n key={virtualRow.key}\n data-index={virtualRow.index}\n ref={rowVirtualizer.measureElement}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <HistoryRow\n index={virtualRow.index}\n point={filteredPoints[virtualRow.index]}\n vital={vital}\n isSelected={selected.has(virtualRow.index)}\n isLast={virtualRow.index === filteredPoints.length - 1}\n onToggle={togglePoint}\n onViewRecord={openOriginal}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"mr-cc-table__footer\">\n <span\n className={`mr-sv__checkbox mr-cc-table__footer-check${allSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={allSelected}\n tabIndex={0}\n onClick={toggleAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleAll();\n }\n }}\n >\n {allSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <span className=\"mr-cc-table__footer-label\" onClick={toggleAll}>Select all</span>\n <span className=\"mr-cc-table__footer-count\">{selected.size} of {points.length} selected</span>\n <button\n ref={copyBtnRef}\n type=\"button\"\n className=\"mr-cc-table__copy-note-btn\"\n disabled={!someSelected || !hasCopyToNote}\n onClick={handleCopyToNote}\n >\n Copy to note\n </button>\n </div>\n </div>\n );\n}\n","import { useState, useMemo, useCallback } from \"react\";\nimport { isOutOfRange } from \"../../../helpers/smartReport\";\nimport type { Vital, HistoryPoint } from \"../../types\";\n\nexport function useVitalHistoryPanel(vital: Vital, points: HistoryPoint[]) {\n const [selected, setSelected] = useState<Set<number>>(new Set());\n\n const outOfRangeCount = useMemo(\n () => points.filter((p) => isOutOfRange({ ...vital, status: p.status })).length,\n [points, vital],\n );\n\n const allSelected = points.length > 0 && points.every((_, i) => selected.has(i));\n const someSelected = selected.size > 0;\n\n const togglePoint = useCallback((i: number) => {\n setSelected((prev) => {\n const n = new Set(prev);\n n.has(i) ? n.delete(i) : n.add(i);\n return n;\n });\n }, []);\n\n const toggleAll = useCallback(() => {\n setSelected(allSelected ? new Set() : new Set(points.map((_, i) => i)));\n }, [allSelected, points]);\n\n const clearSelection = useCallback(() => setSelected(new Set()), []);\n\n const buildHistoryText = useCallback(\n (pts: HistoryPoint[]) => {\n const lines = pts.map(\n (p) => `${vital.name}: ${p.value} ${p.unit} (${p.date}${p.caseLabel ? ` · ${p.caseLabel}` : \"\"})`,\n );\n return [`**${vital.name} — Historical data:**`, ...lines].join(\"\\n\");\n },\n [vital.name],\n );\n\n return {\n selected,\n outOfRangeCount,\n allSelected,\n someSelected,\n togglePoint,\n toggleAll,\n clearSelection,\n buildHistoryText,\n };\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }require('./chunk-
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }require('./chunk-KTHLLAAG.js');
|
|
2
2
|
require('./chunk-WXCGQDIL.js');
|
|
3
3
|
|
|
4
4
|
|
|
@@ -2432,12 +2432,12 @@ function CareContextEmptyState() {
|
|
|
2432
2432
|
|
|
2433
2433
|
|
|
2434
2434
|
var VitalHistoryPanel2 = _react.lazy.call(void 0,
|
|
2435
|
-
() => Promise.resolve().then(() => _interopRequireWildcard(require("./VitalHistoryPanel-
|
|
2435
|
+
() => Promise.resolve().then(() => _interopRequireWildcard(require("./VitalHistoryPanel-VQQ27P6Q.js"))).then((m) => ({
|
|
2436
2436
|
default: m.VitalHistoryPanel
|
|
2437
2437
|
}))
|
|
2438
2438
|
);
|
|
2439
2439
|
var OriginalRecordPanel = _react.lazy.call(void 0,
|
|
2440
|
-
() => Promise.resolve().then(() => _interopRequireWildcard(require("./OriginalRecordPanel-
|
|
2440
|
+
() => Promise.resolve().then(() => _interopRequireWildcard(require("./OriginalRecordPanel-DCGRXQST.js"))).then((m) => ({
|
|
2441
2441
|
default: m.OriginalRecordPanel
|
|
2442
2442
|
}))
|
|
2443
2443
|
);
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-5TPILQYM.mjs";
|
|
2
2
|
import "./chunk-3J6XMPXB.mjs";
|
|
3
3
|
import {
|
|
4
4
|
SmartSparkles_default,
|
|
@@ -2432,12 +2432,12 @@ function CareContextEmptyState() {
|
|
|
2432
2432
|
import { memo as memo5, Suspense as Suspense2, lazy as lazy2 } from "react";
|
|
2433
2433
|
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2434
2434
|
var VitalHistoryPanel2 = lazy2(
|
|
2435
|
-
() => import("./VitalHistoryPanel-
|
|
2435
|
+
() => import("./VitalHistoryPanel-FT5VMJ37.mjs").then((m) => ({
|
|
2436
2436
|
default: m.VitalHistoryPanel
|
|
2437
2437
|
}))
|
|
2438
2438
|
);
|
|
2439
2439
|
var OriginalRecordPanel = lazy2(
|
|
2440
|
-
() => import("./OriginalRecordPanel-
|
|
2440
|
+
() => import("./OriginalRecordPanel-NGLSSJLE.mjs").then((m) => ({
|
|
2441
2441
|
default: m.OriginalRecordPanel
|
|
2442
2442
|
}))
|
|
2443
2443
|
);
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/medical-records-ui/medical-records-ui/dist/OriginalRecordPanel-PR35G6KV.js","../src/views/components/shared/OriginalRecordPanel.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/medical-records-ui/medical-records-ui/dist/OriginalRecordPanel-PR35G6KV.js","sourcesContent":[null,"\"use client\";\n\nimport { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { ChevronLeft, ChevronRight, ChevronDown, ExternalLink, Check, File, LoaderCircle } from \"lucide-react\";\nimport { useStore } from \"zustand\";\nimport { useSdk } from \"../../../connection/useSdk\";\nimport { useRecordPreview } from \"../../../connection/useRecordPreview\";\nimport { useRecordPanelTable } from \"../../hooks/care-panel/useRecordPanelTable\";\nimport { useParameterTrend } from \"../../hooks/care-panel/useParameterTrend\";\nimport { epochToDisplay } from \"../../../helpers/formatters\";\nimport type { ParameterTrendResponse } from \"@eka-care/medical-records-ts-sdk\";\nimport { useSmartRecordsActions } from \"../../context/SmartRecordsActionsContext\";\nimport { IconButton, Typography, SearchInput, Tooltip } from \"widgets\";\nimport type { RecordItem } from \"../../../helpers\";\nimport type { PanelRow } from \"../../../helpers/vitalsPanel\";\nimport { toVitalNoteRows } from \"../../../helpers/vitalsPanel\";\nimport SmartSparkles from \"icons/SmartSparkles\";\n\nconst DocumentViewer = lazy(() =>\n import(\"../../RecordPreview/DocumentViewer\").then((m) => ({\n default: m.DocumentViewer,\n })),\n);\n\ninterface OriginalRecordPanelProps {\n recordId: string;\n caseId?: string;\n onBack: () => void;\n}\n\ntype SrTab = \"all\" | \"oor\" | \"none\";\n\nfunction buildVitalsText(rows: PanelRow[]): string {\n return rows\n .map((r) => {\n const cell = r.cells[0];\n const ref = cell?.refRange ? ` (Ref: ${cell.refRange})` : \"\";\n return `${r.name}: ${cell?.value ?? \"—\"} ${r.unit}${ref}`;\n })\n .join(\"\\n\");\n}\n\nexport function OriginalRecordPanel({\n recordId,\n caseId,\n onBack,\n}: OriginalRecordPanelProps) {\n const { store } = useSdk();\n const record = useStore(store, (s) => s.records.byId[recordId]);\n const recordsById = useStore(store, (s) => s.records.byId);\n const preview = useRecordPreview(recordId);\n const { replaceOriginal, onCopyToNote, onCopyVitalsToNote, hasCopyToNote, onToast } =\n useSmartRecordsActions();\n\n // Smart report vitals (only fetched when record.isSmart)\n const { status: vitalsStatus, table } = useRecordPanelTable(\n record?.isSmart ? recordId : null,\n );\n const [smartPanelOpen, setSmartPanelOpen] = useState(true);\n const [srSearch, setSrSearch] = useState(\"\");\n const [srTab, setSrTab] = useState<SrTab>(\"all\");\n const [expandedVital, setExpandedVital] = useState<string | null>(null);\n const toggleExpand = useCallback((key: string) => {\n setExpandedVital((prev) => (prev === key ? null : key));\n }, []);\n const [srSelected, setSrSelected] = useState<Set<string>>(new Set());\n const srCopyBtnRef = useRef<HTMLButtonElement>(null);\n\n // Dropdown state\n const [dropdownOpen, setDropdownOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!dropdownOpen) return;\n const handler = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setDropdownOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [dropdownOpen]);\n\n const caseRecords = useMemo<RecordItem[]>(() => {\n if (!caseId) return [];\n return Object.values(recordsById)\n .filter(\n (r): r is RecordItem =>\n r != null &&\n (caseId === \"__ungrouped__\" ? r.cases.length === 0 : r.cases.includes(caseId)),\n )\n .sort((a, b) => b.createdAtEpoch - a.createdAtEpoch);\n }, [recordsById, caseId]);\n\n const currentIndex = caseRecords.findIndex((r) => r.id === recordId);\n const total = caseRecords.length;\n const isUngrouped = caseId === \"__ungrouped__\";\n\n const goTo = useCallback(\n (r: RecordItem) => {\n setDropdownOpen(false);\n replaceOriginal(r.id, caseId);\n },\n [replaceOriginal, caseId],\n );\n\n const goPrev = useCallback(() => {\n if (currentIndex > 0) goTo(caseRecords[currentIndex - 1]);\n }, [currentIndex, caseRecords, goTo]);\n\n const goNext = useCallback(() => {\n if (currentIndex < total - 1) goTo(caseRecords[currentIndex + 1]);\n }, [currentIndex, total, caseRecords, goTo]);\n\n const showNavPicker = caseId && total > 0;\n\n // Smart report vitals filtering\n const allRows = table.rows;\n const oorRows = useMemo(\n () => allRows.filter((r) => r.latestStatus === \"high\" || r.latestStatus === \"low\"),\n [allRows],\n );\n const noInterpRows = useMemo(\n () => allRows.filter((r) => r.latestStatus === \"unknown\"),\n [allRows],\n );\n\n const baseRows = srTab === \"oor\" ? oorRows : srTab === \"none\" ? noInterpRows : allRows;\n\n const filteredRows = useMemo(() => {\n if (!srSearch) return baseRows;\n const q = srSearch.toLowerCase();\n return baseRows.filter((r) => r.name.toLowerCase().includes(q));\n }, [baseRows, srSearch]);\n\n const tabCounts = useMemo(() => {\n if (!srSearch) return { all: allRows.length, oor: oorRows.length, none: noInterpRows.length };\n const q = srSearch.toLowerCase();\n return {\n all: allRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n oor: oorRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n none: noInterpRows.filter((r) => r.name.toLowerCase().includes(q)).length,\n };\n }, [srSearch, allRows, oorRows, noInterpRows]);\n\n useEffect(() => {\n setSrSelected(new Set());\n }, [srTab, srSearch]);\n\n useEffect(() => {\n if (srTab === \"oor\" && oorRows.length === 0) setSrTab(\"all\");\n if (srTab === \"none\" && noInterpRows.length === 0) setSrTab(\"all\");\n }, [srTab, oorRows.length, noInterpRows.length]);\n\n const srAllSelected =\n filteredRows.length > 0 && filteredRows.every((r) => srSelected.has(r.key));\n const srSomeSelected = srSelected.size > 0;\n\n const toggleSrRow = useCallback((key: string) => {\n setSrSelected((prev) => {\n const next = new Set(prev);\n next.has(key) ? next.delete(key) : next.add(key);\n return next;\n });\n }, []);\n\n const toggleSrAll = useCallback(() => {\n setSrSelected(\n srAllSelected ? new Set() : new Set(filteredRows.map((r) => r.key)),\n );\n }, [srAllSelected, filteredRows]);\n\n const handleSrCopyToNote = useCallback(() => {\n const selectedRows = filteredRows.filter((r) => srSelected.has(r.key));\n if (!selectedRows.length) return;\n const text = buildVitalsText(selectedRows);\n if (onCopyVitalsToNote) {\n void onCopyVitalsToNote(text);\n } else if (onCopyToNote) {\n const rect = srCopyBtnRef.current?.getBoundingClientRect();\n void onCopyToNote(\n text,\n rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : undefined,\n toVitalNoteRows(selectedRows),\n );\n }\n }, [filteredRows, srSelected, onCopyVitalsToNote, onCopyToNote]);\n\n const htmlCopyBtnRef = useRef<HTMLButtonElement>(null);\n const [isHtmlCopying, setIsHtmlCopying] = useState(false);\n\n const handleHtmlCopyToNote = useCallback(async () => {\n const url = preview.files[0]?.url;\n if (!url) return;\n setIsHtmlCopying(true);\n try {\n const res = await fetch(url);\n const html = await res.text();\n const doc = new DOMParser().parseFromString(html, \"text/html\");\n const text = doc.body.textContent?.trim() ?? \"\";\n if (!text) return;\n if (onCopyVitalsToNote) {\n void onCopyVitalsToNote(text);\n } else if (onCopyToNote) {\n const rect = htmlCopyBtnRef.current?.getBoundingClientRect();\n void onCopyToNote(\n text,\n rect ? { x: rect.left, y: rect.bottom } : undefined,\n );\n }\n } catch {\n onToast?.(\"Failed to copy document text\", \"error\");\n } finally {\n setIsHtmlCopying(false);\n }\n }, [preview.files, onCopyVitalsToNote, onCopyToNote, onToast]);\n\n const isSmart = record?.isSmart ?? false;\n const hasPreview = preview.status === \"loaded\" && preview.files.length > 0;\n\n return (\n <div className=\"mr-sv__panel\">\n <div className=\"mr-sv__panel-header\">\n <button type=\"button\" className=\"mr-sv__back-btn\" onClick={onBack}>\n <ChevronLeft size={16} aria-hidden />\n Back\n </button>\n\n {/* Prev/next record carousel + dropdown — temporarily disabled, will re-enable later.\n {showNavPicker ? (\n <div className=\"mr-orig__nav-wrap\" ref={dropdownRef}>\n <div\n className={`mr-orig__nav-pill${dropdownOpen ? \" mr-orig__nav-pill--open\" : \"\"}`}\n role=\"button\"\n tabIndex={0}\n onClick={() => setDropdownOpen((v) => !v)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setDropdownOpen((v) => !v);\n }\n }}\n >\n <button\n type=\"button\"\n className=\"mr-orig__nav-chevron\"\n onClick={(e) => { e.stopPropagation(); goPrev(); }}\n aria-label=\"Previous record\"\n disabled={currentIndex <= 0}\n >\n <ChevronLeft size={14} aria-hidden />\n </button>\n <div className=\"mr-orig__nav-text\">\n <span className=\"mr-orig__nav-title\">{record?.title ?? \"Record\"}</span>\n <span className=\"mr-orig__nav-counter\">\n {currentIndex + 1} of {total}\n </span>\n </div>\n <button\n type=\"button\"\n className=\"mr-orig__nav-chevron\"\n onClick={(e) => { e.stopPropagation(); goNext(); }}\n aria-label=\"Next record\"\n disabled={currentIndex >= total - 1}\n >\n <ChevronRight size={14} aria-hidden />\n </button>\n </div>\n\n {dropdownOpen && (\n <div className=\"mr-orig__dropdown\">\n <div className=\"mr-orig__dropdown-eyebrow\">\n {total} RECORD{total !== 1 ? \"S\" : \"\"}{\" \"}\n {isUngrouped ? \"WITH NO CARE CONTEXT\" : \"FOUND IN THIS ENCOUNTER\"}\n </div>\n <div className=\"mr-orig__dropdown-list\">\n {caseRecords.map((r) => {\n const isActive = r.id === recordId;\n return (\n <button\n key={r.id}\n type=\"button\"\n className={`mr-orig__dropdown-item${isActive ? \" mr-orig__dropdown-item--active\" : \"\"}`}\n onClick={() => goTo(r)}\n >\n <div className=\"mr-orig__dropdown-icon\">\n <File size={16} aria-hidden />\n {r.isSmart && (\n <SmartSparkles\n className=\"mr-orig__dropdown-smart-dot\"\n aria-label=\"Smart report\"\n />\n )}\n </div>\n <div className=\"mr-orig__dropdown-info\">\n <div className=\"mr-orig__dropdown-title-row\">\n <span className=\"mr-orig__dropdown-title\">{r.title}</span>\n {r.isSmart && (\n <span className=\"mr-orig__dropdown-smart-badge\">\n <SmartSparkles aria-hidden />\n Smart Report\n </span>\n )}\n {r.fileType?.toUpperCase() === \"HTML\" && (\n <span className=\"mr-tag-chip mr-tag-chip--html\">\n <span className=\"mr-tag-chip__label\">HTML</span>\n </span>\n )}\n </div>\n <div className=\"mr-orig__dropdown-meta\">\n <span>{epochToDisplay(r.createdAtEpoch)}</span>\n {r.isSmart && r.totalVitals > 0 && (\n <>\n <span className=\"mr-orig__dropdown-dot\">·</span>\n <span>{r.totalVitals} vitals</span>\n </>\n )}\n </div>\n </div>\n {isActive && (\n <Check\n size={14}\n className=\"mr-orig__dropdown-check\"\n aria-hidden\n />\n )}\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n ) : record ? (\n */}\n {record ? (\n <div className=\"mr-sv__panel-info\">\n <Typography variant=\"label\" as=\"span\" className=\"mr-sv__panel-name\">\n {record.title}\n </Typography>\n <Typography variant=\"hint\" as=\"span\" className=\"mr-sv__panel-meta-text\">\n {epochToDisplay(record.createdAtEpoch)}\n </Typography>\n </div>\n ) : null}\n {/* } */}\n\n <div className=\"mr-orig__header-actions\">\n {preview.isHtml && hasCopyToNote && (\n <button\n ref={htmlCopyBtnRef}\n type=\"button\"\n className=\"mr-orig__html-copy-btn\"\n onClick={handleHtmlCopyToNote}\n disabled={isHtmlCopying}\n >\n {isHtmlCopying && <LoaderCircle size={12} className=\"mr-sv__loading-spinner\" aria-hidden />}\n Copy to note\n </button>\n )}\n {hasPreview && (\n <IconButton\n icon={<ExternalLink size={16} aria-hidden />}\n label=\"Open in new tab\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() =>\n window.open(preview.files[0].url, \"_blank\", \"noopener,noreferrer\")\n }\n />\n )}\n </div>\n </div>\n\n <div\n className=\"mr-sv__panel-body\"\n style={{ flex: 1, display: \"flex\", flexDirection: \"column\", overflow: \"hidden\" }}\n >\n {preview.status === \"loading\" && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n }}\n >\n <LoaderCircle size={44} className=\"mr-sv__loading-spinner\" aria-hidden />\n </div>\n )}\n {preview.status === \"error\" && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n Failed to load document preview.\n </Typography>\n )}\n {preview.status === \"loaded\" && preview.files.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No preview available for this record.\n </Typography>\n )}\n\n {/* Non-smart: full-width PDF */}\n {hasPreview && !isSmart && (\n <div\n className=\"mr-record-preview__body\"\n style={{ flex: 1, display: \"flex\", overflow: \"hidden\" }}\n >\n <Suspense fallback={null}>\n <DocumentViewer\n files={preview.files}\n title={record?.title ?? \"\"}\n isHtml={preview.isHtml}\n />\n </Suspense>\n </div>\n )}\n\n {/* Smart: split view — PDF left, smart report panel right */}\n {hasPreview && isSmart && (\n <div className=\"mr-orig__split\">\n <div className=\"mr-orig__pdf-side\">\n <Suspense fallback={null}>\n <DocumentViewer\n files={preview.files}\n title={record?.title ?? \"\"}\n isHtml={preview.isHtml}\n />\n </Suspense>\n </div>\n\n {smartPanelOpen ? (\n <div className=\"mr-orig__smart-side\">\n {/* Header */}\n <div className=\"mr-orig__smart-hdr\">\n <span className=\"mr-orig__smart-title-row\">\n <span className=\"mr-orig__smart-title\">Smart Report</span>\n <SmartSparkles className=\"mr-orig__smart-title-icon\" aria-hidden />\n </span>\n <button\n type=\"button\"\n className=\"mr-sv__sidebar-collapse-btn mr-orig__smart-expanded-btn\"\n aria-label=\"Collapse smart report panel\"\n aria-expanded={true}\n onClick={() => setSmartPanelOpen(false)}\n >\n <ChevronRight size={14} aria-hidden />\n </button>\n </div>\n\n {/* Search */}\n <SearchInput\n className=\"mr-orig__smart-search\"\n iconSize={16}\n placeholder=\"Search vitals\"\n value={srSearch}\n onChange={setSrSearch}\n />\n\n {/* Filter tabs — only when at least one sub-category has data */}\n {(oorRows.length > 0 || noInterpRows.length > 0) && (\n <div className=\"mr-orig__smart-tabs-wrap\">\n <div className=\"mr-orig__smart-tabs\">\n {([\"all\", \"oor\", \"none\"] as SrTab[]).map((tab) => {\n if (tab === \"oor\" && oorRows.length === 0) return null;\n if (tab === \"none\" && noInterpRows.length === 0) return null;\n const count =\n tab === \"all\"\n ? tabCounts.all\n : tab === \"oor\"\n ? tabCounts.oor\n : tabCounts.none;\n const label =\n tab === \"all\"\n ? \"All\"\n : tab === \"oor\"\n ? \"Out of range\"\n : \"No interpretation\";\n return (\n <button\n key={tab}\n type=\"button\"\n className={`mr-orig__smart-tab${srTab === tab ? \" mr-orig__smart-tab--active\" : \"\"}`}\n onClick={() => setSrTab(tab)}\n >\n {label} ({count})\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Vital list */}\n <div className=\"mr-orig__smart-list\">\n {vitalsStatus === \"loading\" && (\n <div className=\"mr-orig__smart-loading\">\n <LoaderCircle\n size={20}\n className=\"mr-sv__loading-spinner\"\n aria-hidden\n />\n </div>\n )}\n {vitalsStatus === \"loaded\" && filteredRows.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-orig__smart-empty\">\n No vitals match.\n </Typography>\n )}\n {vitalsStatus === \"loaded\" &&\n filteredRows.map((row, idx) => {\n const cell = row.cells[0];\n const isOor =\n row.latestStatus === \"high\" || row.latestStatus === \"low\";\n const isSelected = srSelected.has(row.key);\n const isLast = idx === filteredRows.length - 1;\n return (\n <div\n key={row.key}\n className={`mr-orig__vital-item${isLast ? \" mr-orig__vital-item--last\" : \"\"}`}\n >\n <div\n className={`mr-orig__vital-row mr-orig__vital-row--selectable${isSelected ? \" mr-orig__vital-row--selected\" : \"\"}`}\n onClick={() => toggleSrRow(row.key)}\n >\n <span\n className={`mr-sv__checkbox mr-cc-table__row-check${isSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n toggleSrRow(row.key);\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n toggleSrRow(row.key);\n }\n }}\n >\n {isSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <div className=\"mr-orig__vital-info\">\n <span className=\"mr-orig__vital-name\">{row.name}</span>\n {row.refRange && (\n <span className=\"mr-orig__vital-ref\">\n Ref {row.refRange}\n </span>\n )}\n </div>\n {cell && (\n <div className=\"mr-orig__vital-value\">\n <span\n className={`mr-orig__vital-val${isOor ? \" mr-orig__vital-val--oor\" : \"\"}`}\n >\n {cell.value}\n </span>\n {cell.unit && (\n <span className=\"mr-orig__vital-unit\">{cell.unit}</span>\n )}\n </div>\n )}\n {row.ekaId && (\n <button\n type=\"button\"\n className={`mr-orig__vital-expand-btn${expandedVital === row.key ? \" mr-orig__vital-expand-btn--open\" : \"\"}`}\n onClick={(e) => { e.stopPropagation(); toggleExpand(row.key); }}\n aria-label={expandedVital === row.key ? \"Collapse readings\" : \"Show latest readings\"}\n >\n <ChevronDown size={13} aria-hidden />\n </button>\n )}\n </div>\n {expandedVital === row.key && row.ekaId && (\n <VitalReadingsExpanded vitalName={row.name} ekaId={row.ekaId} />\n )}\n </div>\n );\n })}\n </div>\n\n {/* Footer */}\n <div className=\"mr-cc-table__footer\">\n <span\n className={`mr-sv__checkbox mr-cc-table__footer-check${srAllSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={srAllSelected}\n tabIndex={0}\n onClick={toggleSrAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleSrAll();\n }\n }}\n >\n {srAllSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <span className=\"mr-cc-table__footer-label\" onClick={toggleSrAll}>Select all</span>\n <span className=\"mr-cc-table__footer-count\">\n {srSelected.size} of {filteredRows.length} selected\n </span>\n <button\n ref={srCopyBtnRef}\n type=\"button\"\n className=\"mr-cc-table__copy-note-btn\"\n disabled={!srSomeSelected || !hasCopyToNote}\n onClick={handleSrCopyToNote}\n >\n Copy to note\n </button>\n </div>\n </div>\n ) : (\n <div className=\"mr-orig__smart-side mr-orig__smart-side--collapsed\">\n <Tooltip content=\"Show smart report\">\n <button\n type=\"button\"\n className=\"mr-sv__sidebar-collapse-btn mr-orig__smart-collapsed-btn\"\n aria-label=\"Expand smart report panel\"\n aria-expanded={false}\n onClick={() => setSmartPanelOpen(true)}\n >\n <span className=\"mr-orig__smart-collapsed-icon-wrap\">\n <SmartSparkles className=\"mr-orig__smart-collapsed-icon\" aria-hidden />\n </span>\n </button>\n </Tooltip>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction VitalReadingsExpanded({ vitalName, ekaId }: { vitalName: string; ekaId: string }) {\n const { data: trendData, status } = useParameterTrend(ekaId);\n\n const readings = useMemo(() => {\n const trend = trendData as ParameterTrendResponse | null;\n if (!trend?.vitals_info?.length) return [];\n return [...trend.vitals_info]\n .sort((a, b) => (b.date ?? 0) - (a.date ?? 0))\n .slice(0, 3)\n .map((info) => {\n const dr = (info.display_result ?? \"\").toLowerCase();\n const isOor = dr.includes(\"high\") || dr.includes(\"above\") || dr.includes(\"abnormal_high\") ||\n dr.includes(\"low\") || dr.includes(\"below\") || dr.includes(\"abnormal_low\");\n return {\n value: info.val != null ? String(info.val) : ((info as any).val_string ?? \"—\"),\n date: (info.display_time || \"\").replace(/['‘’]/g, \" \"),\n isOor,\n };\n });\n }, [trendData]);\n\n if (status === \"loading\") {\n return (\n <div className=\"mr-orig__vital-readings mr-orig__vital-readings--loading\">\n <LoaderCircle size={16} className=\"mr-sv__loading-spinner\" aria-hidden />\n </div>\n );\n }\n\n if (status === \"error\" || !readings.length) {\n return (\n <div className=\"mr-orig__vital-readings\">\n <Typography variant=\"muted\" className=\"mr-orig__vital-readings-empty\">\n No readings available\n </Typography>\n </div>\n );\n }\n\n return (\n <div className=\"mr-orig__vital-readings\">\n <div className=\"mr-orig__vital-readings-title\">\n LATEST READINGS FOR {vitalName.toUpperCase()}\n </div>\n <div className=\"mr-orig__vital-readings-grid\">\n {readings.map((r, i) => (\n <div key={i} className=\"mr-orig__vital-reading-item\">\n <span className={`mr-orig__vital-reading-value${r.isOor ? \" mr-orig__vital-reading-value--oor\" : \"\"}`}>{r.value}</span>\n <span className=\"mr-orig__vital-reading-date\">{r.date}</span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var _chunk636WE5XCjs = require('./chunk-636WE5XC.js');
|
|
5
|
-
require('./chunk-STQYPHI3.js');
|
|
6
|
-
require('./chunk-QGGLSO4W.js');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
exports.VitalHistoryPanel = _chunk636WE5XCjs.VitalHistoryPanel;
|
|
10
|
-
//# sourceMappingURL=VitalHistoryPanel-7GT3GZEJ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/medical-records-ui/medical-records-ui/dist/chunk-636WE5XC.js","../src/views/containers/care-panel/VitalHistoryPanel.tsx","../src/views/hooks/care-panel/useVitalHistoryPanel.ts"],"names":[],"mappings":"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","file":"/home/runner/work/medical-records-ui/medical-records-ui/dist/chunk-636WE5XC.js","sourcesContent":[null,"\"use client\";\n\nimport { ChevronLeft, Check, LoaderCircle } from \"lucide-react\";\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { isOutOfRange } from \"../../../helpers/smartReport\";\nimport { useSmartRecordsActions } from \"../../context/SmartRecordsActionsContext\";\nimport { useVitalHistoryPanel } from \"../../hooks/care-panel/useVitalHistoryPanel\";\nimport { useParameterTrend } from \"../../hooks/care-panel/useParameterTrend\";\nimport { invalidateRecordPanelTable } from \"../../hooks/care-panel/useRecordPanelTable\";\nimport { useRecordPreview } from \"../../../connection/useRecordPreview\";\nimport type { HistoryPoint } from \"../../types\";\nimport type {\n VitalStatus,\n Vital,\n VitalHistoryPoint,\n} from \"../../../helpers/smartReport\";\nimport type { VitalNoteRow } from \"../../../helpers/vitalsPanel\";\nimport type { ParameterTrendResponse } from \"@eka-care/medical-records-ts-sdk\";\nimport { Typography } from \"widgets\";\n\nconst HISTORY_COLS = \"2fr 2fr 88px\";\n\n// One row per reading — date is folded into `value` since the shared note\n// table has no dedicated date column (each reading needs to stay distinguishable).\nfunction toHistoryNoteRows(vital: Vital, pts: HistoryPoint[]): VitalNoteRow[] {\n return pts.map((p) => {\n const dateSuffix = p.date ? ` (${p.date}${p.caseLabel ? ` · ${p.caseLabel}` : \"\"})` : \"\";\n return {\n name: vital.name,\n value: `${p.value}${p.unit ? ` ${p.unit}` : \"\"}${dateSuffix}`,\n unit: \"\",\n refRange: vital.refRange,\n };\n });\n}\n\nfunction normalizeStatus(displayResult: string): VitalStatus {\n const s = displayResult.toLowerCase();\n if (s.includes(\"high\") || s.includes(\"above\") || s === \"abnormal_high\")\n return \"high\";\n if (s.includes(\"low\") || s.includes(\"below\") || s === \"abnormal_low\")\n return \"low\";\n if (s.includes(\"normal\") || s.includes(\"in range\") || s === \"ok\")\n return \"normal\";\n return \"unknown\";\n}\n\ninterface VitalHistoryPanelProps {\n recordId: string;\n vitalId: string;\n caseId?: string;\n returnTo?: \"smart\" | \"careContext\";\n}\n\ninterface HistoryRowProps {\n index: number;\n point: HistoryPoint;\n vital: Vital;\n isSelected: boolean;\n isLast: boolean;\n onToggle: (i: number) => void;\n onViewRecord: (\n recordId: string,\n returnTo: \"smart\" | \"history\",\n returnVitalId?: string,\n ) => void;\n}\n\nconst HistoryRow = memo(function HistoryRow({\n index,\n point,\n vital,\n isSelected,\n isLast,\n onToggle,\n onViewRecord,\n}: HistoryRowProps) {\n const oor = isOutOfRange({ ...vital, status: point.status });\n const handleToggle = useCallback(() => onToggle(index), [onToggle, index]);\n const handleViewRecord = useCallback(\n () => onViewRecord(point.recordId, \"history\", vital.id),\n [onViewRecord, point.recordId, vital.id],\n );\n\n return (\n <div className={`mr-cc-table__row-wrap${isLast ? \" mr-cc-table__row-wrap--last\" : \"\"}`}>\n <div\n className={`mr-cc-table__row${isSelected ? \" mr-cc-table__row--selected\" : \"\"}`}\n role=\"row\"\n style={{ gridTemplateColumns: HISTORY_COLS, cursor: \"pointer\" }}\n onClick={handleToggle}\n >\n <div\n className=\"mr-cc-table__reading-cell\"\n role=\"cell\"\n style={{ flexDirection: \"row\", alignItems: \"center\", gap: \"8px\" }}\n >\n <span\n className={`mr-sv__checkbox mr-cc-table__row-check${isSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n handleToggle();\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n handleToggle();\n }\n }}\n >\n {isSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <div className=\"mr-cc-table__reading-value-row\">\n {point.value ? (\n <>\n <span\n className={`mr-cc-table__rvalue${oor ? \" mr-cc-table__rvalue--oor\" : \"\"}`}\n >\n {point.value}\n </span>\n {point.unit && (\n <span className=\"mr-cc-table__runit\">{point.unit}</span>\n )}\n </>\n ) : (\n <span className=\"mr-cc-table__empty-dash\">—</span>\n )}\n </div>\n </div>\n\n <div className=\"mr-cc-table__reading-cell\" role=\"cell\">\n {point.date ? (\n <span className=\"mr-cc-table__rvalue\">{point.date}</span>\n ) : (\n <span className=\"mr-cc-table__empty-dash\">—</span>\n )}\n </div>\n\n <div\n className=\"mr-cc-table__actions\"\n role=\"cell\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n className=\"mr-sv__view-record-btn\"\n onClick={handleViewRecord}\n >\n View record\n </button>\n </div>\n </div>\n </div>\n );\n});\n\nexport function VitalHistoryPanel({\n recordId,\n vitalId,\n caseId,\n}: VitalHistoryPanelProps) {\n const { back, openOriginal: _openOriginal, onCopyToNote, onCopyVitalsToNote, onToast } =\n useSmartRecordsActions();\n\n const openOriginal = useCallback(\n (recordId: string, returnTo: \"smart\" | \"history\" | \"careContext\", returnVitalId?: string) => {\n invalidateRecordPanelTable(recordId);\n _openOriginal(recordId, caseId ? \"careContext\" : returnTo, returnVitalId, caseId);\n },\n [_openOriginal, caseId],\n );\n const preview = useRecordPreview(recordId);\n const vital = preview.vitals.find((v) => v.id === vitalId);\n const copyBtnRef = useRef<HTMLButtonElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n const { data: trendData, status: trendStatus } = useParameterTrend(\n vital?.ekaId,\n );\n\n const points = useMemo((): HistoryPoint[] => {\n const trend = trendData as ParameterTrendResponse | null;\n if (!trend?.vitals_info?.length) return [];\n return trend.vitals_info\n .sort((a, b) => (b.date ?? 0) - (a.date ?? 0))\n .map((info) => ({\n date: (info.display_time || \"\").replace(/['‘’]/g, \" \"),\n caseLabel: \"\",\n value:\n info.val !== undefined\n ? String(info.val)\n : ((info as any).val_string ?? \"\"),\n unit: trend.unit,\n status: normalizeStatus(info.display_result ?? \"\"),\n recordId: info.document_id,\n recordName: trend.name,\n }));\n }, [trendData]);\n\n type VhpTab = \"all\" | \"oor\" | \"none\";\n const [activeTab, setActiveTab] = useState<VhpTab>(\"all\");\n\n const oorCount = useMemo(\n () => points.filter((p) => p.status === \"high\" || p.status === \"low\").length,\n [points],\n );\n const noneCount = useMemo(\n () => points.filter((p) => p.status === \"unknown\").length,\n [points],\n );\n\n useEffect(() => {\n if (activeTab === \"oor\" && oorCount === 0) setActiveTab(\"all\");\n if (activeTab === \"none\" && noneCount === 0) setActiveTab(\"all\");\n }, [activeTab, oorCount, noneCount]);\n\n useEffect(() => {\n if (trendStatus === \"error\") {\n back();\n onToast?.(\"Failed to load vital history\", \"error\");\n }\n }, [trendStatus, back, onToast]);\n\n const filteredPoints = useMemo(() => {\n if (activeTab === \"oor\") return points.filter((p) => p.status === \"high\" || p.status === \"low\");\n if (activeTab === \"none\") return points.filter((p) => p.status === \"unknown\");\n return points;\n }, [points, activeTab]);\n\n const rowVirtualizer = useVirtualizer({\n count: filteredPoints.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => 50,\n overscan: 5,\n });\n\n const {\n selected,\n allSelected,\n someSelected,\n togglePoint,\n toggleAll,\n buildHistoryText,\n } = useVitalHistoryPanel(\n vital ?? {\n id: vitalId,\n name: \"\",\n value: \"\",\n unit: \"\",\n refRange: \"\",\n status: \"normal\" as VitalStatus,\n history: [] as VitalHistoryPoint[],\n },\n filteredPoints,\n );\n\n const handleCopyToNote = useCallback(() => {\n const chosen = points.filter((_, i) => selected.has(i));\n if (!chosen.length) return;\n const text = buildHistoryText(chosen);\n if (onCopyVitalsToNote) {\n void onCopyVitalsToNote(text);\n } else if (onCopyToNote) {\n const rect = copyBtnRef.current?.getBoundingClientRect();\n void onCopyToNote(\n text,\n rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : undefined,\n vital ? toHistoryNoteRows(vital, chosen) : undefined,\n );\n }\n }, [points, selected, buildHistoryText, onCopyVitalsToNote, onCopyToNote, vital]);\n\n const hasCopyToNote = !!(onCopyToNote || onCopyVitalsToNote);\n\n if (preview.status === \"loading\") {\n return (\n <div\n className=\"mr-sv__panel\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <LoaderCircle\n size={32}\n className=\"mr-sv__loading-spinner\"\n aria-hidden\n />\n </div>\n );\n }\n\n if (!vital) {\n return (\n <div className=\"mr-sv__panel\">\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n Vital not found.\n </Typography>\n </div>\n );\n }\n\n return (\n <div className=\"mr-sv__panel\">\n <div className=\"mr-sv__back-row\">\n <button type=\"button\" className=\"mr-sv__back-btn\" onClick={back}>\n <ChevronLeft size={16} aria-hidden />\n Back\n </button>\n </div>\n {/* Header */}\n <div className=\"mr-sv__panel-header\">\n <div className=\"mr-sv__panel-left\">\n <div className=\"mr-sv__panel-info\">\n <div className=\"mr-sv__panel-name-row\">\n <Typography\n variant=\"label\"\n as=\"span\"\n className=\"mr-sv__panel-name\"\n >\n {vital.name}\n </Typography>\n {vital.refRange && (\n <span className=\"mr-sv__panel-ref-badge\">\n Ref: {vital.refRange}\n </span>\n )}\n </div>\n <div className=\"mr-sv__panel-meta\">\n {trendStatus === \"loaded\" && (\n <span>\n {points.length} reading{points.length !== 1 ? \"s\" : \"\"}\n {oorCount > 0 && (\n <>\n {\" \"}\n ·{\" \"}\n <span className=\"mr-sv__oor\">\n {oorCount} out of range\n </span>\n </>\n )}\n </span>\n )}\n </div>\n </div>\n </div>\n <span className=\"mr-cc-panel__viewing-label\">Viewing vital history</span>\n </div>\n\n {/* Filter tabs — only shown when at least one sub-category has data */}\n {trendStatus === \"loaded\" && points.length > 0 && (oorCount > 0 || noneCount > 0) && (\n <div className=\"mr-orig__smart-tabs-wrap\" style={{ padding: \"8px 16px 0\" }}>\n <div className=\"mr-orig__smart-tabs\">\n {([\"all\", \"oor\", \"none\"] as VhpTab[]).map((tab) => {\n if (tab === \"oor\" && oorCount === 0) return null;\n if (tab === \"none\" && noneCount === 0) return null;\n const count = tab === \"all\" ? points.length : tab === \"oor\" ? oorCount : noneCount;\n const label = tab === \"all\" ? \"All\" : tab === \"oor\" ? \"Out of range\" : \"No interpretation\";\n return (\n <button\n key={tab}\n type=\"button\"\n className={`mr-orig__smart-tab${activeTab === tab ? \" mr-orig__smart-tab--active\" : \"\"}`}\n onClick={() => setActiveTab(tab)}\n >\n {label} ({count})\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Body */}\n <div className=\"mr-sv__panel-body\" ref={scrollRef} style={{ overflowY: \"auto\" }}>\n {trendStatus === \"loading\" && (\n <div className=\"mr-cc-table mr-cc-table--state\">\n <LoaderCircle size={20} className=\"mr-sv__loading-spinner\" aria-hidden />\n <Typography variant=\"muted\">Loading vital history…</Typography>\n </div>\n )}\n {trendStatus === \"loaded\" && points.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No historical data available for this vital.\n </Typography>\n )}\n {points.length > 0 && (\n <div className=\"mr-vhp-table\" role=\"table\">\n <div\n className=\"mr-cc-table__row mr-cc-table__row--head\"\n role=\"row\"\n style={{ gridTemplateColumns: HISTORY_COLS, margin: 0 }}\n >\n <span className=\"mr-cc-table__head-cell\" role=\"columnheader\">READING</span>\n <span className=\"mr-cc-table__head-cell\" role=\"columnheader\">DATE</span>\n <span className=\"mr-cc-table__head-cell\" aria-hidden />\n </div>\n {filteredPoints.length === 0 ? (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No readings match this filter.\n </Typography>\n ) : (\n <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: \"relative\" }}>\n {rowVirtualizer.getVirtualItems().map((virtualRow) => (\n <div\n key={virtualRow.key}\n data-index={virtualRow.index}\n ref={rowVirtualizer.measureElement}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <HistoryRow\n index={virtualRow.index}\n point={filteredPoints[virtualRow.index]}\n vital={vital}\n isSelected={selected.has(virtualRow.index)}\n isLast={virtualRow.index === filteredPoints.length - 1}\n onToggle={togglePoint}\n onViewRecord={openOriginal}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"mr-cc-table__footer\">\n <span\n className={`mr-sv__checkbox mr-cc-table__footer-check${allSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={allSelected}\n tabIndex={0}\n onClick={toggleAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleAll();\n }\n }}\n >\n {allSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <span className=\"mr-cc-table__footer-label\" onClick={toggleAll}>Select all</span>\n <span className=\"mr-cc-table__footer-count\">{selected.size} of {points.length} selected</span>\n <button\n ref={copyBtnRef}\n type=\"button\"\n className=\"mr-cc-table__copy-note-btn\"\n disabled={!someSelected || !hasCopyToNote}\n onClick={handleCopyToNote}\n >\n Copy to note\n </button>\n </div>\n </div>\n );\n}\n","import { useState, useMemo, useCallback } from \"react\";\nimport { isOutOfRange } from \"../../../helpers/smartReport\";\nimport type { Vital, HistoryPoint } from \"../../types\";\n\nexport function useVitalHistoryPanel(vital: Vital, points: HistoryPoint[]) {\n const [selected, setSelected] = useState<Set<number>>(new Set());\n\n const outOfRangeCount = useMemo(\n () => points.filter((p) => isOutOfRange({ ...vital, status: p.status })).length,\n [points, vital],\n );\n\n const allSelected = points.length > 0 && points.every((_, i) => selected.has(i));\n const someSelected = selected.size > 0;\n\n const togglePoint = useCallback((i: number) => {\n setSelected((prev) => {\n const n = new Set(prev);\n n.has(i) ? n.delete(i) : n.add(i);\n return n;\n });\n }, []);\n\n const toggleAll = useCallback(() => {\n setSelected(allSelected ? new Set() : new Set(points.map((_, i) => i)));\n }, [allSelected, points]);\n\n const clearSelection = useCallback(() => setSelected(new Set()), []);\n\n const buildHistoryText = useCallback(\n (pts: HistoryPoint[]) => {\n const lines = pts.map(\n (p) => `${vital.name}: ${p.value} ${p.unit} (${p.date}${p.caseLabel ? ` · ${p.caseLabel}` : \"\"})`,\n );\n return [`**${vital.name} — Historical data:**`, ...lines].join(\"\\n\");\n },\n [vital.name],\n );\n\n return {\n selected,\n outOfRangeCount,\n allSelected,\n someSelected,\n togglePoint,\n toggleAll,\n clearSelection,\n buildHistoryText,\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/views/containers/care-panel/VitalHistoryPanel.tsx","../src/views/hooks/care-panel/useVitalHistoryPanel.ts"],"sourcesContent":["\"use client\";\n\nimport { ChevronLeft, Check, LoaderCircle } from \"lucide-react\";\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { isOutOfRange } from \"../../../helpers/smartReport\";\nimport { useSmartRecordsActions } from \"../../context/SmartRecordsActionsContext\";\nimport { useVitalHistoryPanel } from \"../../hooks/care-panel/useVitalHistoryPanel\";\nimport { useParameterTrend } from \"../../hooks/care-panel/useParameterTrend\";\nimport { invalidateRecordPanelTable } from \"../../hooks/care-panel/useRecordPanelTable\";\nimport { useRecordPreview } from \"../../../connection/useRecordPreview\";\nimport type { HistoryPoint } from \"../../types\";\nimport type {\n VitalStatus,\n Vital,\n VitalHistoryPoint,\n} from \"../../../helpers/smartReport\";\nimport type { VitalNoteRow } from \"../../../helpers/vitalsPanel\";\nimport type { ParameterTrendResponse } from \"@eka-care/medical-records-ts-sdk\";\nimport { Typography } from \"widgets\";\n\nconst HISTORY_COLS = \"2fr 2fr 88px\";\n\n// One row per reading — date is folded into `value` since the shared note\n// table has no dedicated date column (each reading needs to stay distinguishable).\nfunction toHistoryNoteRows(vital: Vital, pts: HistoryPoint[]): VitalNoteRow[] {\n return pts.map((p) => {\n const dateSuffix = p.date ? ` (${p.date}${p.caseLabel ? ` · ${p.caseLabel}` : \"\"})` : \"\";\n return {\n name: vital.name,\n value: `${p.value}${p.unit ? ` ${p.unit}` : \"\"}${dateSuffix}`,\n unit: \"\",\n refRange: vital.refRange,\n };\n });\n}\n\nfunction normalizeStatus(displayResult: string): VitalStatus {\n const s = displayResult.toLowerCase();\n if (s.includes(\"high\") || s.includes(\"above\") || s === \"abnormal_high\")\n return \"high\";\n if (s.includes(\"low\") || s.includes(\"below\") || s === \"abnormal_low\")\n return \"low\";\n if (s.includes(\"normal\") || s.includes(\"in range\") || s === \"ok\")\n return \"normal\";\n return \"unknown\";\n}\n\ninterface VitalHistoryPanelProps {\n recordId: string;\n vitalId: string;\n caseId?: string;\n returnTo?: \"smart\" | \"careContext\";\n}\n\ninterface HistoryRowProps {\n index: number;\n point: HistoryPoint;\n vital: Vital;\n isSelected: boolean;\n isLast: boolean;\n onToggle: (i: number) => void;\n onViewRecord: (\n recordId: string,\n returnTo: \"smart\" | \"history\",\n returnVitalId?: string,\n ) => void;\n}\n\nconst HistoryRow = memo(function HistoryRow({\n index,\n point,\n vital,\n isSelected,\n isLast,\n onToggle,\n onViewRecord,\n}: HistoryRowProps) {\n const oor = isOutOfRange({ ...vital, status: point.status });\n const handleToggle = useCallback(() => onToggle(index), [onToggle, index]);\n const handleViewRecord = useCallback(\n () => onViewRecord(point.recordId, \"history\", vital.id),\n [onViewRecord, point.recordId, vital.id],\n );\n\n return (\n <div className={`mr-cc-table__row-wrap${isLast ? \" mr-cc-table__row-wrap--last\" : \"\"}`}>\n <div\n className={`mr-cc-table__row${isSelected ? \" mr-cc-table__row--selected\" : \"\"}`}\n role=\"row\"\n style={{ gridTemplateColumns: HISTORY_COLS, cursor: \"pointer\" }}\n onClick={handleToggle}\n >\n <div\n className=\"mr-cc-table__reading-cell\"\n role=\"cell\"\n style={{ flexDirection: \"row\", alignItems: \"center\", gap: \"8px\" }}\n >\n <span\n className={`mr-sv__checkbox mr-cc-table__row-check${isSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={isSelected}\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n handleToggle();\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n handleToggle();\n }\n }}\n >\n {isSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <div className=\"mr-cc-table__reading-value-row\">\n {point.value ? (\n <>\n <span\n className={`mr-cc-table__rvalue${oor ? \" mr-cc-table__rvalue--oor\" : \"\"}`}\n >\n {point.value}\n </span>\n {point.unit && (\n <span className=\"mr-cc-table__runit\">{point.unit}</span>\n )}\n </>\n ) : (\n <span className=\"mr-cc-table__empty-dash\">—</span>\n )}\n </div>\n </div>\n\n <div className=\"mr-cc-table__reading-cell\" role=\"cell\">\n {point.date ? (\n <span className=\"mr-cc-table__rvalue\">{point.date}</span>\n ) : (\n <span className=\"mr-cc-table__empty-dash\">—</span>\n )}\n </div>\n\n <div\n className=\"mr-cc-table__actions\"\n role=\"cell\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n className=\"mr-sv__view-record-btn\"\n onClick={handleViewRecord}\n >\n View record\n </button>\n </div>\n </div>\n </div>\n );\n});\n\nexport function VitalHistoryPanel({\n recordId,\n vitalId,\n caseId,\n}: VitalHistoryPanelProps) {\n const { back, openOriginal: _openOriginal, onCopyToNote, onCopyVitalsToNote, onToast } =\n useSmartRecordsActions();\n\n const openOriginal = useCallback(\n (recordId: string, returnTo: \"smart\" | \"history\" | \"careContext\", returnVitalId?: string) => {\n invalidateRecordPanelTable(recordId);\n _openOriginal(recordId, caseId ? \"careContext\" : returnTo, returnVitalId, caseId);\n },\n [_openOriginal, caseId],\n );\n const preview = useRecordPreview(recordId);\n const vital = preview.vitals.find((v) => v.id === vitalId);\n const copyBtnRef = useRef<HTMLButtonElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n const { data: trendData, status: trendStatus } = useParameterTrend(\n vital?.ekaId,\n );\n\n const points = useMemo((): HistoryPoint[] => {\n const trend = trendData as ParameterTrendResponse | null;\n if (!trend?.vitals_info?.length) return [];\n return trend.vitals_info\n .sort((a, b) => (b.date ?? 0) - (a.date ?? 0))\n .map((info) => ({\n date: (info.display_time || \"\").replace(/['‘’]/g, \" \"),\n caseLabel: \"\",\n value:\n info.val !== undefined\n ? String(info.val)\n : ((info as any).val_string ?? \"\"),\n unit: trend.unit,\n status: normalizeStatus(info.display_result ?? \"\"),\n recordId: info.document_id,\n recordName: trend.name,\n }));\n }, [trendData]);\n\n type VhpTab = \"all\" | \"oor\" | \"none\";\n const [activeTab, setActiveTab] = useState<VhpTab>(\"all\");\n\n const oorCount = useMemo(\n () => points.filter((p) => p.status === \"high\" || p.status === \"low\").length,\n [points],\n );\n const noneCount = useMemo(\n () => points.filter((p) => p.status === \"unknown\").length,\n [points],\n );\n\n useEffect(() => {\n if (activeTab === \"oor\" && oorCount === 0) setActiveTab(\"all\");\n if (activeTab === \"none\" && noneCount === 0) setActiveTab(\"all\");\n }, [activeTab, oorCount, noneCount]);\n\n useEffect(() => {\n if (trendStatus === \"error\") {\n back();\n onToast?.(\"Failed to load vital history\", \"error\");\n }\n }, [trendStatus, back, onToast]);\n\n const filteredPoints = useMemo(() => {\n if (activeTab === \"oor\") return points.filter((p) => p.status === \"high\" || p.status === \"low\");\n if (activeTab === \"none\") return points.filter((p) => p.status === \"unknown\");\n return points;\n }, [points, activeTab]);\n\n const rowVirtualizer = useVirtualizer({\n count: filteredPoints.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => 50,\n overscan: 5,\n });\n\n const {\n selected,\n allSelected,\n someSelected,\n togglePoint,\n toggleAll,\n buildHistoryText,\n } = useVitalHistoryPanel(\n vital ?? {\n id: vitalId,\n name: \"\",\n value: \"\",\n unit: \"\",\n refRange: \"\",\n status: \"normal\" as VitalStatus,\n history: [] as VitalHistoryPoint[],\n },\n filteredPoints,\n );\n\n const handleCopyToNote = useCallback(() => {\n const chosen = points.filter((_, i) => selected.has(i));\n if (!chosen.length) return;\n const text = buildHistoryText(chosen);\n if (onCopyVitalsToNote) {\n void onCopyVitalsToNote(text);\n } else if (onCopyToNote) {\n const rect = copyBtnRef.current?.getBoundingClientRect();\n void onCopyToNote(\n text,\n rect ? { x: rect.left + rect.width / 2, y: rect.bottom } : undefined,\n vital ? toHistoryNoteRows(vital, chosen) : undefined,\n );\n }\n }, [points, selected, buildHistoryText, onCopyVitalsToNote, onCopyToNote, vital]);\n\n const hasCopyToNote = !!(onCopyToNote || onCopyVitalsToNote);\n\n if (preview.status === \"loading\") {\n return (\n <div\n className=\"mr-sv__panel\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <LoaderCircle\n size={32}\n className=\"mr-sv__loading-spinner\"\n aria-hidden\n />\n </div>\n );\n }\n\n if (!vital) {\n return (\n <div className=\"mr-sv__panel\">\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n Vital not found.\n </Typography>\n </div>\n );\n }\n\n return (\n <div className=\"mr-sv__panel\">\n <div className=\"mr-sv__back-row\">\n <button type=\"button\" className=\"mr-sv__back-btn\" onClick={back}>\n <ChevronLeft size={16} aria-hidden />\n Back\n </button>\n </div>\n {/* Header */}\n <div className=\"mr-sv__panel-header\">\n <div className=\"mr-sv__panel-left\">\n <div className=\"mr-sv__panel-info\">\n <div className=\"mr-sv__panel-name-row\">\n <Typography\n variant=\"label\"\n as=\"span\"\n className=\"mr-sv__panel-name\"\n >\n {vital.name}\n </Typography>\n {vital.refRange && (\n <span className=\"mr-sv__panel-ref-badge\">\n Ref: {vital.refRange}\n </span>\n )}\n </div>\n <div className=\"mr-sv__panel-meta\">\n {trendStatus === \"loaded\" && (\n <span>\n {points.length} reading{points.length !== 1 ? \"s\" : \"\"}\n {oorCount > 0 && (\n <>\n {\" \"}\n ·{\" \"}\n <span className=\"mr-sv__oor\">\n {oorCount} out of range\n </span>\n </>\n )}\n </span>\n )}\n </div>\n </div>\n </div>\n <span className=\"mr-cc-panel__viewing-label\">Viewing vital history</span>\n </div>\n\n {/* Filter tabs — only shown when at least one sub-category has data */}\n {trendStatus === \"loaded\" && points.length > 0 && (oorCount > 0 || noneCount > 0) && (\n <div className=\"mr-orig__smart-tabs-wrap\" style={{ padding: \"8px 16px 0\" }}>\n <div className=\"mr-orig__smart-tabs\">\n {([\"all\", \"oor\", \"none\"] as VhpTab[]).map((tab) => {\n if (tab === \"oor\" && oorCount === 0) return null;\n if (tab === \"none\" && noneCount === 0) return null;\n const count = tab === \"all\" ? points.length : tab === \"oor\" ? oorCount : noneCount;\n const label = tab === \"all\" ? \"All\" : tab === \"oor\" ? \"Out of range\" : \"No interpretation\";\n return (\n <button\n key={tab}\n type=\"button\"\n className={`mr-orig__smart-tab${activeTab === tab ? \" mr-orig__smart-tab--active\" : \"\"}`}\n onClick={() => setActiveTab(tab)}\n >\n {label} ({count})\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Body */}\n <div className=\"mr-sv__panel-body\" ref={scrollRef} style={{ overflowY: \"auto\" }}>\n {trendStatus === \"loading\" && (\n <div className=\"mr-cc-table mr-cc-table--state\">\n <LoaderCircle size={20} className=\"mr-sv__loading-spinner\" aria-hidden />\n <Typography variant=\"muted\">Loading vital history…</Typography>\n </div>\n )}\n {trendStatus === \"loaded\" && points.length === 0 && (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No historical data available for this vital.\n </Typography>\n )}\n {points.length > 0 && (\n <div className=\"mr-vhp-table\" role=\"table\">\n <div\n className=\"mr-cc-table__row mr-cc-table__row--head\"\n role=\"row\"\n style={{ gridTemplateColumns: HISTORY_COLS, margin: 0 }}\n >\n <span className=\"mr-cc-table__head-cell\" role=\"columnheader\">READING</span>\n <span className=\"mr-cc-table__head-cell\" role=\"columnheader\">DATE</span>\n <span className=\"mr-cc-table__head-cell\" aria-hidden />\n </div>\n {filteredPoints.length === 0 ? (\n <Typography variant=\"muted\" className=\"mr-sv__panel-empty\">\n No readings match this filter.\n </Typography>\n ) : (\n <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: \"relative\" }}>\n {rowVirtualizer.getVirtualItems().map((virtualRow) => (\n <div\n key={virtualRow.key}\n data-index={virtualRow.index}\n ref={rowVirtualizer.measureElement}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <HistoryRow\n index={virtualRow.index}\n point={filteredPoints[virtualRow.index]}\n vital={vital}\n isSelected={selected.has(virtualRow.index)}\n isLast={virtualRow.index === filteredPoints.length - 1}\n onToggle={togglePoint}\n onViewRecord={openOriginal}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"mr-cc-table__footer\">\n <span\n className={`mr-sv__checkbox mr-cc-table__footer-check${allSelected ? \" mr-sv__checkbox--checked\" : \"\"}`}\n role=\"checkbox\"\n aria-checked={allSelected}\n tabIndex={0}\n onClick={toggleAll}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleAll();\n }\n }}\n >\n {allSelected && <Check size={10} strokeWidth={3} />}\n </span>\n <span className=\"mr-cc-table__footer-label\" onClick={toggleAll}>Select all</span>\n <span className=\"mr-cc-table__footer-count\">{selected.size} of {points.length} selected</span>\n <button\n ref={copyBtnRef}\n type=\"button\"\n className=\"mr-cc-table__copy-note-btn\"\n disabled={!someSelected || !hasCopyToNote}\n onClick={handleCopyToNote}\n >\n Copy to note\n </button>\n </div>\n </div>\n );\n}\n","import { useState, useMemo, useCallback } from \"react\";\nimport { isOutOfRange } from \"../../../helpers/smartReport\";\nimport type { Vital, HistoryPoint } from \"../../types\";\n\nexport function useVitalHistoryPanel(vital: Vital, points: HistoryPoint[]) {\n const [selected, setSelected] = useState<Set<number>>(new Set());\n\n const outOfRangeCount = useMemo(\n () => points.filter((p) => isOutOfRange({ ...vital, status: p.status })).length,\n [points, vital],\n );\n\n const allSelected = points.length > 0 && points.every((_, i) => selected.has(i));\n const someSelected = selected.size > 0;\n\n const togglePoint = useCallback((i: number) => {\n setSelected((prev) => {\n const n = new Set(prev);\n n.has(i) ? n.delete(i) : n.add(i);\n return n;\n });\n }, []);\n\n const toggleAll = useCallback(() => {\n setSelected(allSelected ? new Set() : new Set(points.map((_, i) => i)));\n }, [allSelected, points]);\n\n const clearSelection = useCallback(() => setSelected(new Set()), []);\n\n const buildHistoryText = useCallback(\n (pts: HistoryPoint[]) => {\n const lines = pts.map(\n (p) => `${vital.name}: ${p.value} ${p.unit} (${p.date}${p.caseLabel ? ` · ${p.caseLabel}` : \"\"})`,\n );\n return [`**${vital.name} — Historical data:**`, ...lines].join(\"\\n\");\n },\n [vital.name],\n );\n\n return {\n selected,\n outOfRangeCount,\n allSelected,\n someSelected,\n togglePoint,\n toggleAll,\n clearSelection,\n buildHistoryText,\n };\n}\n"],"mappings":";;;;;;;;;;;;AAEA,SAAS,aAAa,OAAO,oBAAoB;AACjD,SAAS,MAAM,eAAAA,cAAa,WAAW,WAAAC,UAAS,QAAQ,YAAAC,iBAAgB;AACxE,SAAS,sBAAsB;;;ACJ/B,SAAS,UAAU,SAAS,mBAAmB;AAIxC,SAAS,qBAAqB,OAAc,QAAwB;AACzE,QAAM,CAAC,UAAU,WAAW,IAAI,SAAsB,oBAAI,IAAI,CAAC;AAE/D,QAAM,kBAAkB;AAAA,IACtB,MAAM,OAAO,OAAO,CAAC,MAAM,aAAa,EAAE,GAAG,OAAO,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE;AAAA,IACzE,CAAC,QAAQ,KAAK;AAAA,EAChB;AAEA,QAAM,cAAc,OAAO,SAAS,KAAK,OAAO,MAAM,CAAC,GAAG,MAAM,SAAS,IAAI,CAAC,CAAC;AAC/E,QAAM,eAAe,SAAS,OAAO;AAErC,QAAM,cAAc,YAAY,CAAC,MAAc;AAC7C,gBAAY,CAAC,SAAS;AACpB,YAAM,IAAI,IAAI,IAAI,IAAI;AACtB,QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;AAChC,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,YAAY,YAAY,MAAM;AAClC,gBAAY,cAAc,oBAAI,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;AAAA,EACxE,GAAG,CAAC,aAAa,MAAM,CAAC;AAExB,QAAM,iBAAiB,YAAY,MAAM,YAAY,oBAAI,IAAI,CAAC,GAAG,CAAC,CAAC;AAEnE,QAAM,mBAAmB;AAAA,IACvB,CAAC,QAAwB;AACvB,YAAM,QAAQ,IAAI;AAAA,QAChB,CAAC,MAAM,GAAG,MAAM,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,IAAI,KAAK,EAAE,IAAI,GAAG,EAAE,YAAY,SAAM,EAAE,SAAS,KAAK,EAAE;AAAA,MAChG;AACA,aAAO,CAAC,KAAK,MAAM,IAAI,8BAAyB,GAAG,KAAK,EAAE,KAAK,IAAI;AAAA,IACrE;AAAA,IACA,CAAC,MAAM,IAAI;AAAA,EACb;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ADkEyB,SAIb,UAJa,KAIb,YAJa;AA9FzB,IAAM,eAAe;AAIrB,SAAS,kBAAkB,OAAc,KAAqC;AAC5E,SAAO,IAAI,IAAI,CAAC,MAAM;AACpB,UAAM,aAAa,EAAE,OAAO,KAAK,EAAE,IAAI,GAAG,EAAE,YAAY,SAAM,EAAE,SAAS,KAAK,EAAE,MAAM;AACtF,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,OAAO,GAAG,EAAE,KAAK,GAAG,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,EAAE,GAAG,UAAU;AAAA,MAC3D,MAAM;AAAA,MACN,UAAU,MAAM;AAAA,IAClB;AAAA,EACF,CAAC;AACH;AAEA,SAAS,gBAAgB,eAAoC;AAC3D,QAAM,IAAI,cAAc,YAAY;AACpC,MAAI,EAAE,SAAS,MAAM,KAAK,EAAE,SAAS,OAAO,KAAK,MAAM;AACrD,WAAO;AACT,MAAI,EAAE,SAAS,KAAK,KAAK,EAAE,SAAS,OAAO,KAAK,MAAM;AACpD,WAAO;AACT,MAAI,EAAE,SAAS,QAAQ,KAAK,EAAE,SAAS,UAAU,KAAK,MAAM;AAC1D,WAAO;AACT,SAAO;AACT;AAuBA,IAAM,aAAa,KAAK,SAASC,YAAW;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,MAAM,aAAa,EAAE,GAAG,OAAO,QAAQ,MAAM,OAAO,CAAC;AAC3D,QAAM,eAAeC,aAAY,MAAM,SAAS,KAAK,GAAG,CAAC,UAAU,KAAK,CAAC;AACzE,QAAM,mBAAmBA;AAAA,IACvB,MAAM,aAAa,MAAM,UAAU,WAAW,MAAM,EAAE;AAAA,IACtD,CAAC,cAAc,MAAM,UAAU,MAAM,EAAE;AAAA,EACzC;AAEA,SACE,oBAAC,SAAI,WAAW,wBAAwB,SAAS,iCAAiC,EAAE,IACpF;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,mBAAmB,aAAa,gCAAgC,EAAE;AAAA,MAC7E,MAAK;AAAA,MACL,OAAO,EAAE,qBAAqB,cAAc,QAAQ,UAAU;AAAA,MAC9D,SAAS;AAAA,MAET;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,MAAM;AAAA,YAEhE;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW,yCAAyC,aAAa,8BAA8B,EAAE;AAAA,kBACjG,MAAK;AAAA,kBACL,gBAAc;AAAA,kBACd,UAAU;AAAA,kBACV,SAAS,CAAC,MAAM;AACd,sBAAE,gBAAgB;AAClB,iCAAa;AAAA,kBACf;AAAA,kBACA,WAAW,CAAC,MAAM;AAChB,wBAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,SAAS;AACtC,wBAAE,eAAe;AACjB,wBAAE,gBAAgB;AAClB,mCAAa;AAAA,oBACf;AAAA,kBACF;AAAA,kBAEC,wBAAc,oBAAC,SAAM,MAAM,IAAI,aAAa,GAAG;AAAA;AAAA,cAClD;AAAA,cACA,oBAAC,SAAI,WAAU,kCACZ,gBAAM,QACL,iCACE;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAW,sBAAsB,MAAM,8BAA8B,EAAE;AAAA,oBAEtE,gBAAM;AAAA;AAAA,gBACT;AAAA,gBACC,MAAM,QACL,oBAAC,UAAK,WAAU,sBAAsB,gBAAM,MAAK;AAAA,iBAErD,IAEA,oBAAC,UAAK,WAAU,2BAA0B,oBAAC,GAE/C;AAAA;AAAA;AAAA,QACF;AAAA,QAEA,oBAAC,SAAI,WAAU,6BAA4B,MAAK,QAC7C,gBAAM,OACL,oBAAC,UAAK,WAAU,uBAAuB,gBAAM,MAAK,IAElD,oBAAC,UAAK,WAAU,2BAA0B,oBAAC,GAE/C;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,YAElC;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS;AAAA,gBACV;AAAA;AAAA,YAED;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF,GACA;AAEJ,CAAC;AAEM,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,EAAE,MAAM,cAAc,eAAe,cAAc,oBAAoB,QAAQ,IACnF,uBAAuB;AAEzB,QAAM,eAAeA;AAAA,IACnB,CAACC,WAAkB,UAA+C,kBAA2B;AAC3F,iCAA2BA,SAAQ;AACnC,oBAAcA,WAAU,SAAS,gBAAgB,UAAU,eAAe,MAAM;AAAA,IAClF;AAAA,IACA,CAAC,eAAe,MAAM;AAAA,EACxB;AACA,QAAM,UAAU,iBAAiB,QAAQ;AACzC,QAAM,QAAQ,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACzD,QAAM,aAAa,OAA0B,IAAI;AACjD,QAAM,YAAY,OAAuB,IAAI;AAE7C,QAAM,EAAE,MAAM,WAAW,QAAQ,YAAY,IAAI;AAAA,IAC/C,OAAO;AAAA,EACT;AAEA,QAAM,SAASC,SAAQ,MAAsB;AAC3C,UAAM,QAAQ;AACd,QAAI,CAAC,OAAO,aAAa,OAAQ,QAAO,CAAC;AACzC,WAAO,MAAM,YACV,KAAK,CAAC,GAAG,OAAO,EAAE,QAAQ,MAAM,EAAE,QAAQ,EAAE,EAC5C,IAAI,CAAC,UAAU;AAAA,MACZ,OAAO,KAAK,gBAAgB,IAAI,QAAQ,UAAU,GAAG;AAAA,MACrD,WAAW;AAAA,MACX,OACE,KAAK,QAAQ,SACT,OAAO,KAAK,GAAG,IACb,KAAa,cAAc;AAAA,MACnC,MAAM,MAAM;AAAA,MACZ,QAAQ,gBAAgB,KAAK,kBAAkB,EAAE;AAAA,MACjD,UAAU,KAAK;AAAA,MACf,YAAY,MAAM;AAAA,IACtB,EAAE;AAAA,EACN,GAAG,CAAC,SAAS,CAAC;AAGd,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAiB,KAAK;AAExD,QAAM,WAAWD;AAAA,IACf,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE,WAAW,KAAK,EAAE;AAAA,IACtE,CAAC,MAAM;AAAA,EACT;AACA,QAAM,YAAYA;AAAA,IAChB,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE;AAAA,IACnD,CAAC,MAAM;AAAA,EACT;AAEA,YAAU,MAAM;AACd,QAAI,cAAc,SAAS,aAAa,EAAG,cAAa,KAAK;AAC7D,QAAI,cAAc,UAAU,cAAc,EAAG,cAAa,KAAK;AAAA,EACjE,GAAG,CAAC,WAAW,UAAU,SAAS,CAAC;AAEnC,YAAU,MAAM;AACd,QAAI,gBAAgB,SAAS;AAC3B,WAAK;AACL,gBAAU,gCAAgC,OAAO;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,aAAa,MAAM,OAAO,CAAC;AAE/B,QAAM,iBAAiBA,SAAQ,MAAM;AACnC,QAAI,cAAc,MAAO,QAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE,WAAW,KAAK;AAC9F,QAAI,cAAc,OAAQ,QAAO,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAC5E,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,QAAM,iBAAiB,eAAe;AAAA,IACpC,OAAO,eAAe;AAAA,IACtB,kBAAkB,MAAM,UAAU;AAAA,IAClC,cAAc,MAAM;AAAA,IACpB,UAAU;AAAA,EACZ,CAAC;AAED,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAAA,IACF,SAAS;AAAA,MACP,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,CAAC;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AAEA,QAAM,mBAAmBF,aAAY,MAAM;AACzC,UAAM,SAAS,OAAO,OAAO,CAAC,GAAG,MAAM,SAAS,IAAI,CAAC,CAAC;AACtD,QAAI,CAAC,OAAO,OAAQ;AACpB,UAAM,OAAO,iBAAiB,MAAM;AACpC,QAAI,oBAAoB;AACtB,WAAK,mBAAmB,IAAI;AAAA,IAC9B,WAAW,cAAc;AACvB,YAAM,OAAO,WAAW,SAAS,sBAAsB;AACvD,WAAK;AAAA,QACH;AAAA,QACA,OAAO,EAAE,GAAG,KAAK,OAAO,KAAK,QAAQ,GAAG,GAAG,KAAK,OAAO,IAAI;AAAA,QAC3D,QAAQ,kBAAkB,OAAO,MAAM,IAAI;AAAA,MAC7C;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,UAAU,kBAAkB,oBAAoB,cAAc,KAAK,CAAC;AAEhF,QAAM,gBAAgB,CAAC,EAAE,gBAAgB;AAEzC,MAAI,QAAQ,WAAW,WAAW;AAChC,WACE;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,QAClB;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,WAAU;AAAA,YACV,eAAW;AAAA;AAAA,QACb;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,MAAI,CAAC,OAAO;AACV,WACE,oBAAC,SAAI,WAAU,gBACb,8BAAC,cAAW,SAAQ,SAAQ,WAAU,sBAAqB,8BAE3D,GACF;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAU,gBACb;AAAA,wBAAC,SAAI,WAAU,mBACb,+BAAC,YAAO,MAAK,UAAS,WAAU,mBAAkB,SAAS,MACzD;AAAA,0BAAC,eAAY,MAAM,IAAI,eAAW,MAAC;AAAA,MAAE;AAAA,OAEvC,GACF;AAAA,IAEA,qBAAC,SAAI,WAAU,uBACb;AAAA,0BAAC,SAAI,WAAU,qBACb,+BAAC,SAAI,WAAU,qBACb;AAAA,6BAAC,SAAI,WAAU,yBACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,IAAG;AAAA,cACH,WAAU;AAAA,cAET,gBAAM;AAAA;AAAA,UACT;AAAA,UACC,MAAM,YACL,qBAAC,UAAK,WAAU,0BAAyB;AAAA;AAAA,YACjC,MAAM;AAAA,aACd;AAAA,WAEJ;AAAA,QACA,oBAAC,SAAI,WAAU,qBACZ,0BAAgB,YACf,qBAAC,UACE;AAAA,iBAAO;AAAA,UAAO;AAAA,UAAS,OAAO,WAAW,IAAI,MAAM;AAAA,UACnD,WAAW,KACV,iCACG;AAAA;AAAA,YAAI;AAAA,YACH;AAAA,YACF,qBAAC,UAAK,WAAU,cACb;AAAA;AAAA,cAAS;AAAA,eACZ;AAAA,aACF;AAAA,WAEJ,GAEJ;AAAA,SACF,GACF;AAAA,MACA,oBAAC,UAAK,WAAU,8BAA6B,mCAAqB;AAAA,OACpE;AAAA,IAGC,gBAAgB,YAAY,OAAO,SAAS,MAAM,WAAW,KAAK,YAAY,MAC7E,oBAAC,SAAI,WAAU,4BAA2B,OAAO,EAAE,SAAS,aAAa,GACvE,8BAAC,SAAI,WAAU,uBACX,WAAC,OAAO,OAAO,MAAM,EAAe,IAAI,CAAC,QAAQ;AACjD,UAAI,QAAQ,SAAS,aAAa,EAAG,QAAO;AAC5C,UAAI,QAAQ,UAAU,cAAc,EAAG,QAAO;AAC9C,YAAM,QAAQ,QAAQ,QAAQ,OAAO,SAAS,QAAQ,QAAQ,WAAW;AACzE,YAAM,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,iBAAiB;AACvE,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,WAAW,qBAAqB,cAAc,MAAM,gCAAgC,EAAE;AAAA,UACtF,SAAS,MAAM,aAAa,GAAG;AAAA,UAE9B;AAAA;AAAA,YAAM;AAAA,YAAG;AAAA,YAAM;AAAA;AAAA;AAAA,QALX;AAAA,MAMP;AAAA,IAEJ,CAAC,GACH,GACF;AAAA,IAIF,qBAAC,SAAI,WAAU,qBAAoB,KAAK,WAAW,OAAO,EAAE,WAAW,OAAO,GAC3E;AAAA,sBAAgB,aACf,qBAAC,SAAI,WAAU,kCACb;AAAA,4BAAC,gBAAa,MAAM,IAAI,WAAU,0BAAyB,eAAW,MAAC;AAAA,QACvE,oBAAC,cAAW,SAAQ,SAAQ,yCAAsB;AAAA,SACpD;AAAA,MAED,gBAAgB,YAAY,OAAO,WAAW,KAC7C,oBAAC,cAAW,SAAQ,SAAQ,WAAU,sBAAqB,0DAE3D;AAAA,MAED,OAAO,SAAS,KACf,qBAAC,SAAI,WAAU,gBAAe,MAAK,SACjC;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,OAAO,EAAE,qBAAqB,cAAc,QAAQ,EAAE;AAAA,YAEtD;AAAA,kCAAC,UAAK,WAAU,0BAAyB,MAAK,gBAAe,qBAAO;AAAA,cACpE,oBAAC,UAAK,WAAU,0BAAyB,MAAK,gBAAe,kBAAI;AAAA,cACjE,oBAAC,UAAK,WAAU,0BAAyB,eAAW,MAAC;AAAA;AAAA;AAAA,QACvD;AAAA,QACC,eAAe,WAAW,IACzB,oBAAC,cAAW,SAAQ,SAAQ,WAAU,sBAAqB,4CAE3D,IAEA,oBAAC,SAAI,OAAO,EAAE,QAAQ,GAAG,eAAe,aAAa,CAAC,MAAM,UAAU,WAAW,GAC9E,yBAAe,gBAAgB,EAAE,IAAI,CAAC,eACrC;AAAA,UAAC;AAAA;AAAA,YAEC,cAAY,WAAW;AAAA,YACvB,KAAK,eAAe;AAAA,YACpB,OAAO;AAAA,cACL,UAAU;AAAA,cACV,KAAK;AAAA,cACL,MAAM;AAAA,cACN,OAAO;AAAA,cACP,WAAW,cAAc,WAAW,KAAK;AAAA,YAC3C;AAAA,YAEA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,WAAW;AAAA,gBAClB,OAAO,eAAe,WAAW,KAAK;AAAA,gBACtC;AAAA,gBACA,YAAY,SAAS,IAAI,WAAW,KAAK;AAAA,gBACzC,QAAQ,WAAW,UAAU,eAAe,SAAS;AAAA,gBACrD,UAAU;AAAA,gBACV,cAAc;AAAA;AAAA,YAChB;AAAA;AAAA,UAnBK,WAAW;AAAA,QAoBlB,CACD,GACH;AAAA,SAEJ;AAAA,OAEJ;AAAA,IAEA,qBAAC,SAAI,WAAU,uBACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,4CAA4C,cAAc,8BAA8B,EAAE;AAAA,UACrG,MAAK;AAAA,UACL,gBAAc;AAAA,UACd,UAAU;AAAA,UACV,SAAS;AAAA,UACT,WAAW,CAAC,MAAM;AAChB,gBAAI,EAAE,QAAQ,OAAO,EAAE,QAAQ,SAAS;AACtC,gBAAE,eAAe;AACjB,wBAAU;AAAA,YACZ;AAAA,UACF;AAAA,UAEC,yBAAe,oBAAC,SAAM,MAAM,IAAI,aAAa,GAAG;AAAA;AAAA,MACnD;AAAA,MACA,oBAAC,UAAK,WAAU,6BAA4B,SAAS,WAAW,wBAAU;AAAA,MAC1E,qBAAC,UAAK,WAAU,6BAA6B;AAAA,iBAAS;AAAA,QAAK;AAAA,QAAK,OAAO;AAAA,QAAO;AAAA,SAAS;AAAA,MACvF;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,WAAU;AAAA,UACV,UAAU,CAAC,gBAAgB,CAAC;AAAA,UAC5B,SAAS;AAAA,UACV;AAAA;AAAA,MAED;AAAA,OACF;AAAA,KACF;AAEJ;","names":["useCallback","useMemo","useState","HistoryRow","useCallback","recordId","useMemo","useState"]}
|
|
File without changes
|