Przeglądaj źródła

Canvas based Vitals

Vijayakrishnan 4 lat temu
rodzic
commit
37571bf334

+ 6 - 0
public/css/style.css

@@ -332,6 +332,9 @@ body>nav.navbar {
 .c-pointer {
     cursor: pointer;
 }
+.events-none {
+    pointer-events: none;
+}
 .inset-comment p {
     margin-bottom: 0.3rem;
 }
@@ -885,6 +888,9 @@ body .node input[type="number"] {
 .stag-popup.wide>form {
     width: calc(100% - 4rem);
 }
+.stag-popup.narrow>form {
+    max-width: 500px;
+}
 .stag-popup.stag-popup-sm>form {
     max-width: 500px;
 }

+ 10 - 0
resources/views/app/patient/canvas-sections/vitals/default.php

@@ -0,0 +1,10 @@
+<?php
+
+$canvasData = [];
+if ($patient->canvas_data) {
+    $canvasData = json_decode($patient->canvas_data, true);
+    if (isset($canvasData["vitals"])) {
+        $canvasData = $canvasData["vitals"];
+    }
+}
+$contentData = $canvasData;

+ 168 - 0
resources/views/app/patient/canvas-sections/vitals/form.blade.php

@@ -0,0 +1,168 @@
+<?php
+if(!$contentData) {
+    $contentData = [
+        "heightInches" => [
+            "label" => "Ht. (in.)",
+            "value" => "",
+            "date" => "",
+        ],
+        "weightPounds" => [
+            "label" => "Wt. (lbs.)",
+            "value" => "",
+            "date" => "",
+        ],
+        "temperatureF" => [
+            "label" => "Temp. (F)",
+            "value" => "",
+            "date" => "",
+        ],
+        "pulseRatePerMinute" => [
+            "label" => "Pulse",
+            "value" => "",
+            "date" => "",
+        ],
+        "respirationRatePerMinute" => [
+            "label" => "Resp.",
+            "value" => "",
+            "date" => "",
+        ],
+        "pulseOx" => [
+            "label" => "Pulse Ox.",
+            "value" => "",
+            "date" => "",
+        ],
+        "systolicBP" => [
+            "label" => "SBP",
+            "value" => "",
+            "date" => "",
+        ],
+        "diastolicBP" => [
+            "label" => "DBP",
+            "value" => "",
+            "date" => "",
+        ],
+        "smokingStatus" => [
+            "label" => "Smoking Status",
+            "value" => "",
+            "date" => "",
+        ],
+        "bmi" => [
+            "label" => "BMI (kg/m²)",
+            "value" => "",
+            "date" => "",
+        ],
+    ];
+}
+
+$formID = rand(0, 100000);
+?>
+<div id="vitalsSection">
+    <h3 class="stag-popup-title mb-2 border-bottom-0 pb-1 hide-if-note">
+        <span>Vitals</span>
+        <a href="#" onclick="return closeStagPopup()"
+           class="ml-auto text-secondary">
+            <i class="fa fa-times-circle"></i>
+        </a>
+    </h3>
+
+    <input type="hidden" name="data" value="{{json_encode($contentData)}}">
+
+    <table class="table table-sm table-bordered mb-2 table-edit-sheet">
+        <thead>
+        <tr class="bg-light">
+            <th class="px-2 text-secondary border-bottom-0 w-25">Vital</th>
+            <th class="px-2 text-secondary border-bottom-0 w-35">Value</th>
+            <th class="px-2 text-secondary border-bottom-0">Date</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr v-for="(item, index) in items">
+            <td>
+                <input type="text" :data-index="index" tabindex="-1"
+                       class="form-control form-control-sm events-none"
+                       data-field="title" v-model="item.label" readonly>
+            </td>
+            <td>
+                <input type="text" :data-index="index" v-if="index === 'bmi'" :readonly="index === 'bmi'"
+                       class="form-control form-control-sm vitals-title"
+                       data-field="value" v-model="bmi">
+                <input type="text" :data-index="index" v-if="index !== 'bmi'"
+                       class="form-control form-control-sm vitals-title"
+                       data-field="value" v-model="item.value">
+            </td>
+            <td>
+                <input type="date" :data-index="index" v-if="index !== 'bmi'"
+                       class="form-control form-control-sm vitals-title"
+                       data-field="date" v-model="item.date">
+            </td>
+        </tr>
+        </tbody>
+    </table>
+
+</div>
+<script>
+    (function() {
+        function init() {
+            window.clientVitalsApp = new Vue({
+                el: '#vitalsSection',
+                data: {
+                    items: <?= json_encode($contentData) ?>
+                },
+                mounted: function() {
+                    $(this.$el).closest('#vitalsSection').find('[name="data"]').val(
+                        JSON.stringify(this.cleanObject(this.items))
+                    );
+                },
+                watch: {
+                    $data: {
+                        handler: function(val, oldVal) {
+                            $(this.$el).closest('#vitalsSection').find('[name="data"]').val(
+                                JSON.stringify(this.cleanObject(this.items))
+                            );
+                        },
+                        deep: true
+                    },
+                },
+                computed: {
+                    bmi: function () {
+                        let result = '';
+                        let h = this.items.heightInches.value, w = this.items.weightPounds.value;
+                        if(!h || !w) {
+                            return result;
+                        }
+                        try {
+                            h = parseFloat(h);
+                            w = parseFloat(w);
+                            if(!h || !w) {
+                                this.items.bmi.value = '';
+                                return result;
+                            }
+                            let result = (w / [ h * h]) * 703;
+                            return result.toFixed(1);
+                        }
+                        catch (e) {
+                            return result;
+                        }
+                    }
+                },
+                methods: {
+                    cleanObject: function(_source) {
+                        let plObject = {};
+                        for (let y in _source) {
+                            if(_source.hasOwnProperty(y)) {
+                                plObject[y] = _source[y];
+                            }
+                        }
+                        plObject.bmi = {
+                            label: "BMI (kg/m²)",
+                            value: this.bmi,
+                            date: "",
+                        };
+                        return plObject;
+                    }
+                }
+            });
+        }
+        addMCInitializer('client-vitals-{{ $patient->uid }}', init);
+    })();
+</script>

+ 76 - 0
resources/views/app/patient/canvas-sections/vitals/summary.php

@@ -0,0 +1,76 @@
+<?php
+
+$contentData = [
+    "heightInches" => [
+        "label" => "Ht. (in.)",
+        "value" => "",
+        "date" => "",
+    ],
+    "weightPounds" => [
+        "label" => "Wt. (lbs.)",
+        "value" => "",
+        "date" => "",
+    ],
+    "temperatureF" => [
+        "label" => "Temp. (F)",
+        "value" => "",
+        "date" => "",
+    ],
+    "pulseRatePerMinute" => [
+        "label" => "Pulse",
+        "value" => "",
+        "date" => "",
+    ],
+    "respirationRatePerMinute" => [
+        "label" => "Resp.",
+        "value" => "",
+        "date" => "",
+    ],
+    "pulseOx" => [
+        "label" => "Pulse Ox.",
+        "value" => "",
+        "date" => "",
+    ],
+    "systolicBP" => [
+        "label" => "SBP",
+        "value" => "",
+        "date" => "",
+    ],
+    "diastolicBP" => [
+        "label" => "DBP",
+        "value" => "",
+        "date" => "",
+    ],
+    "smokingStatus" => [
+        "label" => "Smoking Status",
+        "value" => "",
+        "date" => "",
+    ],
+    "bmi" => [
+        "label" => "BMI (kg/m²)",
+        "value" => "",
+        "date" => "",
+    ],
+];
+
+if($patient->canvas_data) {
+    $canvasData = json_decode($patient->canvas_data, true);
+    if(isset($canvasData["vitals"])) {
+        $contentData = $canvasData["vitals"];
+    }
+}
+
+foreach ($contentData as $k => $vital) {
+?>
+    <div class="d-flex vital-item align-items-center">
+        <span class="content-html text-nowrap">
+            <span><?= $vital["label"] ?>:</span>
+            <b><?= isset($vital["value"]) && !empty($vital["value"]) ? $vital["value"] : '-' ?></b>
+            <?php if(!!$vital["date"]): ?>
+                <span class="font-weight-normal text-secondary ml-2 text-sm">(as on <?= friendly_date_time($vital["date"], false) ?>)</span>
+            <?php endif; ?>
+        </span>
+    </div>
+<?php
+}
+?>

+ 13 - 1
resources/views/app/patient/dashboard.blade.php

@@ -325,7 +325,19 @@
                 </div>
 
                 {{-- vitals --}}
-                @include('app/patient/partials/vitals')
+                {{--@include('app/patient/partials/vitals')--}}
+
+                {{-- canvas based vitals --}}
+                <div class="pt-2 border-top">
+                    <div class="d-flex align-items-center pb-2">
+                        <h6 class="my-0 font-weight-bold text-secondary">Vitals</h6>
+                        <span class="mx-2 text-secondary">|</span>
+                        @include('app.patient.canvas-sections.canvas-editor-modal', ['key' => 'vitals', 'class' => 'narrow'])
+                    </div>
+                    <div class="bg-light border p-2 mb-3">
+                        @include('app.patient.canvas-sections.vitals.summary')
+                    </div>
+                </div>
 
             </div>
             <div class="col-6">

+ 1 - 1
resources/views/layouts/template.blade.php

@@ -281,7 +281,7 @@
             stagPopup.find('[moe][initialized]').removeAttr('initialized');
             initMoes();
             window.setTimeout(function() {
-                stagPopup.find('input[type="text"]:visible,select:visible').first().focus();
+                stagPopup.find('input[type="text"]:not([readonly]):visible,select:visible').first().focus();
             }, 150);
             return false;
         }