Portal Updates (#4897)
[openemr.git] / templates / portal / home.html.twig
blobbfaa3cbcf161b03faa5239e0d09092278d4eaaf2
1 {% extends "portal/base.html.twig" %}
3 {% block head %}
4     {{ parent() }}
6     <link href="../portal/sign/css/signer_modal.css?v={{ assetVersion | attr }}" rel="stylesheet" />
7     <script src="../interface/main/tabs/js/dialog_utils.js?v={{ assetVersion | attr }}"></script>
8     <script src="../portal/sign/assets/signature_pad.umd.js?v={{ assetVersion | attr }}"></script>
9     <script src="../portal/sign/assets/signer_api.js?v={{ assetVersion | attr }}"></script>
11     {% if payment_gateway == 'Stripe' %}
12         <script src="https://js.stripe.com/v3/"></script>
13     {% endif %}
15     {% if payment_gateway == 'AuthorizeNet' %}
16         {% if gateway_mode_production %}
17             <script src="https://js.authorize.net/v1/Accept.js"></script>
18         {% else %}
19             <script src="https://jstest.authorize.net/v1/Accept.js"></script>
20         {% endif %}
21     {% endif %}
23     <script>
24         var cpid = {{ patientID | js_escape }},
25             cuser = {{ user | js_escape }},
26             webRoot = {{ web_root | js_escape }},
27             ptName = {{ patientName | js_escape }},
28             whereto = {{ whereto | js_escape }},
29             webroot_url = webRoot,
30             tab_mode = true,
31             isPortal = 1;
33         function restoreSession() {
34             return true;
35         }
37         function persist(where, portalInit = false) {
38             if (where[0] !== '#') {
39                 return;
40             }
41             whereto = where;
42             fetch('lib/persist.php', {
43                 method: 'POST',
44                 headers: {
45                     'Content-Type': 'application/json',
46                 },
47                 body: JSON.stringify(
48                     {
49                         'csrf_token_form': {{ csrfUtils | js_escape }},
50                         'where': where,
51                         'portal_init': portalInit
52                     }
53                 ),
54             });
55         }
57         $(function () {
58             $('#topNav [data-parent="#cardgroup"]').on('click', (e) => {
59                 persist($(e.target).attr('href'), false);
60             });
62             if ($('body').css('direction') == "rtl") {
63                 $('.float-left').each(function () {
64                     $(this).addClass('float-right').removeClass('float-left');
65                 });
66                 $('.dropdown-menu-right').each(function () {
67                     $(this).removeClass('dropdown-menu-right');
68                 });
69                 $('.dropdown-menu-md-right').each(function () {
70                     $(this).removeClass('dropdown-menu-md-right');
71                 });
72             }
74             $("#profilereport").load("get_profile.php", {}, function () {
75                 $("table").addClass("table table-sm");
76                 $(".demographics td").removeClass("label");
77                 $(".demographics td").addClass("bold");
78                 $(".insurance table").addClass("table-sm table-striped");
79                 $("#editDems").click(function () {
80                     showProfileModal()
81                 });
82             });
84             $("#medicationlist").load("./get_medications.php", {}, function () {
85             });
87             $("#labresults").load("./get_lab_results.php", {}, function () {
88             });
90             $("#amendmentslist").load("./get_amendments.php", {}, function () {
91             });
93             $("#problemslist").load("./get_problems.php", {}, function () {
94             });
96             $("#allergylist").load("./get_allergies.php", {}, function () {
97             });
99             $("#reports").load("./report/portal_patient_report.php?pid=" + {{ patientID | js_url }}, {}, function () {
101             });
103             {% if portal_two_payments %}
104             $("#payment").load("./portal_payment.php", {}, function () {
105             });
106             {% endif %}
108             $(".generateDoc_download").click(function () {
109                 $("#doc_form").submit();
110             });
112             function showProfileModal() {
113                 var title = {{ 'Profile Edits Red = Charted Values and Blue = Patient Edits' | xlj }};
115                 var params = {
116                     buttons: [{
117                         text: {{ 'Help' | xlj }},
118                         close: false,
119                         style: 'info',
120                         id: 'formHelp'
121                     },
122                         {
123                             text: {{ 'Cancel' | xlj }},
124                             close: true,
125                             style: 'default'
126                         },
127                         {
128                             text: {{ 'Revert Edits' | xlj }},
129                             close: false,
130                             style: 'danger',
131                             id: 'replaceAllButton'
132                         },
133                         {
134                             text: {{ 'Submit Changes' | xlj }},
135                             close: false,
136                             style: 'success',
137                             id: 'donePatientButton'
138                         }],
139                     sizeHeight: 'full',
140                     allowDrag: false,
141                     onClosed: 'reload',
142                     resolvePromiseOn: 'init',
143                     type: 'GET',
144                     url: webRoot + '/portal/patient/patientdata?pid=' + encodeURIComponent(cpid) + '&user=' + encodeURIComponent(cuser)
145                 };
147                 dlgopen('', '', 'modal-xl', 500, '', title, params).then(function (dialog) {
148                     $('div.modal-body', dialog).addClass('overflow-auto');
149                 });
150             }
152             function saveProfile() {
153                 page.updateModel();
154             }
156             var gowhere = {{ whereto | js_escape }};
158             $(gowhere).collapse('show');
160             $('#cardgroup').on('hide.bs.collapse', '.show', function (e) {
161                 let target = this.attributes.id.nodeValue;
162                 if (whereto.includes(target)) {
163                     whereto = '';
164                     return false;
165                 }
166             });
168             $('#popwait').addClass('d-none');
170             $('#callccda').click(function () {
171                 $('#popwait').removeClass('d-none');
172             });
173         });
175         function editAppointment(mode, deid) {
176             let mdata = {};
177             let title = '';
179             if (mode === 'add') {
180                 title = {{ 'Request New Appointment' | xlj }};
181                 mdata = {
182                     pid: deid
183                 };
184             } else if (mode === 'recurring') {
185                 let msg = {{ 'A Recurring Appointment. Please contact your appointment desk for any changes.' | xlj }};
186                 signerAlertMsg(msg, 8000);
187                 return false;
188             } else {
189                 title = {{ 'Edit Appointment' | xlj }};
190                 mdata = {
191                     eid: deid
192                 };
193             }
195             var params = {
196                 dialogId: 'editpop',
197                 buttons: [{text: 'Cancel', close: true, style: 'btn-sm btn-secondary'}],
198                 allowDrag: false,
199                 size: 800,
200                 title: title,
201                 type: "GET",
202                 url: './add_edit_event_user.php',
203                 data: mdata
204             };
205             /*
206             * A couple notes on dialog.ajax .alert etc.
207             * opener is not required. library will handle for you.
208             * these run in the same scope as calling script.
209             * so same styles, dependencies are in scope.
210             * a promise is returned for doing other neat stuff.
211             *
212             * */
213             dialog.ajax(params);
214         }
216         function changeCredentials(e) {
217             title = {{ 'Please Enter New Credentials' | xlj }};
218             dlgopen("./account/index_reset.php", '', 575, 600, null, title, {});
219         }
221         {% if isEasyPro %}
223         $("#pro").load("./get_pro.php", {}, function () {
224         });
226         function writeResult(score, stdErr, assessmentOID) {
227             $.ajax({
228                 url: '../library/ajax/easipro_util.php',
229                 data: {
230                     'csrf_token_form': {{ csrfUtils | js_escape }},
231                     'function': 'record_result',
232                     'score': score,
233                     'stdErr': stdErr,
234                     'assessmentOID': assessmentOID
235                 },
236                 type: 'POST',
237                 dataType: 'script'
238             });
239         }
241         function selectResponse(obj, assessmentOID) {
242             $.ajax({
243                 url: '../library/ajax/easipro_util.php',
244                 type: "POST",
245                 data: {
246                     'csrf_token_form': {{ csrfUtils | js_escape }},
247                     'function': 'select_response',
248                     'assessmentOID': assessmentOID,
249                     'ItemResponseOID': obj.name,
250                     'Response': +obj.id
251                 },
252                 dataType: "json",
253                 success: function (data) {
254                     if (data.DateFinished != '') {
255                         document.getElementById("Content").innerHTML = jsText({{ 'You have finished the assessment.' | xlj }}) + "<br /> " + jsText({{ 'Thank you' | xlj }});
256                         document.getElementById("asst_" + assessmentOID).innerHTML = "<i class='fa fa-check-circle'></i>";
257                         document.getElementById("asst_status_" + assessmentOID).innerHTML = "completed";
258                         $.ajax({
259                             url: '../library/ajax/easipro_util.php',
260                             type: "POST",
261                             data: {
262                                 'csrf_token_form': {{ csrfUtils | js_escape }},
263                                 'function': 'collect_results',
264                                 'assessmentOID': assessmentOID
265                             },
266                             dataType: "json",
267                             success: function (data) {
268                                 writeResult(data.Items[0].Theta, data.Items[0].StdError, assessmentOID);
269                             }
270                         });
271                         return
272                     }
274                     var screen = "";
275                     for (var j = 0; j < data.Items[0].Elements.length; j++) {
276                         if (typeof (data.Items[0].Elements[j].Map) == 'undefined') {
277                             screen = `<div style="height: 30px>${data.Items[0].Elements[j].Description}</div>`
278                         } else {
279                             for (var k = 0; k < data.Items[0].Elements[j].Map.length; k++) {
280                                 screen = `<div style="height: 50px"><input type="button" class="btn-submit" id="${data.Items[0].Elements[j].Map[k].Value}" name="${data.Items[0].Elements[j].Map[k].ItemResponseOID}" value="${data.Items[0].Elements[j].Map[k].Description}" onclick=selectResponse(this,${assessmentOID}) /></div>`;
281                             }
282                         }
283                     }
284                     document.getElementById("Content").innerHTML = screen;
285                 },
286                 error: function (jqXHR, textStatus, errorThrown) { // document.write(jqXHR.responseText + ':' + textStatus + ':' + errorThrown);
287                     alert("An error occurred");
288                 }
289             });
290         }
292         function startAssessment(param, assessmentOID) {
293             param.innerHTML = "<i class='fa fa-circle-notch fa-spin'></i> " + jsText({{ 'Loading' | xlj }});
295             $.ajax({
296                 url: '../library/ajax/easipro_util.php',
297                 type: "POST",
298                 data: {
299                     'csrf_token_form': {{ csrfUtils | js_escape }},
300                     'function': 'start_assessment',
301                     'assessmentOID': assessmentOID
302                 },
303                 dataType: "json",
304                 success: function (data) {
305                     var screen = "";
306                     for (var j = 0; j < data.Items[0].Elements.length; j++) {
307                         if (typeof (data.Items[0].Elements[j].Map) == 'undefined') {
308                             screen = `<div style="height: 30px">${data.Items[0].Elements[j].Description}</div>`;
309                         } else {
310                             for (var k = 0; k < data.Items[0].Elements[j].Map.length; k++) {
311                                 screen = `<div style="height: 50px"><input type="button" class='btn-submit' id="${data.Items[0].Elements[j].Map[k].Value}" name="${data.Items[0].Elements[j].Map[k].ItemResponseOID}" value="${data.Items[0].Elements[j].Map[k].Description}" onclick=selectResponse(this, ${assessmentOID})/></div>`;
312                             }
313                         }
314                     }
316                     document.getElementById("Content").innerHTML = screen;
318                     param.innerHTML = jsText({{ 'Start Assessment' | xlj }});
319                 },
320                 error: function (jqXHR, textStatus, errorThrown) {
321                     param.innerHTML = jsText({{ 'Start Assessment' | xlj }});
323                     // document.write(jqXHR.responseText);
324                     alert("An error occurred");
325                 }
326             });
327         }
329         {% endif %}
330     </script>
331     {{ fireEvent(eventNames.scriptsRenderPre) }}
333 {% endblock %}
335 {% block pagetitle %}
336     {{ pagetitle | text }}
337 {% endblock %}
339 {% block header %}
340     {% include "portal/header.html.twig" %}
341 {% endblock %}
343 {% block content %}
345     <section class="flex-column accordion" id="cardgroup">
346         <div id="popwait" class="alert alert-warning d-none">
347             <strong>{{ 'Working!' | xlt }}</strong>
348             {{ 'Please wait...' | xlt }}</div>
350         <div class="collapse overflow-auto" data-parent="#cardgroup" id="lists">
351             <div class="card">
352                 <header class="card-header bg-primary text-light">{{ 'Medications' | xlt }}</header>
353                 <div id="medicationlist" class="card-body bg-light"></div>
354             </div>
355             <div class="card">
356                 <header class="card-header bg-primary text-light">{{ 'Medications Allergy List' | xlt }}</header>
357                 <div id="allergylist" class="card-body bg-light"></div>
358             </div>
359             <div class="card">
360                 <header class="card-header bg-primary text-light">{{ 'Issues List' | xlt }}</header>
361                 <div id="problemslist" class="card-body bg-light"></div>
362             </div>
363             <div class="card">
364                 <header class="card-header bg-primary text-light">{{ 'Amendment List' | xlt }}</header>
365                 <div id="amendmentslist" class="card-body bg-light"></div>
366             </div>
367             <div class="card">
368                 <header class="card-header bg-primary text-light">{{ 'Lab Results' | xlt }}</header>
369                 <div id="labresults" class="card-body bg-light"></div>
370             </div>
371         </div>
373         <div class="card collapse overflow-auto" data-parent="#cardgroup" id="reportcard">
374             <header class="card-header bg-primary text-light">{{ 'Reports' | xlt }}</header>
375             <div id="reports" class="card-body"></div>
376         </div>
378         <div class="card collapse" data-parent="#cardgroup" id="profilecard">
379             <div id="profilereport" class="card-body bg-light"></div>
380         </div>
382         <div class="collapse" data-parent="#cardgroup" id="documentscard">
383             <div class="card">
384                 <div id="patdocuments" class="card-body">
385                     <iframe src="{{ web_root | attr }}/portal/patient/onsitedocuments?pid={{ patientID | attr_url }}" class="w-100 vh-100 border-0"></iframe>
386                 </div>
387             </div>
388         </div>
390         <div class="collapse" data-parent="#cardgroup" id="secure-msgs-card">
391             <div class="card">
392                 <div id="secure-msgs" class="card-body">
393                     <iframe src="{{ web_root | attr }}/portal/messaging/messages.php" class="w-100 vh-100 border-0"></iframe>
394                 </div>
395             </div>
396         </div>
398         {% if allow_portal_appointments %}
399             <div class="collapse mt-2 overflow-auto" data-parent="#cardgroup" id="appointmentcard">
400                 <div class="container-fluid">
401                     <h3 class="text-center">{{ 'Appointments' | xlt }}</h3>
402                     <div class="row">
403                         {% if appointments|length > 0 %}
404                             {% for appt in appointments %}
405                                 {% include 'portal/appointment-item.html.twig' with {appt: appt} %}
406                             {% endfor %}
408                             {% if appointmentLimit == appointmentCount %}
409                                 <p>{{ 'Display limit reached' | xlt }}
410                                     <br>
411                                     {{ 'More appointments may exist' | xlt }}</p>
412                             {% endif %}
413                         {% else %}
414                             <h3 class='text-center'>{{ 'No Appointments' | xlt }}</h3>
415                         {% endif %}
417                     </div>
418                     <div class="mb-3">
419                         <a class='btn btn-primary btn-block' href='#' onclick="editAppointment('add',{{ patientID | attr_js }})">{{ 'Schedule A New Appointment' | xlt }}</a>
420                     </div>
421                 </div>
422             </div>
423             <!-- /.row -->
424         {% endif %}
426         {% if portal_two_payments %}
427             <div class="collapse overflow-auto" data-parent="#cardgroup" id="paymentcard">
428                 <div class="card">
429                     <header class="card-header bg-primary text-light">{{ 'Payments' | xlt }}</header>
430                     <div id="payment" class="card-body bg-light"></div>
431                 </div>
432             </div>
433         {% endif %}
435         {% if allow_portal_chat %}
436             <div class="collapse overflow-auto" data-parent="#cardgroup" id="messagescard">
437                 <div class="card pt-0 pb-0">
438                     <header class="card-header bg-primary text-light">{{ 'Secure Chat' | xlt }}</header>
439                     <div id="chat" class="card-body p-0 overflow-auto">
440                         <iframe src="./messaging/secure_chat.php" class="w-100" style="height: calc(100vh - 120px);"></iframe>
441                     </div>
442                 </div>
443             </div>
444         {% endif %}
446         {% if portal_onsite_document_download %}
447             <div class="card collapse overflow-auto" data-parent="#cardgroup" id="downloadcard">
448                 <header class="card-header bg-primary text-light">{{ 'Download Documents' | xlt }}</header>
449                 <div id="docsdownload" class="card-body">
450                     <div>
451                         <span class="text">{{ 'Download all patient documents' | xlt }}</span>
452                         <form name='doc_form' id='doc_form' action='./get_patient_documents.php' method='post'>
453                             <input type="button" class="generateDoc_download" value="{{ 'Download' | xla }}" />
454                         </form>
455                     </div>
456                 </div>
457                 <!-- /.card-body -->
458             </div>
459         {% endif %}
461         {% if portal_two_ledger %}
462             <div class="collapse overflow-auto" data-parent="#cardgroup" id="ledgercard">
463                 <div class="card">
464                     <header class="card-header bg-primary text-light">{{ 'Ledger' | xlt }}</header>
465                     <div id="patledger" class="card-body">
466                         <iframe src="./report/pat_ledger.php" class="w-100 vh-100 border-0"></iframe>
467                     </div>
468                 </div>
469             </div>
470         {% endif %}
472         {% if isEasyPro %}
473             <div class="card collapse overflow-auto" data-parent="#cardgroup" id="procard">
474                 <header class="card-header bg-primary text-light">{{ 'Patient Reported Outcomes' | xlt }}</header>
475                 <div id="pro" class="card-body bg-light"></div>
476             </div>
477         {% endif %}
479         {{ fireEvent(eventNames.sectionRenderPost) }}
481     </section>
482 {% endblock %}