@imranq2/fhirpatientsummary 1.0.25 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +111 -82
  2. package/dist/index.js +111 -82
  3. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -142,7 +142,7 @@ var IPSSectionResourceFilters = {
142
142
  // Only include pregnancy history Observations
143
143
  ["HistoryOfPregnancySection" /* PREGNANCY_HISTORY */]: (resource) => resource.resourceType === "Observation" && (resource.code?.coding?.some((c) => Object.keys(PREGNANCY_LOINC_CODES.PREGNANCY_STATUS).includes(c.code)) || resource.valueCodeableConcept?.coding?.some((c) => Object.keys(PREGNANCY_LOINC_CODES.PREGNANCY_OUTCOME).includes(c.code))),
144
144
  // Only include Conditions or completed ClinicalImpressions
145
- ["FunctionalStatusSection" /* FUNCTIONAL_STATUS */]: (resource) => resource.resourceType === "Condition" || resource.resourceType === "ClinicalImpression" && resource.status === "completed",
145
+ ["FunctionalStatusSection" /* FUNCTIONAL_STATUS */]: (resource) => resource.resourceType === "Condition" && resource.clinicalStatus?.coding?.some((c) => !["inactive", "resolved"].includes(c.code)) || resource.resourceType === "ClinicalImpression" && resource.status === "completed",
146
146
  // Only include resolved medical history Conditions
147
147
  ["HistoryOfPastIllnessSection" /* MEDICAL_HISTORY */]: (resource) => resource.resourceType === "Condition" && resource.clinicalStatus?.coding?.some((c) => ["inactive", "resolved"].includes(c.code)),
148
148
  // Only include active care plans
@@ -1887,8 +1887,8 @@ var ProblemListTemplate = class _ProblemListTemplate {
1887
1887
  let html = ``;
1888
1888
  const activeConditions = resources.map((entry) => entry) || [];
1889
1889
  activeConditions.sort((a, b) => {
1890
- const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
1891
- const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
1890
+ const dateA = a.recordedDate ? new Date(a.recordedDate).getTime() : 0;
1891
+ const dateB = b.recordedDate ? new Date(b.recordedDate).getTime() : 0;
1892
1892
  return dateB - dateA;
1893
1893
  });
1894
1894
  html += `
@@ -1901,12 +1901,17 @@ var ProblemListTemplate = class _ProblemListTemplate {
1901
1901
  </tr>
1902
1902
  </thead>
1903
1903
  <tbody>`;
1904
+ const addedConditionCodes = /* @__PURE__ */ new Set();
1904
1905
  for (const cond of activeConditions) {
1905
- html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1906
- <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
1907
- <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1908
- <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1909
- </tr>`;
1906
+ const conditionCode = templateUtilities.codeableConcept(cond.code);
1907
+ if (!addedConditionCodes.has(conditionCode)) {
1908
+ addedConditionCodes.add(conditionCode);
1909
+ html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1910
+ <td class="Name">${conditionCode}</td>
1911
+ <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1912
+ <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1913
+ </tr>`;
1914
+ }
1910
1915
  }
1911
1916
  html += `</tbody>
1912
1917
  </table>`;
@@ -2390,8 +2395,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2390
2395
  </tr>
2391
2396
  </thead>
2392
2397
  <tbody>`;
2393
- let observationExists = false;
2394
- let diagnosticReportExists = false;
2398
+ const observationAdded = /* @__PURE__ */ new Set();
2399
+ const diagnosticReportAdded = /* @__PURE__ */ new Set();
2395
2400
  for (const resourceItem of resources) {
2396
2401
  for (const rowData of resourceItem.section ?? []) {
2397
2402
  const data = {};
@@ -2431,7 +2436,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2431
2436
  }
2432
2437
  }
2433
2438
  if (resourceItem.title === "Observation|Labs Summary Grouped by Lab Code") {
2434
- observationExists = true;
2435
2439
  let date = data["effectiveDateTime"] ? templateUtilities.renderTime(data["effectiveDateTime"], timezone) : "";
2436
2440
  if (!date && data["effectivePeriodStart"]) {
2437
2441
  date = templateUtilities.renderTime(data["effectivePeriodStart"], timezone);
@@ -2440,48 +2444,59 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2440
2444
  }
2441
2445
  }
2442
2446
  if (components.length > 0) {
2443
- const groupName = data["code"] ?? "";
2447
+ const groupName = data["code"] ? `${data["code"]} - ` : "";
2444
2448
  for (const component of components) {
2445
- this.formatSummaryObservationData(component);
2446
- observationhtml += `
2447
- <tr>
2448
- <td>${groupName ? groupName + " - " : ""}${component["code"] ?? "-"}</td>
2449
- <td>${component["formattedValue"] ?? "-"}</td>
2450
- <td>${component["referenceRange"]?.trim() ?? "-"}</td>
2451
- <td>${date ?? "-"}</td>
2452
- </tr>`;
2449
+ const componentCode = `${groupName}${component["code"] ?? ""}`;
2450
+ if (componentCode && !observationAdded.has(componentCode)) {
2451
+ observationAdded.add(componentCode);
2452
+ this.formatSummaryObservationData(component);
2453
+ observationhtml += `
2454
+ <tr>
2455
+ <td>${componentCode}</td>
2456
+ <td>${component["formattedValue"] ?? "-"}</td>
2457
+ <td>${component["referenceRange"]?.trim() ?? "-"}</td>
2458
+ <td>${date ?? "-"}</td>
2459
+ </tr>`;
2460
+ }
2453
2461
  }
2454
2462
  } else {
2455
- this.formatSummaryObservationData(data);
2456
- observationhtml += `
2457
- <tr>
2458
- <td>${data["code"] ?? "-"}</td>
2459
- <td>${data["formattedValue"] ?? "-"}</td>
2460
- <td>${data["referenceRange"]?.trim() ?? "-"}</td>
2461
- <td>${date ?? "-"}</td>
2462
- </tr>`;
2463
+ const code = data["code"] ?? "";
2464
+ if (code && !observationAdded.has(code)) {
2465
+ observationAdded.add(code);
2466
+ this.formatSummaryObservationData(data);
2467
+ observationhtml += `
2468
+ <tr>
2469
+ <td>${data["code"] ?? "-"}</td>
2470
+ <td>${data["formattedValue"] ?? "-"}</td>
2471
+ <td>${data["referenceRange"]?.trim() ?? "-"}</td>
2472
+ <td>${date ?? "-"}</td>
2473
+ </tr>`;
2474
+ }
2463
2475
  }
2464
2476
  } else if (resourceItem.title === "DiagnosticReportLab Summary Grouped by DiagnosticReport|Lab Code") {
2465
2477
  if (data["status"] === "final") {
2466
- diagnosticReportExists = true;
2467
- diagnosticReporthtml += `
2468
- <tr>
2469
- <td>${data["report"] ?? "-"}</td>
2470
- <td>${data["performer"] ?? "-"}</td>
2471
- <td>${templateUtilities.renderTime(data["issued"], timezone) ?? "-"}</td>
2472
- </tr>`;
2478
+ const reportName = data["report"] ?? "";
2479
+ if (reportName && !diagnosticReportAdded.has(reportName)) {
2480
+ diagnosticReportAdded.add(reportName);
2481
+ diagnosticReporthtml += `
2482
+ <tr>
2483
+ <td>${data["report"] ?? "-"}</td>
2484
+ <td>${data["performer"] ?? "-"}</td>
2485
+ <td>${templateUtilities.renderTime(data["issued"], timezone) ?? "-"}</td>
2486
+ </tr>`;
2487
+ }
2473
2488
  }
2474
2489
  }
2475
2490
  }
2476
2491
  }
2477
- if (observationExists) {
2492
+ if (observationAdded.size > 0) {
2478
2493
  html += observationhtml;
2479
2494
  html += `
2480
2495
  </tbody>
2481
2496
  </table>
2482
2497
  </div>`;
2483
2498
  }
2484
- if (diagnosticReportExists) {
2499
+ if (diagnosticReportAdded.size > 0) {
2485
2500
  html += diagnosticReporthtml;
2486
2501
  html += `
2487
2502
  </tbody>
@@ -2490,7 +2505,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2490
2505
  }
2491
2506
  html += `
2492
2507
  </div>`;
2493
- return observationExists || diagnosticReportExists ? html : void 0;
2508
+ return observationAdded.size > 0 || diagnosticReportAdded.size > 0 ? html : void 0;
2494
2509
  }
2495
2510
  /**
2496
2511
  * Internal static implementation that actually generates the narrative
@@ -2504,8 +2519,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2504
2519
  const observations = this.getObservations(resources);
2505
2520
  if (observations.length > 0) {
2506
2521
  observations.sort((a, b) => {
2507
- const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
2508
- const dateB = b.effectiveDateTime || b.effectivePeriod?.start;
2522
+ const dateA = a.effectiveDateTime || a.effectivePeriod?.start || a.effectivePeriod?.end;
2523
+ const dateB = b.effectiveDateTime || b.effectivePeriod?.start || b.effectivePeriod?.end;
2509
2524
  return dateA && dateB ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
2510
2525
  });
2511
2526
  html += this.renderObservations(templateUtilities, observations, timezone);
@@ -2560,17 +2575,22 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2560
2575
  </tr>
2561
2576
  </thead>
2562
2577
  <tbody>`;
2578
+ const observationAdded = /* @__PURE__ */ new Set();
2563
2579
  for (const obs of observations) {
2564
- html += `
2565
- <tr id="${templateUtilities.narrativeLinkId(obs)}">
2566
- <td>${templateUtilities.codeableConcept(obs.code)}</td>
2567
- <td>${templateUtilities.extractObservationValue(obs)}</td>
2568
- <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
2569
- <td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
2570
- <td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
2571
- <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
2572
- <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
2573
- </tr>`;
2580
+ const obsCode = templateUtilities.codeableConcept(obs.code);
2581
+ if (!observationAdded.has(obsCode)) {
2582
+ observationAdded.add(obsCode);
2583
+ html += `
2584
+ <tr id="${templateUtilities.narrativeLinkId(obs)}">
2585
+ <td>${obsCode}</td>
2586
+ <td>${templateUtilities.extractObservationValue(obs)}</td>
2587
+ <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
2588
+ <td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
2589
+ <td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
2590
+ <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
2591
+ <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
2592
+ </tr>`;
2593
+ }
2574
2594
  }
2575
2595
  html += `
2576
2596
  </tbody>
@@ -2597,18 +2617,23 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2597
2617
  </tr>
2598
2618
  </thead>
2599
2619
  <tbody>`;
2620
+ const diagnosticReportAdded = /* @__PURE__ */ new Set();
2600
2621
  for (const report of reports) {
2601
- let resultCount = "";
2602
- if (report.result && Array.isArray(report.result)) {
2603
- resultCount = `${report.result.length} result${report.result.length !== 1 ? "s" : ""}`;
2622
+ const reportName = templateUtilities.codeableConcept(report.code);
2623
+ if (!diagnosticReportAdded.has(reportName)) {
2624
+ diagnosticReportAdded.add(reportName);
2625
+ let resultCount = "";
2626
+ if (report.result && Array.isArray(report.result)) {
2627
+ resultCount = `${report.result.length} result${report.result.length !== 1 ? "s" : ""}`;
2628
+ }
2629
+ html += `
2630
+ <tr id="${templateUtilities.narrativeLinkId(report)}">
2631
+ <td>${reportName}</td>
2632
+ <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
2633
+ <td>${resultCount}</td>
2634
+ <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
2635
+ </tr>`;
2604
2636
  }
2605
- html += `
2606
- <tr id="${templateUtilities.narrativeLinkId(report)}">
2607
- <td>${templateUtilities.codeableConcept(report.code)}</td>
2608
- <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
2609
- <td>${resultCount}</td>
2610
- <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
2611
- </tr>`;
2612
2637
  }
2613
2638
  html += `
2614
2639
  </tbody>
@@ -2788,8 +2813,8 @@ var PastHistoryOfIllnessTemplate = class {
2788
2813
  let html = ``;
2789
2814
  const resolvedConditions = resources.map((entry) => entry) || [];
2790
2815
  resolvedConditions.sort((a, b) => {
2791
- const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
2792
- const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
2816
+ const dateA = a.recordedDate ? new Date(a.recordedDate).getTime() : 0;
2817
+ const dateB = b.recordedDate ? new Date(b.recordedDate).getTime() : 0;
2793
2818
  return dateB - dateA;
2794
2819
  });
2795
2820
  html += `
@@ -2803,13 +2828,18 @@ var PastHistoryOfIllnessTemplate = class {
2803
2828
  </tr>
2804
2829
  </thead>
2805
2830
  <tbody>`;
2831
+ const addedConditionCodes = /* @__PURE__ */ new Set();
2806
2832
  for (const cond of resolvedConditions) {
2807
- html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2808
- <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
2809
- <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2810
- <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2811
- <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
2812
- </tr>`;
2833
+ const conditionCode = templateUtilities.codeableConcept(cond.code);
2834
+ if (!addedConditionCodes.has(conditionCode)) {
2835
+ addedConditionCodes.add(conditionCode);
2836
+ html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2837
+ <td class="Name">${conditionCode}</td>
2838
+ <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2839
+ <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2840
+ <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
2841
+ </tr>`;
2842
+ }
2813
2843
  }
2814
2844
  html += `</tbody>
2815
2845
  </table>`;
@@ -2934,20 +2964,14 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
2934
2964
  const clinicalImpressions = [];
2935
2965
  for (const resourceItem of resources) {
2936
2966
  if (resourceItem.resourceType === "Condition") {
2937
- const cond = resourceItem;
2938
- const isResolved = cond.clinicalStatus?.coding?.some(
2939
- (c) => c.code === "resolved" || c.code === "inactive" || c.display?.toLowerCase().includes("resolved")
2940
- );
2941
- if (!isResolved) {
2942
- activeConditions.push(cond);
2943
- }
2967
+ activeConditions.push(resourceItem);
2944
2968
  } else if (resourceItem.resourceType === "ClinicalImpression") {
2945
2969
  clinicalImpressions.push(resourceItem);
2946
2970
  }
2947
2971
  }
2948
2972
  activeConditions.sort((a, b) => {
2949
- const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
2950
- const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
2973
+ const dateA = a.recordedDate ? new Date(a.recordedDate).getTime() : 0;
2974
+ const dateB = b.recordedDate ? new Date(b.recordedDate).getTime() : 0;
2951
2975
  return dateB - dateA;
2952
2976
  });
2953
2977
  clinicalImpressions.sort((a, b) => {
@@ -2966,12 +2990,17 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
2966
2990
  </tr>
2967
2991
  </thead>
2968
2992
  <tbody>`;
2993
+ const addedConditionCodes = /* @__PURE__ */ new Set();
2969
2994
  for (const cond of activeConditions) {
2970
- html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2971
- <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
2972
- <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2973
- <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2974
- </tr>`;
2995
+ const conditionCode = templateUtilities.codeableConcept(cond.code);
2996
+ if (!addedConditionCodes.has(conditionCode)) {
2997
+ addedConditionCodes.add(conditionCode);
2998
+ html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2999
+ <td class="Name">${conditionCode}</td>
3000
+ <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
3001
+ <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
3002
+ </tr>`;
3003
+ }
2975
3004
  }
2976
3005
  html += `</tbody>
2977
3006
  </table>`;
package/dist/index.js CHANGED
@@ -114,7 +114,7 @@ var IPSSectionResourceFilters = {
114
114
  // Only include pregnancy history Observations
115
115
  ["HistoryOfPregnancySection" /* PREGNANCY_HISTORY */]: (resource) => resource.resourceType === "Observation" && (resource.code?.coding?.some((c) => Object.keys(PREGNANCY_LOINC_CODES.PREGNANCY_STATUS).includes(c.code)) || resource.valueCodeableConcept?.coding?.some((c) => Object.keys(PREGNANCY_LOINC_CODES.PREGNANCY_OUTCOME).includes(c.code))),
116
116
  // Only include Conditions or completed ClinicalImpressions
117
- ["FunctionalStatusSection" /* FUNCTIONAL_STATUS */]: (resource) => resource.resourceType === "Condition" || resource.resourceType === "ClinicalImpression" && resource.status === "completed",
117
+ ["FunctionalStatusSection" /* FUNCTIONAL_STATUS */]: (resource) => resource.resourceType === "Condition" && resource.clinicalStatus?.coding?.some((c) => !["inactive", "resolved"].includes(c.code)) || resource.resourceType === "ClinicalImpression" && resource.status === "completed",
118
118
  // Only include resolved medical history Conditions
119
119
  ["HistoryOfPastIllnessSection" /* MEDICAL_HISTORY */]: (resource) => resource.resourceType === "Condition" && resource.clinicalStatus?.coding?.some((c) => ["inactive", "resolved"].includes(c.code)),
120
120
  // Only include active care plans
@@ -1859,8 +1859,8 @@ var ProblemListTemplate = class _ProblemListTemplate {
1859
1859
  let html = ``;
1860
1860
  const activeConditions = resources.map((entry) => entry) || [];
1861
1861
  activeConditions.sort((a, b) => {
1862
- const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
1863
- const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
1862
+ const dateA = a.recordedDate ? new Date(a.recordedDate).getTime() : 0;
1863
+ const dateB = b.recordedDate ? new Date(b.recordedDate).getTime() : 0;
1864
1864
  return dateB - dateA;
1865
1865
  });
1866
1866
  html += `
@@ -1873,12 +1873,17 @@ var ProblemListTemplate = class _ProblemListTemplate {
1873
1873
  </tr>
1874
1874
  </thead>
1875
1875
  <tbody>`;
1876
+ const addedConditionCodes = /* @__PURE__ */ new Set();
1876
1877
  for (const cond of activeConditions) {
1877
- html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1878
- <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
1879
- <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1880
- <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1881
- </tr>`;
1878
+ const conditionCode = templateUtilities.codeableConcept(cond.code);
1879
+ if (!addedConditionCodes.has(conditionCode)) {
1880
+ addedConditionCodes.add(conditionCode);
1881
+ html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
1882
+ <td class="Name">${conditionCode}</td>
1883
+ <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
1884
+ <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
1885
+ </tr>`;
1886
+ }
1882
1887
  }
1883
1888
  html += `</tbody>
1884
1889
  </table>`;
@@ -2362,8 +2367,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2362
2367
  </tr>
2363
2368
  </thead>
2364
2369
  <tbody>`;
2365
- let observationExists = false;
2366
- let diagnosticReportExists = false;
2370
+ const observationAdded = /* @__PURE__ */ new Set();
2371
+ const diagnosticReportAdded = /* @__PURE__ */ new Set();
2367
2372
  for (const resourceItem of resources) {
2368
2373
  for (const rowData of resourceItem.section ?? []) {
2369
2374
  const data = {};
@@ -2403,7 +2408,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2403
2408
  }
2404
2409
  }
2405
2410
  if (resourceItem.title === "Observation|Labs Summary Grouped by Lab Code") {
2406
- observationExists = true;
2407
2411
  let date = data["effectiveDateTime"] ? templateUtilities.renderTime(data["effectiveDateTime"], timezone) : "";
2408
2412
  if (!date && data["effectivePeriodStart"]) {
2409
2413
  date = templateUtilities.renderTime(data["effectivePeriodStart"], timezone);
@@ -2412,48 +2416,59 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2412
2416
  }
2413
2417
  }
2414
2418
  if (components.length > 0) {
2415
- const groupName = data["code"] ?? "";
2419
+ const groupName = data["code"] ? `${data["code"]} - ` : "";
2416
2420
  for (const component of components) {
2417
- this.formatSummaryObservationData(component);
2418
- observationhtml += `
2419
- <tr>
2420
- <td>${groupName ? groupName + " - " : ""}${component["code"] ?? "-"}</td>
2421
- <td>${component["formattedValue"] ?? "-"}</td>
2422
- <td>${component["referenceRange"]?.trim() ?? "-"}</td>
2423
- <td>${date ?? "-"}</td>
2424
- </tr>`;
2421
+ const componentCode = `${groupName}${component["code"] ?? ""}`;
2422
+ if (componentCode && !observationAdded.has(componentCode)) {
2423
+ observationAdded.add(componentCode);
2424
+ this.formatSummaryObservationData(component);
2425
+ observationhtml += `
2426
+ <tr>
2427
+ <td>${componentCode}</td>
2428
+ <td>${component["formattedValue"] ?? "-"}</td>
2429
+ <td>${component["referenceRange"]?.trim() ?? "-"}</td>
2430
+ <td>${date ?? "-"}</td>
2431
+ </tr>`;
2432
+ }
2425
2433
  }
2426
2434
  } else {
2427
- this.formatSummaryObservationData(data);
2428
- observationhtml += `
2429
- <tr>
2430
- <td>${data["code"] ?? "-"}</td>
2431
- <td>${data["formattedValue"] ?? "-"}</td>
2432
- <td>${data["referenceRange"]?.trim() ?? "-"}</td>
2433
- <td>${date ?? "-"}</td>
2434
- </tr>`;
2435
+ const code = data["code"] ?? "";
2436
+ if (code && !observationAdded.has(code)) {
2437
+ observationAdded.add(code);
2438
+ this.formatSummaryObservationData(data);
2439
+ observationhtml += `
2440
+ <tr>
2441
+ <td>${data["code"] ?? "-"}</td>
2442
+ <td>${data["formattedValue"] ?? "-"}</td>
2443
+ <td>${data["referenceRange"]?.trim() ?? "-"}</td>
2444
+ <td>${date ?? "-"}</td>
2445
+ </tr>`;
2446
+ }
2435
2447
  }
2436
2448
  } else if (resourceItem.title === "DiagnosticReportLab Summary Grouped by DiagnosticReport|Lab Code") {
2437
2449
  if (data["status"] === "final") {
2438
- diagnosticReportExists = true;
2439
- diagnosticReporthtml += `
2440
- <tr>
2441
- <td>${data["report"] ?? "-"}</td>
2442
- <td>${data["performer"] ?? "-"}</td>
2443
- <td>${templateUtilities.renderTime(data["issued"], timezone) ?? "-"}</td>
2444
- </tr>`;
2450
+ const reportName = data["report"] ?? "";
2451
+ if (reportName && !diagnosticReportAdded.has(reportName)) {
2452
+ diagnosticReportAdded.add(reportName);
2453
+ diagnosticReporthtml += `
2454
+ <tr>
2455
+ <td>${data["report"] ?? "-"}</td>
2456
+ <td>${data["performer"] ?? "-"}</td>
2457
+ <td>${templateUtilities.renderTime(data["issued"], timezone) ?? "-"}</td>
2458
+ </tr>`;
2459
+ }
2445
2460
  }
2446
2461
  }
2447
2462
  }
2448
2463
  }
2449
- if (observationExists) {
2464
+ if (observationAdded.size > 0) {
2450
2465
  html += observationhtml;
2451
2466
  html += `
2452
2467
  </tbody>
2453
2468
  </table>
2454
2469
  </div>`;
2455
2470
  }
2456
- if (diagnosticReportExists) {
2471
+ if (diagnosticReportAdded.size > 0) {
2457
2472
  html += diagnosticReporthtml;
2458
2473
  html += `
2459
2474
  </tbody>
@@ -2462,7 +2477,7 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2462
2477
  }
2463
2478
  html += `
2464
2479
  </div>`;
2465
- return observationExists || diagnosticReportExists ? html : void 0;
2480
+ return observationAdded.size > 0 || diagnosticReportAdded.size > 0 ? html : void 0;
2466
2481
  }
2467
2482
  /**
2468
2483
  * Internal static implementation that actually generates the narrative
@@ -2476,8 +2491,8 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2476
2491
  const observations = this.getObservations(resources);
2477
2492
  if (observations.length > 0) {
2478
2493
  observations.sort((a, b) => {
2479
- const dateA = a.effectiveDateTime || a.effectivePeriod?.start;
2480
- const dateB = b.effectiveDateTime || b.effectivePeriod?.start;
2494
+ const dateA = a.effectiveDateTime || a.effectivePeriod?.start || a.effectivePeriod?.end;
2495
+ const dateB = b.effectiveDateTime || b.effectivePeriod?.start || b.effectivePeriod?.end;
2481
2496
  return dateA && dateB ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
2482
2497
  });
2483
2498
  html += this.renderObservations(templateUtilities, observations, timezone);
@@ -2532,17 +2547,22 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2532
2547
  </tr>
2533
2548
  </thead>
2534
2549
  <tbody>`;
2550
+ const observationAdded = /* @__PURE__ */ new Set();
2535
2551
  for (const obs of observations) {
2536
- html += `
2537
- <tr id="${templateUtilities.narrativeLinkId(obs)}">
2538
- <td>${templateUtilities.codeableConcept(obs.code)}</td>
2539
- <td>${templateUtilities.extractObservationValue(obs)}</td>
2540
- <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
2541
- <td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
2542
- <td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
2543
- <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
2544
- <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
2545
- </tr>`;
2552
+ const obsCode = templateUtilities.codeableConcept(obs.code);
2553
+ if (!observationAdded.has(obsCode)) {
2554
+ observationAdded.add(obsCode);
2555
+ html += `
2556
+ <tr id="${templateUtilities.narrativeLinkId(obs)}">
2557
+ <td>${obsCode}</td>
2558
+ <td>${templateUtilities.extractObservationValue(obs)}</td>
2559
+ <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
2560
+ <td>${templateUtilities.firstFromCodeableConceptList(obs.interpretation)}</td>
2561
+ <td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
2562
+ <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
2563
+ <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
2564
+ </tr>`;
2565
+ }
2546
2566
  }
2547
2567
  html += `
2548
2568
  </tbody>
@@ -2569,18 +2589,23 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2569
2589
  </tr>
2570
2590
  </thead>
2571
2591
  <tbody>`;
2592
+ const diagnosticReportAdded = /* @__PURE__ */ new Set();
2572
2593
  for (const report of reports) {
2573
- let resultCount = "";
2574
- if (report.result && Array.isArray(report.result)) {
2575
- resultCount = `${report.result.length} result${report.result.length !== 1 ? "s" : ""}`;
2594
+ const reportName = templateUtilities.codeableConcept(report.code);
2595
+ if (!diagnosticReportAdded.has(reportName)) {
2596
+ diagnosticReportAdded.add(reportName);
2597
+ let resultCount = "";
2598
+ if (report.result && Array.isArray(report.result)) {
2599
+ resultCount = `${report.result.length} result${report.result.length !== 1 ? "s" : ""}`;
2600
+ }
2601
+ html += `
2602
+ <tr id="${templateUtilities.narrativeLinkId(report)}">
2603
+ <td>${reportName}</td>
2604
+ <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
2605
+ <td>${resultCount}</td>
2606
+ <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
2607
+ </tr>`;
2576
2608
  }
2577
- html += `
2578
- <tr id="${templateUtilities.narrativeLinkId(report)}">
2579
- <td>${templateUtilities.codeableConcept(report.code)}</td>
2580
- <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
2581
- <td>${resultCount}</td>
2582
- <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
2583
- </tr>`;
2584
2609
  }
2585
2610
  html += `
2586
2611
  </tbody>
@@ -2760,8 +2785,8 @@ var PastHistoryOfIllnessTemplate = class {
2760
2785
  let html = ``;
2761
2786
  const resolvedConditions = resources.map((entry) => entry) || [];
2762
2787
  resolvedConditions.sort((a, b) => {
2763
- const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
2764
- const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
2788
+ const dateA = a.recordedDate ? new Date(a.recordedDate).getTime() : 0;
2789
+ const dateB = b.recordedDate ? new Date(b.recordedDate).getTime() : 0;
2765
2790
  return dateB - dateA;
2766
2791
  });
2767
2792
  html += `
@@ -2775,13 +2800,18 @@ var PastHistoryOfIllnessTemplate = class {
2775
2800
  </tr>
2776
2801
  </thead>
2777
2802
  <tbody>`;
2803
+ const addedConditionCodes = /* @__PURE__ */ new Set();
2778
2804
  for (const cond of resolvedConditions) {
2779
- html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2780
- <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
2781
- <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2782
- <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2783
- <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
2784
- </tr>`;
2805
+ const conditionCode = templateUtilities.codeableConcept(cond.code);
2806
+ if (!addedConditionCodes.has(conditionCode)) {
2807
+ addedConditionCodes.add(conditionCode);
2808
+ html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2809
+ <td class="Name">${conditionCode}</td>
2810
+ <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2811
+ <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2812
+ <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
2813
+ </tr>`;
2814
+ }
2785
2815
  }
2786
2816
  html += `</tbody>
2787
2817
  </table>`;
@@ -2906,20 +2936,14 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
2906
2936
  const clinicalImpressions = [];
2907
2937
  for (const resourceItem of resources) {
2908
2938
  if (resourceItem.resourceType === "Condition") {
2909
- const cond = resourceItem;
2910
- const isResolved = cond.clinicalStatus?.coding?.some(
2911
- (c) => c.code === "resolved" || c.code === "inactive" || c.display?.toLowerCase().includes("resolved")
2912
- );
2913
- if (!isResolved) {
2914
- activeConditions.push(cond);
2915
- }
2939
+ activeConditions.push(resourceItem);
2916
2940
  } else if (resourceItem.resourceType === "ClinicalImpression") {
2917
2941
  clinicalImpressions.push(resourceItem);
2918
2942
  }
2919
2943
  }
2920
2944
  activeConditions.sort((a, b) => {
2921
- const dateA = a.onsetDateTime ? new Date(a.onsetDateTime).getTime() : 0;
2922
- const dateB = b.onsetDateTime ? new Date(b.onsetDateTime).getTime() : 0;
2945
+ const dateA = a.recordedDate ? new Date(a.recordedDate).getTime() : 0;
2946
+ const dateB = b.recordedDate ? new Date(b.recordedDate).getTime() : 0;
2923
2947
  return dateB - dateA;
2924
2948
  });
2925
2949
  clinicalImpressions.sort((a, b) => {
@@ -2938,12 +2962,17 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
2938
2962
  </tr>
2939
2963
  </thead>
2940
2964
  <tbody>`;
2965
+ const addedConditionCodes = /* @__PURE__ */ new Set();
2941
2966
  for (const cond of activeConditions) {
2942
- html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2943
- <td class="Name">${templateUtilities.codeableConcept(cond.code)}</td>
2944
- <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2945
- <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2946
- </tr>`;
2967
+ const conditionCode = templateUtilities.codeableConcept(cond.code);
2968
+ if (!addedConditionCodes.has(conditionCode)) {
2969
+ addedConditionCodes.add(conditionCode);
2970
+ html += `<tr id="${templateUtilities.narrativeLinkId(cond)}">
2971
+ <td class="Name">${conditionCode}</td>
2972
+ <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2973
+ <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2974
+ </tr>`;
2975
+ }
2947
2976
  }
2948
2977
  html += `</tbody>
2949
2978
  </table>`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imranq2/fhirpatientsummary",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "A template for creating npm packages using TypeScript and VSCode",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",