Browse Source

Merge branch 'dev-josh-notes' of rav.triplestart.com:jmudaka/stagfe2 into dev-josh-notes

= 3 years ago
parent
commit
404403c4f1

+ 14 - 2
app/Models/Point.php

@@ -28,7 +28,19 @@ class Point extends Model
         return $this->hasOne(Note::class, 'id', 'last_child_plan_point_scoped_note_id');
     }
 
-    public static function getIntakePointsOfCategory(Client $_patient, String $_category, Note $_note) {
+    public static function getGlobalSingletonOfCategory(Client $_patient, String $_category, $_assoc = false) {
+        $point = Point
+            ::where('client_id', $_patient->id)
+            ->where('category', $_category)
+            ->orderBy('created_at', 'DESC')
+            ->first();
+        if ($point->data) {
+            $point->data = json_decode($point->data, $_assoc);
+        }
+        return $point;
+    }
+
+    public static function getIntakePointsOfCategory(Client $_patient, String $_category, Note $_note, $_assoc = false) {
         $points = Point
             ::where('client_id', $_patient->id)
             ->where('category', $_category)
@@ -45,7 +57,7 @@ class Point extends Model
             ->get();
         foreach ($points as $point) {
             if ($point->data) {
-                $point->data = json_decode($point->data);
+                $point->data = json_decode($point->data, $_assoc);
             }
         }
         return $points;

+ 42 - 0
resources/views/app/patient/note/_templates-v2-index.blade.php

@@ -0,0 +1,42 @@
+<?php
+$templateIndex = json_decode(file_get_contents(storage_path('templates/index.json')));
+$hasTemplates = false;
+if(isset($templateIndex->{$sectionInternalName})) {
+    $hasTemplates = true;
+    $templateName = '';
+    $defaultTemplateName = '';
+    foreach($templateIndex->{$sectionInternalName} as $k => $templateSet) {
+        if($templateName === '') $templateName = $k;
+        if($templateSet->default) $defaultTemplateName = $k;
+    }
+    if($defaultTemplateName !== '') $templateName = $defaultTemplateName;
+?>
+    <span class="mx-2 text-secondary text-sm d-none if-edit">|</span>
+    <span class="position-relative d-none if-edit">
+        <a href="#" class="note-templates-trigger">Templates</a>
+        <div class="note-template-container">
+            <div class="position-relative w-100">
+                <div class="note-template-output">
+                    <div class="font-weight-bold text-secondary">Result:</div>
+                    <div class="note-template-output-text"></div>
+                </div>
+                <div class="note-template-buttons d-flex align-items-center">
+                    <button class="btn btn-sm btn-default bg-white border text-primary border-primary note-template-apply-trigger">Apply</button>
+                    <button class="btn btn-sm btn-default bg-light border text-secondary border-secondary note-template-close-trigger">Close</button>
+                </div>
+            </div>
+            <div class="p-1 border border-bottom">
+                <select class="form-control form-control-sm note-template-set-chooser" data-section="{{$sectionInternalName}}">
+                    @foreach($templateIndex->{$sectionInternalName} as $k => $templateSet)
+                        <option value="{{$k}}" {{$k === $templateName ? 'selected' : ''}}>{{$templateSet->name}}</option>
+                    @endforeach
+                </select>
+            </div>
+            {{--@include('app/patient/note/_template')--}}
+        </div>
+    </span>
+<?php
+}
+?>
+
+

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

@@ -455,6 +455,7 @@
                         }
                         ?>
                         <script>window.userShortcuts = <?= json_encode($shortCutsObject); ?>;</script>
+                        <script>window.segmentInitializers = {};</script>
                         <?php
                         $shortcuts = "";
                         $latestSectionTS = 0;

+ 2 - 0
resources/views/app/patient/note/segment.blade.php

@@ -17,6 +17,8 @@
 			Refresh
 		</a>
 
+		@include('app/patient/note/_templates-v2-index', ['sectionInternalName' => $segment->segmentTemplate->internal_name])
+
 		<span class="mx-2 text-secondary text-sm d-none if-edit">|</span>
 
 		<!-- toggle to read mode -->

+ 48 - 2
resources/views/app/patient/note/segment_script.blade.php

@@ -17,6 +17,13 @@
                 initRTEs(segment);
                 initSegmentMoes(segment);
                 initMoes();
+                if(window.segmentInitializers) {
+                    let internalName = segment.attr('data-segment-template-name');
+                    if(window.segmentInitializers.hasOwnProperty(internalName) &&
+                        typeof window.segmentInitializers[internalName] === 'function') {
+                        window.segmentInitializers[internalName].call(window);
+                    }
+                }
             }
         }
 
@@ -49,7 +56,26 @@
                     }
                     form.find('[data-name]').each(function() {
                         if(!parsed) parsed = {};
-                        parsed[$(this).attr('data-name')] = $(this).val();
+
+                        let keys = $(this).attr('data-name').split('->');
+                        let currentNode = parsed;
+                        for (let i = 0; i < keys.length; i++) {
+                            if(i !== keys.length - 1) {
+                                if(typeof currentNode[keys[i]] === 'undefined') {
+                                    currentNode[keys[i]] = {};
+                                }
+                                currentNode = currentNode[keys[i]];
+                            }
+                            else {
+                                if($(this).is(':checkbox')) {
+                                    currentNode[keys[i]] = $(this).prop('checked');
+                                }
+                                else {
+                                    currentNode[keys[i]] = $(this).val();
+                                }
+                            }
+                        }
+
                     });
                     if(parsed) {
                         dataField.val(JSON.stringify(parsed));
@@ -57,9 +83,17 @@
 
                     showMask();
 
+                    let closeOnSave = false, noteSection = form.closest('.note-section');
+                    if($(this).closest('[visit-moe]').is('[close-on-save]')) {
+                        closeOnSave = true;
+                    }
+
                     $.post(form.attr('url'), form.serialize(), _data => {
                         hideMask();
                         updateAllSegmentsInResponse(_data);
+                        if(closeOnSave) {
+                            noteSection.removeClass('edit');
+                        }
                     }, 'json');
                     return false;
                 });
@@ -79,6 +113,9 @@
                 .off('click.visit-moe-cancel')
                 .on('click.visit-moe-cancel', function() {
                     $(this).closest('[visit-moe]').find('[url]:not([show])').hide();
+                    if($(this).closest('[visit-moe]').is('[close-on-cancel]')) {
+                        $(this).closest('.note-section').removeClass('edit');
+                    }
                     return false;
                 });
         }
@@ -96,7 +133,7 @@
                     fieldName = this.name;
 
                 var el = this;
-                var existingContent = $(el).attr('data-content');
+                var existingContent = $(el).html();
                 var quill = new Quill(el, {
                     theme: 'snow',
                     modules: stagQuillConfig
@@ -133,6 +170,15 @@
             initRTEs(parent);
             initSegmentMoes(parent);
 
+            // check and run all segment initializers
+            if(window.segmentInitializers) {
+                for(let x in window.segmentInitializers) {
+                    if(window.segmentInitializers.hasOwnProperty(x) && typeof window.segmentInitializers[x] === 'function') {
+                        window.segmentInitializers[x].call(window);
+                    }
+                }
+            }
+
             // refresh segment
             $(document)
                 .off('click.refresh-segment', '.refresh-segment')

+ 4 - 2
resources/views/app/patient/segment-templates/_simple_text_segment/edit.php

@@ -8,12 +8,14 @@ if (!!@$point->data) {
     $parsed = json_decode($point->data);
 }
 ?>
-<div visit-moe class="d-block">
+<div visit-moe close-on-save close-on-cancel class="d-block">
     <form show url="/api/visitPoint/<?= $endPoint ?>" class="mcp-theme-1">
         <input type="hidden" name="segmentUid" value="<?= $segment->uid ?>">
         <input type="hidden" name="category" value="<?= $category ?>">
         <input type="hidden" name="data">
-        <div note-rte data-content="<?= $parsed && $parsed->value ? $parsed->value : '' ?>"  class="form-group mb-2 border-left border-right rte-holder"></div>
+        <div note-rte
+             class="form-group mb-2 border-left border-right rte-holder"
+        ><?= $parsed && $parsed->value ? $parsed->value : '' ?></div>
         <div>
             <button submit class="btn btn-sm btn-primary mr-2">Submit</button>
             <button cancel class="btn btn-sm btn-default border">Cancel</button>

+ 267 - 1
resources/views/app/patient/segment-templates/history_social/edit.php

@@ -1 +1,267 @@
-<h1>Edit for history_social</h1>
+<?php
+
+use App\Models\Point;
+use App\Models\Client;
+use App\Models\Note;
+use App\Models\Segment;
+
+/** @var Client $patient */
+/** @var Note $note */
+/** @var Segment $segment */
+
+$point = Point::getGlobalSingletonOfCategory($patient, 'SOCIAL_HISTORY',true);
+
+$socHx = $point->data;
+
+$fields = [
+    [
+        "Tobacco" => ["Current every day smoker", "Current some day smoker", "Former smoker", "Heavy tobacco smoker", "Light tobacco smoker", "Never smoker", "Smoker, current status unknown", "Unknown if ever smoked "],
+    ],
+    [
+        "Alcohol" => ["Do not drink", "Drink daily", "Frequently drink", "Hx of Alcoholism", "Occasional drink"],
+        "Drug Abuse" => ["IVDU", "Illicit drug use", "No illicit drug use"],
+    ],
+    [
+        "Cardiovascular" => ["Eat healthy meals", "Regular exercise", "Take daily aspirin"],
+        "Safety" => ["Household Smoke detector", "Keep Firearms in home", "Wear seatbelts"],
+    ],
+    [
+        "Sexual Activity" => ["Exposure to STI", "Homosexual encounters", "Not sexually active", "Safe sex practices", "Sexually active"],
+        "Birth Gender" => ["Male", "Female", "Undifferentiated"],
+    ]
+];
+
+$customFields = [];
+/*
+ // TODO
+$customFields = $pro->canvasCustomItems('sochx');
+$customFields = array_map(function($_item) {
+    return $_item['label'];
+}, $customFields->toArray());
+*/
+if (!$socHx) {
+    $socHx = [
+        "common" => [],
+        "custom" => [],
+        "comments" => "",
+    ];
+}
+
+$contentData = $socHx;
+?>
+<div visit-moe close-on-save close-on-cancel class="d-block">
+    <form show url="/api/visitPoint/upsertGlobalSingleton" class="mcp-theme-1">
+        <input type="hidden" name="segmentUid" value="<?= $segment->uid ?>">
+        <input type="hidden" name="category" value="SOCIAL_HISTORY">
+        <input type="hidden" name="data">
+        <div class="row">
+            <?php for ($i = 0; $i < count($fields); $i++): ?>
+                <div class="col-md-3">
+                    <?php foreach ($fields[$i] as $head => $values): ?>
+                        <div class="font-weight-bold mb-2"><?= $head ?></div>
+                        <div class="mb-3">
+                            <?php for ($k = 0; $k < count($values); $k++): ?>
+                                <?php $fName = $head . '_' . sanitize_field_name($values[$k]); ?>
+                                <label class="d-flex align-items-center mb-1">
+                                    <input type="checkbox" class="m-0"
+                                           data-name="common-><?= $fName ?>"
+                                        <?= @$contentData['common'][$fName] ? 'checked' : '' ?>
+                                    >
+                                    <span class="mx-2"><?= $values[$k] ?></span>
+                                    <!--<div moe>
+                                        <a href="#" start show>
+                                            <i v-show="common['<?= $fName ?>']" class="fa-comment"
+                                               :class="common['<?= $fName ?>__comments'] ? 'fas' : 'far'"></i>
+                                        </a>
+                                        <div url="/nop">
+                                            <div class="mb-2">
+                                        <textarea class="form-control form-control-sm ns-custom-comment"
+                                                  data-name="common['<?= $fName ?>__comments']"></textarea>
+                                            </div>
+                                            <div class="">
+                                                <button type="button" class="btn btn-sm btn-primary" cancel>Close
+                                                </button>
+                                            </div>
+                                        </div>
+                                    </div>-->
+                                </label>
+                            <?php endfor; ?>
+                        </div>
+                    <?php endforeach; ?>
+                </div>
+            <?php endfor; ?>
+        </div>
+
+        <?php /*
+            <div class="row border-top pt-3">
+                <div class="col-12">
+                    <div class="d-flex align-items-center mb-2">
+                        <span class="font-weight-bold">Custom Items</span>
+                        <span class="mx-2 text-secondary">|</span>
+                        <div moe>
+                            <a href="#" start show>Add</a>
+                            <div custom-item-form url="/api/sectionTemplateCustomItem/create">
+                                <div class="mb-2">
+                                    <input type="text" placeholder="Label"
+                                           v-model="newCustomItemLabel"
+                                           class="form-control form-control-sm label_new_custom_item">
+                                </div>
+                                <div>
+                                    <button type="button" class="btn btn-sm btn-primary mr-1"
+                                            v-on:click.prevent="saveCustomItem(newCustomItemLabel)">Submit</button>
+                                    <button type="button" class="btn btn-sm btn-default border"
+                                            v-on:click.prevent="cancelCustomItem()">Cancel</button>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    {{-- custom items --}}
+                    <div class="d-flex align-items-start flex-wrap custom-items-container">
+                        <div class="w-25" v-for="item in customFields">
+                            <label class="d-flex align-items-center mb-1">
+                                <input type="checkbox" class="m-0"
+                                       v-model="item.value">
+                                <span class="mx-2">@{{ item.label }}</span>
+                                <div moe>
+                                    <a href="#" start show>
+                                        <i v-show="item.value" class="fa-comment" :class="item.comments ? 'fas' : 'far'"></i>
+                                    </a>
+                                    <div url="/nop">
+                                        <div class="mb-2">
+                                            <textarea class="form-control form-control-sm ns-custom-comment" v-model="item.comments"></textarea>
+                                        </div>
+                                        <div class="">
+                                            <button type="button" class="btn btn-sm btn-primary" cancel>Close</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </label>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+            */ ?>
+
+        <div class="row mb-3">
+            <div class="col-12">
+                <textarea type="text" class="form-control form-control-sm p-2 mt-2"
+                          data-name="comments"
+                          placeholder="Comments"><?= @$contentData['comments'] ?: '' ?></textarea>
+            </div>
+        </div>
+
+        <div>
+            <button submit class="btn btn-sm btn-primary mr-2">Submit</button>
+            <button cancel class="btn btn-sm btn-default border">Cancel</button>
+        </div>
+
+    </form>
+
+</div>
+
+<script>
+    (function () {
+        let model = <?= json_encode($contentData) ?>;
+        model.newCustomItemLabel = '';
+        let customFields = <?= json_encode($customFields) ?>;
+        if (!model.customFields) {
+            model.customFields = [];
+        }
+        for (let i = 0; i < customFields.length; i++) {
+            let found = model.customFields.filter(function (_item) {
+                return _item.label === customFields[i];
+            }).length;
+            if (!found) {
+                model.customFields.push({
+                    label: customFields[i],
+                    value: '',
+                    comments: '',
+                })
+            }
+        }
+
+        function init() {
+            window.clientSocHXApp = new Vue({
+                el: '#sochxSection',
+                data: model,
+                mounted: function () {
+                    $('#sochxSection [moe][initialized]').removeAttr('initialized');
+                    initMoes();
+                    $('#sochxSection').find('[name="data"]').val(JSON.stringify({
+                        common: this.cleanObject(this.common),
+                        customFields: this.customFields,
+                        comments: this.comments,
+                    }));
+                },
+                watch: {
+                    $data: {
+                        handler: function (val, oldVal) {
+                            $('#sochxSection').find('[name="data"]').val(JSON.stringify({
+                                common: this.cleanObject(this.common),
+                                customFields: this.customFields,
+                                comments: this.comments,
+                            }));
+                        },
+                        deep: true
+                    }
+                },
+                methods: {
+                    cleanObject: function (_source) {
+                        let plObject = {};
+                        for (let y in _source) {
+                            if (_source.hasOwnProperty(y)) {
+                                plObject[y] = _source[y];
+                            }
+                        }
+                        return plObject;
+                    },
+                    saveCustomItem: function (_label) {
+                        if (!_label) return false;
+                        showMask();
+                        let self = this;
+                        $.post('/api/clientCanvasCustomItem/create', {
+                            proUid: '{{ $pro->uid }}',
+                            key: 'sochx',
+                            label: _label
+                        }, function (_data) {
+                            hideMask();
+                            if (_data && _data.success) {
+                                self.appendCustomItem(_label);
+                                hideMoeFormMask();
+                                $('[custom-item-form]').hide();
+                            } else {
+                                toastr.error(_data.message);
+                            }
+                        }, 'json');
+                        return false;
+                    },
+                    cancelCustomItem: function () {
+                        hideMoeFormMask();
+                        $('div[moe]').hide();
+                        return false;
+                    },
+                    appendCustomItem: function (_name) {
+                        this.customFields.push({
+                            label: _name,
+                            value: '',
+                            comments: '',
+                        });
+                        Vue.nextTick(function () {
+                            $('.custom-items-container [moe][initialized]').removeAttr('initialized');
+                            initMoes();
+                        });
+                    }
+                }
+            });
+        }
+
+        window.segmentInitializers.<?= $segment->segmentTemplate->internal_name ?> = function() {
+            // any JS can come here
+            // will be run on page-load as well as whenever this segment is refreshed
+        };
+
+        // addMCInitializer('client-sochx', init, '#sochxSection');
+    })();
+</script>

+ 95 - 1
resources/views/app/patient/segment-templates/history_social/summary.php

@@ -1 +1,95 @@
-<h1>Summary for history_social</h1>
+<?php
+
+use App\Models\Point;
+use App\Models\Client;
+use App\Models\Note;
+use App\Models\Segment;
+
+/** @var Client $patient */
+/** @var Note $note */
+/** @var Segment $segment */
+
+$point = Point::getGlobalSingletonOfCategory($patient, 'SOCIAL_HISTORY', true);
+
+$contentData = $point->data;
+
+$fields = [
+    [
+        "Tobacco" => ["Current every day smoker", "Current some day smoker", "Former smoker", "Heavy tobacco smoker", "Light tobacco smoker", "Never smoker", "Smoker, current status unknown", "Unknown if ever smoked "],
+    ],
+    [
+        "Alcohol" => ["Do not drink", "Drink daily", "Frequently drink", "Hx of Alcoholism", "Occasional drink"],
+        "Drug Abuse" => ["IVDU", "Illicit drug use", "No illicit drug use"],
+    ],
+    [
+        "Cardiovascular" => ["Eat healthy meals", "Regular exercise", "Take daily aspirin"],
+        "Safety" => ["Household Smoke detector", "Keep Firearms in home", "Wear seatbelts"],
+    ],
+    [
+        "Sexual Activity" => ["Exposure to STI", "Homosexual encounters", "Not sexually active", "Safe sex practices", "Sexually active"],
+        "Birth Gender" => ["Male", "Female", "Undifferentiated"],
+    ]
+];
+
+$isempty = false;
+if(!$contentData) {
+    $contentData = [
+        "common" => [],
+        "customFields" => [],
+        "comments" => "",
+    ];
+    $isempty = true;
+}
+
+if($isempty) {
+    echo '<span class="text-secondary">No social history in the system</span>';
+}
+else {
+
+    for ($i = 0; $i < count($fields); $i++):
+        foreach($fields[$i] as $head => $values):
+            for($k = 0; $k < count($values); $k++):
+                $fName = $head . '_' . sanitize_field_name($values[$k]);
+                if(@$contentData['common'][$fName]): ?>
+                    <div>
+                        <?= ucwords($head) ?>
+                        <i class="fa fa-arrow-right text-sm text-secondary"></i>
+                        <span class="font-weight-bold"><?= $values[$k] ?></span>
+                        <?php if(@$contentData['common'][$fName . '__comments']): ?>
+                            <span class="text-sm ml-1 text-secondary">(<?= $contentData['common'][$fName . '__comments'] ?>)</span>
+                        <?php endif; ?>
+                    </div>
+                <?php
+                endif;
+            endfor;
+        endforeach;
+    endfor;
+
+    // custom fields
+    if(@$contentData['customFields'] && count($contentData['customFields'])):
+        ?> <div class="mt-2"> <?php
+        for ($i = 0; $i < count($contentData['customFields']); $i++):
+            $item = $contentData['customFields'][$i];
+            if($item['value']): ?>
+                <div>
+                    Custom
+                    <i class="fa fa-arrow-right text-sm text-secondary"></i>
+                    <span class="font-weight-bold"><?= $item['label'] ?></span>
+                    <?php if($item['comments']): ?>
+                        <span class="text-sm ml-1 text-secondary">(<?= $item['comments'] ?>)</span>
+                    <?php endif; ?>
+                </div>
+            <?php
+            endif;
+        endfor;
+        ?> </div> <?php
+    endif;
+
+    if(isset($contentData['comments'])) { ?>
+        <div class="mt-2 mb-1">
+            <div class="font-weight-bold">Comments:</div>
+            <div><?= $contentData['comments'] ?></div>
+        </div>
+    <?php }
+}
+?>

+ 3 - 3
resources/views/app/patient/segment-templates/intake_medications/edit.php

@@ -1,9 +1,9 @@
 <?php
 
 use App\Models\Point;
-use \App\Models\Client;
-use \App\Models\Note;
-use \App\Models\Segment;
+use App\Models\Client;
+use App\Models\Note;
+use App\Models\Segment;
 
 /** @var Client $patient */
 /** @var Note $note */