@measurequick/measurequick-report-generator 1.5.216 → 1.5.217

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@measurequick/measurequick-report-generator",
3
- "version": "1.5.216",
3
+ "version": "1.5.217",
4
4
  "description": "Generates PDF documents for various measureQuick applications.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,4 +1,4 @@
1
- import { PDFDocument } from "pdf-lib";
1
+ import { PDFDocument, rgb } from "pdf-lib";
2
2
  import * as base64 from "../base-64/icons.js";
3
3
  import * as pdf from "../base-64/mq-vitals-heating.js";
4
4
  import * as systemInfoPage from "./system-info-page.js";
@@ -548,16 +548,51 @@ export async function getReport(payload, _test) {
548
548
  passFails.splice(3, 1);
549
549
  pfLabels.splice(3, 1);
550
550
  }
551
+
552
+ // CO threshold levels (matching mq-hvac app)
553
+ // Normal: 0-8 ppm (Green)
554
+ // Elevated: 9-35 ppm (Yellow/Orange)
555
+ // Dangerous: 36-69 ppm (Red)
556
+ // Emergency: 70+ ppm (Red)
557
+ function getCOIcon(coValue) {
558
+ if (coValue === null || coValue === undefined || isNaN(coValue)) {
559
+ return iconRangeGreen; // default to green if no value
560
+ }
561
+ if (coValue <= 8) {
562
+ return iconRangeGreen; // Normal
563
+ } else if (coValue >= 9 && coValue <= 35) {
564
+ return iconRangeYellow; // Elevated
565
+ } else {
566
+ return iconRangeRed; // Dangerous (36-69) or Emergency (70+)
567
+ }
568
+ }
569
+
570
+ function getCOStateText(coValue) {
571
+ if (coValue === null || coValue === undefined || isNaN(coValue)) {
572
+ return "";
573
+ }
574
+ if (coValue <= 8) {
575
+ return "Normal";
576
+ } else if (coValue >= 9 && coValue <= 35) {
577
+ return "Elevated";
578
+ } else if (coValue >= 36 && coValue <= 69) {
579
+ return "Dangerous";
580
+ } else {
581
+ return "Emergency";
582
+ }
583
+ }
584
+
585
+ // Collect items that have values
586
+ let validItems = [];
551
587
  for (let i = 0; i < passFails.length; i++) {
552
588
  const meas = test.testInfo[passFails[i]];
553
589
 
554
- // If no value provided, hide the label (set empty) and skip icon
590
+ // Skip items with no value
555
591
  if (meas === undefined || meas === null || meas === "") {
556
- safeSetText(form, `SSR${i + 1}`, "");
557
592
  continue;
558
593
  }
559
594
 
560
- // Choose icon based on value
595
+ // Determine icon based on value
561
596
  let icon;
562
597
  if (meas === "Caution") {
563
598
  icon = iconRangeYellow;
@@ -566,53 +601,65 @@ export async function getReport(payload, _test) {
566
601
  } else {
567
602
  icon = iconRangeRed;
568
603
  }
569
- if (passFails[i] === "heating_efficiency_pass_fail")
604
+ if (passFails[i] === "heating_efficiency_pass_fail") {
570
605
  icon = iconRangeGreen;
571
-
572
- // Set the icon as before
573
- safeSetImage(form, `ImageSubsystem${i + 1}_af_image`, icon);
606
+ }
574
607
 
575
608
  const suffix = test.testInfo[passFails[i] + "_override"] ? " *" : "";
576
- const fieldName = `SSR${i + 1}`;
577
-
578
- // Default label for non-special cases
579
609
  let label = pfLabels[i] + suffix;
610
+ let textColor = rgb(0, 0, 0); // default black
580
611
 
581
- // Special handling: Ambient CO failure should be red and show a stronger warning
612
+ // Special handling for Ambient CO
582
613
  if (passFails[i] === "ambient_pass_fail") {
583
- const isFail = !(
584
- meas === "Pass" ||
585
- meas === "High" ||
586
- meas === "Mid" ||
587
- meas === "Caution"
588
- );
589
-
590
- if (isFail) {
591
- label = "CO Ambient High, Investigate Source!";
592
- try {
593
- const tf = form.getTextField(fieldName);
594
- tf.setText(label);
595
- tf.setTextColor(rgb(1, 0, 0)); // red
596
- } catch (e) {}
597
- continue; // move to next item; we've already set text & color
614
+ const coValue = test.data && test.data.co_ambient !== undefined && test.data.co_ambient !== null
615
+ ? Number(test.data.co_ambient)
616
+ : null;
617
+
618
+ // Use CO-specific icon based on actual value
619
+ if (coValue !== null && !isNaN(coValue)) {
620
+ icon = getCOIcon(coValue);
621
+ const stateText = getCOStateText(coValue);
622
+ label = "Ambient CO: " + Math.round(coValue) + " ppm" + (stateText ? " (" + stateText + ")" : "") + suffix;
623
+
624
+ // Set text color based on CO level
625
+ if (coValue >= 36) {
626
+ textColor = rgb(1, 0, 0); // Red for Dangerous/Emergency
627
+ } else if (coValue >= 9) {
628
+ textColor = rgb(0.8, 0.4, 0); // Orange for Elevated
629
+ }
598
630
  } else {
599
- // Non-fail states: ensure text is black
600
- try {
601
- const tf = form.getTextField(fieldName);
602
- tf.setText(label);
603
- tf.setTextColor(rgb(0, 0, 0)); // black
604
- } catch (e) {}
605
- continue;
631
+ // No CO value, use pass/fail status
632
+ const isFail = !(meas === "Pass" || meas === "High" || meas === "Mid" || meas === "Caution");
633
+ if (isFail) {
634
+ label = "CO Ambient High, Investigate Source!" + suffix;
635
+ textColor = rgb(1, 0, 0);
636
+ icon = iconRangeRed;
637
+ }
606
638
  }
607
639
  }
608
640
 
609
- // All other pass/fail items: keep existing label, ensure black text
641
+ validItems.push({ label, icon, textColor });
642
+ }
643
+
644
+ // Fill fields sequentially with valid items (no gaps)
645
+ for (let i = 0; i < validItems.length; i++) {
646
+ const item = validItems[i];
647
+ const fieldName = `SSR${i + 1}`;
648
+
649
+ safeSetImage(form, `ImageSubsystem${i + 1}_af_image`, item.icon);
650
+
610
651
  try {
611
652
  const tf = form.getTextField(fieldName);
612
- tf.setText(label);
613
- tf.setTextColor(rgb(0, 0, 0));
653
+ tf.setText(item.label);
654
+ tf.setTextColor(item.textColor);
614
655
  } catch (e) {}
615
656
  }
657
+
658
+ // Clear any remaining unused fields
659
+ for (let i = validItems.length; i < passFails.length; i++) {
660
+ safeSetText(form, `SSR${i + 1}`, "");
661
+ // Clear the icon by not setting it (or set to null if needed)
662
+ }
616
663
  } else safeSetText(form, `SSR1`, "Not yet reviewed");
617
664
 
618
665
  if (payload.meta.report_type != "FullReport") {