|
@@ -0,0 +1,221 @@
|
|
|
+<?php
|
|
|
+if(!$contentData) {
|
|
|
+ $contentData = [
|
|
|
+ "items" => [
|
|
|
+ [
|
|
|
+ "title" => "",
|
|
|
+ "strength" => "",
|
|
|
+ "frequency" => "",
|
|
|
+ "detail" => "",
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+}
|
|
|
+$formID = rand(0, 100000);
|
|
|
+?>
|
|
|
+<div id="rxSection">
|
|
|
+ <h3 class="stag-popup-title mb-2 border-bottom-0 pb-1">
|
|
|
+ <span>Current Medications</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">Medication</th>
|
|
|
+ <th class="px-2 text-secondary border-bottom-0">Strength/From</th>
|
|
|
+ <th class="px-2 text-secondary border-bottom-0">Frequency</th>
|
|
|
+ <th class="px-2 text-secondary border-bottom-0 w-35">Detail</th>
|
|
|
+ <th class="px-2 text-secondary border-bottom-0"></th>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <tr v-for="(item, index) in items">
|
|
|
+ <td>
|
|
|
+ <input type="text" :data-index="index"
|
|
|
+ class="form-control form-control-sm canvas-rx-title"
|
|
|
+ data-field="title" v-model="item.title">
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <input type="text" :data-index="index"
|
|
|
+ class="form-control form-control-sm"
|
|
|
+ data-field="strength" v-model="item.strength">
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <input type="text" :data-index="index"
|
|
|
+ class="form-control form-control-sm"
|
|
|
+ data-field="frequency" v-model="item.frequency">
|
|
|
+ </td>
|
|
|
+ <td><textarea type="text" class="form-control form-control-sm"
|
|
|
+ rx-rte :data-index="index" data-field="detail"
|
|
|
+ v-model="item.detail"></textarea>
|
|
|
+ </td>
|
|
|
+ <td class="px-2">
|
|
|
+ <a href="#" v-on:click.prevent="removeItem(index)"
|
|
|
+ class="on-hover-opaque text-danger mt-1 d-inline-block">
|
|
|
+ <i class="fa fa-trash-alt"></i>
|
|
|
+ </a>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ <div class="form-group my-2">
|
|
|
+ <button type="button" class="btn btn-sm btn-default text-primary border border-primary mr-2"
|
|
|
+ v-on:click.prevent="addItem()"
|
|
|
+ >+ New Entry</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+</div>
|
|
|
+<script>
|
|
|
+ (function() {
|
|
|
+ function init() {
|
|
|
+ window.clientRXApp = new Vue({
|
|
|
+ el: '#rxSection',
|
|
|
+ data: {
|
|
|
+ items: <?= json_encode($contentData['items']) ?>
|
|
|
+ },
|
|
|
+ mounted: function() {
|
|
|
+ this.initRTE();
|
|
|
+ this.initRxAutoSuggest();
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ $data: {
|
|
|
+ handler: function(val, oldVal) {
|
|
|
+ $(this.$el).closest('#rxSection').find('[name="data"]').val(JSON.stringify({
|
|
|
+ items: this.cleanArray(this.items)
|
|
|
+ }));
|
|
|
+ },
|
|
|
+ deep: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ addItem: function() {
|
|
|
+ let self = this;
|
|
|
+ this.items.push({
|
|
|
+ title: '',
|
|
|
+ strength: '',
|
|
|
+ frequency: '',
|
|
|
+ detail: '',
|
|
|
+ });
|
|
|
+ Vue.nextTick(function() {
|
|
|
+ self.initRTE();
|
|
|
+ self.initRxAutoSuggest();
|
|
|
+ $('.canvas-rx-title').last().focus();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ removeItem: function(_index) {
|
|
|
+ this.items.splice(_index, 1);
|
|
|
+ },
|
|
|
+ cleanArray: function(_source) {
|
|
|
+ let plItems = [], plObject = {};
|
|
|
+ for (let x=0; x<_source.length; x++) {
|
|
|
+ plObject = {};
|
|
|
+ for (let y in _source[x]) {
|
|
|
+ if(_source[x].hasOwnProperty(y)) {
|
|
|
+ plObject[y] = _source[x][y];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ plItems.push(plObject);
|
|
|
+ }
|
|
|
+ return plItems;
|
|
|
+ },
|
|
|
+ initRTE: function() {
|
|
|
+ let self = this;
|
|
|
+ $('#rxSection textarea[rx-rte]').each(function() {
|
|
|
+
|
|
|
+ $(this).wrap(
|
|
|
+ $('<div class="rte-holder"/>')
|
|
|
+ .attr('data-shortcuts', '')
|
|
|
+ );
|
|
|
+
|
|
|
+ // give a unique id to this editor instance
|
|
|
+ var editorID = Math.ceil(Math.random() * 99999);
|
|
|
+
|
|
|
+ $('<div data-editor-id="' + editorID + '" data-field="' + this.name + '"/>')
|
|
|
+ .html(this.value)
|
|
|
+ .insertBefore(this);
|
|
|
+
|
|
|
+ let vueField = $(this).attr('data-field'), vueIndex = +$(this).attr('data-index');
|
|
|
+
|
|
|
+ $(this).remove();
|
|
|
+
|
|
|
+ var qe = new Quill('[data-editor-id="' + editorID + '"]', {
|
|
|
+ theme: 'snow',
|
|
|
+ modules: {
|
|
|
+ keyboard: {
|
|
|
+ bindings: {
|
|
|
+ handleEnter: {
|
|
|
+ key: 13,
|
|
|
+ handler: function() {
|
|
|
+ if(!$('.stag-shortcuts:visible').length) return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ var toolbar = $(qe.container).prev('.ql-toolbar');
|
|
|
+
|
|
|
+ // add button for new shortcut
|
|
|
+ var newSCButton = $('<button type="button" tabindex="-1" ' +
|
|
|
+ 'class="btn bg-white btn-sm btn-default text-primary w-auto px-2 border py-0 ' +
|
|
|
+ 'text-sm add-shortcut" data-editor-id="' + editorID + '">+ Shortcut</button>');
|
|
|
+ toolbar.append(newSCButton);
|
|
|
+
|
|
|
+ qe.on('text-change', function() {
|
|
|
+ self.items[vueIndex][vueField] = qe.root.innerHTML;
|
|
|
+ });
|
|
|
+
|
|
|
+ $(qe.container)
|
|
|
+ .find('.ql-editor[contenteditable]')
|
|
|
+ .attr('data-editor-id', editorID)
|
|
|
+ .attr('with-shortcuts', 1);
|
|
|
+
|
|
|
+ });
|
|
|
+ },
|
|
|
+ initRxAutoSuggest: function() {
|
|
|
+ let self = this;
|
|
|
+ $('#rxSection input[type="text"][data-field="title"]:not([ac-initialized])').each(function() {
|
|
|
+ let elem = this,
|
|
|
+ randPart = Math.ceil(Math.random() * 1000000),
|
|
|
+ dynID = 'rx-' + randPart,
|
|
|
+ vueIndex = $(this).attr('data-index');
|
|
|
+ $(elem).attr('id', dynID);
|
|
|
+ var strengthElem = $(elem).closest('tr').find('[data-field="strength"]')[0],
|
|
|
+ dynStrengthsID = 'rx-' + randPart + '-strengths';
|
|
|
+ $(strengthElem).attr('id', dynStrengthsID);
|
|
|
+ $(strengthElem).attr('rx-id', dynID);
|
|
|
+ new window.Def.Autocompleter.Prefetch(dynStrengthsID, []);
|
|
|
+ new window.Def.Autocompleter.Search(dynID,
|
|
|
+ 'https://clinicaltables.nlm.nih.gov/api/rxterms/v3/search?ef=STRENGTHS_AND_FORMS');
|
|
|
+ window.Def.Autocompleter.Event.observeListSelections(dynID, function() {
|
|
|
+ var autocomp = elem.autocomp, acData = autocomp.getSelectedItemData();
|
|
|
+ // console.log('ALIX 1', acData);
|
|
|
+ self.items[vueIndex].title = acData[0].code;
|
|
|
+ var strengths = acData[0].data['STRENGTHS_AND_FORMS'];
|
|
|
+ if (strengths) {
|
|
|
+ strengthElem.autocomp.setListAndField(strengths, '');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ window.Def.Autocompleter.Event.observeListSelections(dynStrengthsID, function() {
|
|
|
+ var autocomp = elem.autocomp, acData = autocomp.getSelectedItemData();
|
|
|
+ // console.log('ALIX 2', acData);
|
|
|
+ self.items[vueIndex].strength = $(strengthElem).val();
|
|
|
+ });
|
|
|
+ $(elem).attr('ac-initialized', 1);
|
|
|
+ $(strengthElem).attr('ac-initialized', 1);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ addMCInitializer('client-rx-{{ $patient->uid }}', init);
|
|
|
+ })();
|
|
|
+</script>
|