5 * Patient summary screen.
8 * @link http://www.open-emr.org
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Sharon Cohen <sharonco@matrix.co.il>
11 * @author Stephen Waite <stephen.waite@cmsvt.com>
12 * @author Ranganath Pathak <pathak@scrs1.org>
13 * @author Tyler Wrenn <tyler@tylerwrenn.com>
14 * @author Robert Down <robertdown@live.com>
15 * @copyright Copyright (c) 2017-2020 Brady Miller <brady.g.miller@gmail.com>
16 * @copyright Copyright (c) 2017 Sharon Cohen <sharonco@matrix.co.il>
17 * @copyright Copyright (c) 2018-2020 Stephen Waite <stephen.waite@cmsvt.com>
18 * @copyright Copyright (c) 2018 Ranganath Pathak <pathak@scrs1.org>
19 * @copyright Copyright (c) 2020 Tyler Wrenn <tyler@tylerwrenn.com>
20 * @copyright Copyright (c) 2021-2022 Robert Down <robertdown@live.com
21 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
24 require_once("../../globals.php");
25 require_once("$srcdir/lists.inc.php");
26 require_once("$srcdir/patient.inc.php");
27 require_once("$srcdir/options.inc.php");
28 require_once("../history/history.inc.php");
29 require_once("$srcdir/clinical_rules.php");
30 require_once("$srcdir/group.inc.php");
31 require_once(__DIR__
. "/../../../library/appointments.inc.php");
33 use OpenEMR\Billing\EDI270
;
34 use OpenEMR\Common\Acl\AclMain
;
35 use OpenEMR\Common\Csrf\CsrfUtils
;
36 use OpenEMR\Common\Session\SessionUtil
;
37 use OpenEMR\Common\Twig\TwigContainer
;
38 use OpenEMR\Core\Header
;
39 use OpenEMR\Events\Patient\Summary\Card\RenderEvent
as CardRenderEvent
;
40 use OpenEMR\Events\Patient\Summary\Card\SectionEvent
;
41 use OpenEMR\Events\Patient\Summary\Card\RenderModel
;
42 use OpenEMR\Events\Patient\Summary\Card\CardInterface
;
43 use OpenEMR\Events\PatientDemographics\ViewEvent
;
44 use OpenEMR\Events\PatientDemographics\RenderEvent
;
45 use OpenEMR\FHIR\SMART\SmartLaunchController
;
46 use OpenEMR\Menu\PatientMenuRole
;
47 use OpenEMR\OeUI\OemrUI
;
48 use OpenEMR\Patient\Cards\PortalCard
;
49 use OpenEMR\Reminder\BirthdayReminder
;
50 use OpenEMR\Services\AllergyIntoleranceService
;
51 use OpenEMR\Services\ConditionService
;
52 use OpenEMR\Services\ImmunizationService
;
53 use OpenEMR\Services\PatientIssuesService
;
54 use OpenEMR\Services\PatientService
;
55 use Symfony\Component\EventDispatcher\EventDispatcher
;
57 $twig = new TwigContainer(null, $GLOBALS['kernel']);
59 // Set session for pid (via setpid). Also set session for encounter (if applicable)
60 if (isset($_GET['set_pid'])) {
61 require_once("$srcdir/pid.inc.php");
62 setpid($_GET['set_pid']);
63 $ptService = new PatientService();
64 $newPatient = $ptService->findByPid($pid);
65 $ptService->touchRecentPatientList($newPatient);
66 if (isset($_GET['set_encounterid']) && ((int)$_GET['set_encounterid'] > 0)) {
67 $encounter = (int)$_GET['set_encounterid'];
68 SessionUtil
::setSession('encounter', $encounter);
72 // Note: it would eventually be a good idea to move this into
73 // it's own module that people can remove / add if they don't
74 // want smart support in their system.
75 $smartLaunchController = new SMARTLaunchController($GLOBALS["kernel"]->getEventDispatcher());
76 $smartLaunchController->registerContextEvents();
79 * @var EventDispatcher
81 $ed = $GLOBALS['kernel']->getEventDispatcher();
83 $active_reminders = false;
84 $all_allergy_alerts = false;
85 if ($GLOBALS['enable_cdr']) {
87 if ($GLOBALS['enable_allergy_check'] && $GLOBALS['enable_alert_log']) {
88 //Check for new allergies conflicts and throw popup if any exist(note need alert logging to support this)
89 $new_allergy_alerts = allergy_conflict($pid, 'new', $_SESSION['authUser']);
90 if (!empty($new_allergy_alerts)) {
92 foreach ($new_allergy_alerts as $new_allergy_alert) {
93 $pod_warnings .= js_escape($new_allergy_alert) . ' + "\n"';
95 $allergyWarningMessage = '<script>alert(' . xlj('WARNING - FOLLOWING ACTIVE MEDICATIONS ARE ALLERGIES') . ' + "\n" + ' . $pod_warnings . ')</script>';
99 if ((empty($_SESSION['alert_notify_pid']) ||
($_SESSION['alert_notify_pid'] != $pid)) && isset($_GET['set_pid']) && $GLOBALS['enable_cdr_crp']) {
100 // showing a new patient, so check for active reminders and allergy conflicts, which use in active reminder popup
101 $active_reminders = active_alert_summary($pid, "reminders-due", '', 'default', $_SESSION['authUser'], true);
102 if ($GLOBALS['enable_allergy_check']) {
103 $all_allergy_alerts = allergy_conflict($pid, 'all', $_SESSION['authUser'], true);
106 SessionUtil
::setSession('alert_notify_pid', $pid);
107 // can not output html until after above setSession call
108 if (!empty($allergyWarningMessage)) {
109 echo $allergyWarningMessage;
112 //Check to see is only one insurance is allowed
113 if ($GLOBALS['insurance_only_one']) {
114 $insurance_array = array('primary');
116 $insurance_array = array('primary', 'secondary', 'tertiary');
119 function print_as_money($money)
121 preg_match("/(\d*)\.?(\d*)/", $money, $moneymatches);
122 $tmp = wordwrap(strrev($moneymatches[1]), 3, ",", 1);
123 $ccheck = strrev($tmp);
124 if ($ccheck[0] == ",") {
125 $tmp = substr($ccheck, 1, strlen($ccheck) - 1);
128 if ($moneymatches[2] != "") {
129 return "$ " . strrev($tmp) . "." . $moneymatches[2];
131 return "$ " . strrev($tmp);
135 // get an array from Photos category
136 function pic_array($pid, $picture_directory)
139 $sql_query = "select documents.id from documents join categories_to_documents " .
140 "on documents.id = categories_to_documents.document_id " .
141 "join categories on categories.id = categories_to_documents.category_id " .
142 "where categories.name like ? and documents.foreign_id = ? and documents.deleted = 0";
143 if ($query = sqlStatement($sql_query, array($picture_directory, $pid))) {
144 while ($results = sqlFetchArray($query)) {
145 array_push($pics, $results['id']);
152 // Get the document ID's in a specific catg.
153 // this is only used in one place, here for id photos
154 function get_document_by_catg($pid, $doc_catg, $limit = 1)
158 if ($pid and $doc_catg) {
159 $query = sqlStatement("SELECT d.id, d.date, d.url
160 FROM documents AS d, categories_to_documents AS cd, categories AS c
161 WHERE d.foreign_id = ?
162 AND cd.document_id = d.id
163 AND c.id = cd.category_id
165 ORDER BY d.date DESC LIMIT " . escape_limit($limit), array($pid, $doc_catg));
167 while ($result = sqlFetchArray($query)) {
168 $results[] = $result['id'];
170 return ($results ??
false);
173 function isPortalEnabled(): bool
176 !$GLOBALS['portal_onsite_two_enable']
184 function isPortalSiteAddressValid(): bool
187 // maybe can use filter_var() someday but the default value in GLOBALS
188 // fails with FILTER_VALIDATE_URL
189 !isset($GLOBALS['portal_onsite_two_address'])
197 function isPortalAllowed($pid): bool
201 $portalStatus = sqlQuery("SELECT allow_patient_portal FROM patient_data WHERE pid = ?", [$pid]);
202 if ($portalStatus['allow_patient_portal'] == 'YES') {
208 function isApiAllowed($pid): bool
212 $apiStatus = sqlQuery("SELECT prevent_portal_apps FROM patient_data WHERE pid = ?", [$pid]);
213 if (strtoupper($apiStatus['prevent_portal_apps'] ??
'') != 'YES') {
219 function areCredentialsCreated($pid): bool
222 $credentialsCreated = sqlQuery("SELECT date_created FROM `patient_access_onsite` WHERE `pid`=?", [$pid]);
223 if ($credentialsCreated['date_created'] ??
null) {
230 function isContactEmail($pid): bool
234 $email = sqlQuery("SELECT email, email_direct FROM patient_data WHERE pid = ?", [$pid]);
235 if (!empty($email['email']) ||
!empty($email['email_direct'])) {
241 function isEnforceSigninEmailPortal(): bool
244 $GLOBALS['enforce_signin_email']
252 function deceasedDays($days_deceased)
254 $deceased_days = intval($days_deceased['days_deceased'] ??
'');
255 if ($deceased_days == 0) {
256 $num_of_days = xl("Today");
257 } elseif ($deceased_days == 1) {
258 $num_of_days = $deceased_days . " " . xl("day ago");
259 } elseif ($deceased_days > 1 && $deceased_days < 90) {
260 $num_of_days = $deceased_days . " " . xl("days ago");
261 } elseif ($deceased_days >= 90 && $deceased_days < 731) {
262 $num_of_days = "~" . round($deceased_days / 30) . " " . xl("months ago"); // function intdiv available only in php7
263 } elseif ($deceased_days >= 731) {
264 $num_of_days = xl("More than") . " " . round($deceased_days / 365) . " " . xl("years ago");
267 if (strlen($days_deceased['date_deceased'] ??
'') > 10 && $GLOBALS['date_display_format'] < 1) {
268 $deceased_date = substr($days_deceased['date_deceased'], 0, 10);
270 $deceased_date = oeFormatShortDate($days_deceased['date_deceased'] ??
'');
273 return xlt("Deceased") . " - " . text($deceased_date) . " (" . text($num_of_days) . ")";
276 $deceased = is_patient_deceased($pid);
279 // Display image in 'widget style'
280 function image_widget($doc_id, $doc_catg)
282 global $pid, $web_root;
283 $docobj = new Document($doc_id);
284 $image_file = $docobj->get_url_file();
285 $image_file_name = $docobj->get_name();
286 $image_width = $GLOBALS['generate_doc_thumb'] == 1 ?
'' : 'width=100';
287 $extension = substr($image_file_name, strrpos($image_file_name, "."));
288 $viewable_types = array('.png', '.jpg', '.jpeg', '.png', '.bmp', '.PNG', '.JPG', '.JPEG', '.PNG', '.BMP');
289 if (in_array($extension, $viewable_types)) { // extension matches list
290 $to_url = "<td> <a href = '$web_root" .
291 "/controller.php?document&retrieve&patient_id=" . attr_url($pid) . "&document_id=" . attr_url($doc_id) . "&as_file=false&original_file=true&disable_exit=false&show_original=true'" .
292 " onclick='top.restoreSession();' class='image_modal'>" .
293 " <img src = '$web_root" .
294 "/controller.php?document&retrieve&patient_id=" . attr_url($pid) . "&document_id=" . attr_url($doc_id) . "&as_file=false'" .
295 " $image_width alt='" . attr($doc_catg) . ":" . attr($image_file_name) . "'> </a> </td> <td class='align-middle'>" .
296 text($doc_catg) . '<br /> ' . text($image_file_name) . "</td>";
298 $to_url = "<td> <a href='" . $web_root . "/controller.php?document&retrieve" .
299 "&patient_id=" . attr_url($pid) . "&document_id=" . attr_url($doc_id) . "'" .
300 " onclick='top.restoreSession()' class='btn btn-primary btn-sm'>" .
302 xlt("View") . "</a> " .
303 text("$doc_catg - $image_file_name") .
309 echo "</tr></table>";
312 // Determine if the Vitals form is in use for this site.
313 $tmp = sqlQuery("SELECT count(*) AS count FROM registry WHERE directory = 'vitals' AND state = 1");
314 $vitals_is_registered = $tmp['count'];
316 // Get patient/employer/insurance information.
318 $result = getPatientData($pid, "*, DATE_FORMAT(DOB,'%Y-%m-%d') as DOB_YMD");
319 $result2 = getEmployerData($pid);
320 $result3 = getInsuranceData(
325 DATE_FORMAT(`date`,'%Y-%m-%d') as effdate,
326 DATE_FORMAT(`date_end`,'%Y-%m-%d') as effdate_end"
329 if (!empty($result3['provider'])) { // Use provider in case there is an ins record w/ unassigned insco
330 $insco_name = getInsuranceProvider($result3['provider']);
333 $arrOeUiSettings = array(
334 'page_id' => 'core.mrd',
335 'heading_title' => xl('Medical Record Dashboard'),
336 'include_patient_name' => true,
337 'expandable' => true,
338 'expandable_files' => array(), //all file names need suffix _xpd
339 'action' => "", //conceal, reveal, search, reset, link or back
340 'action_title' => "",
341 'action_href' => "", //only for actions - reset, link or back
342 'show_help_icon' => true,
343 'help_file_name' => "medical_dashboard_help.php"
345 $oemr_ui = new OemrUI($arrOeUiSettings);
352 Header
::setupHeader(['common','utility']);
353 require_once("$srcdir/options.js.php");
356 // Process click on diagnosis for referential cds popup.
357 function referentialCdsClick(codetype
, codevalue
) {
358 top
.restoreSession();
359 // Force a new window instead of iframe to address cross site scripting potential
360 dlgopen('../education.php?type=' +
encodeURIComponent(codetype
) +
'&code=' +
encodeURIComponent(codevalue
), '_blank', 1024, 750,true);
363 function oldEvt(apptdate
, eventid
) {
364 let title
= <?php
echo xlj('Appointments'); ?
>;
365 dlgopen('../../main/calendar/add_edit_event.php?date=' +
encodeURIComponent(apptdate
) +
'&eid=' +
encodeURIComponent(eventid
), '_blank', 800, 500, '', title
);
368 function advdirconfigure() {
369 dlgopen('advancedirectives.php', '_blank', 400, 500);
372 function refreshme() {
373 top
.restoreSession();
377 // Process click on Delete link.
378 function deleteme() { // @todo don't think this is used any longer!!
379 dlgopen('../deleter.php?patient=' +
<?php
echo js_url($pid); ?
> +
'&csrf_token_form=' +
<?php
echo js_url(CsrfUtils
::collectCsrfToken()); ?
>, '_blank', 500, 450, '', '', {
388 // Called by the deleteme.php window on a successful delete.
389 function imdeleted() {
394 let title
= <?php
echo xlj('Appointments'); ?
>;
395 let url
= '../../main/calendar/add_edit_event.php?patientid=' +
<?php
echo js_url($pid); ?
>;
396 dlgopen(url
, '_blank', 800, 500, '', title
);
401 top
.restoreSession();
402 location
.href
= '../../weno/indexrx.php'
405 function toggleIndicator(target
, div
) {
406 // <i id="show_hide" class="fa fa-lg small fa-eye-slash" title="Click to Hide"></i>
407 $mode = $
(target
).find(".indicator").text();
408 if ($mode == <?php
echo xlj('collapse'); ?
>) {
409 $
(target
).find(".indicator").text(<?php
echo xlj('expand'); ?
>);
411 $
.post("../../../library/ajax/user_settings.php", {
414 csrf_token_form
: <?php
echo js_escape(CsrfUtils
::collectCsrfToken()); ?
>
417 $
(target
).find(".indicator").text(<?php
echo xlj('collapse'); ?
>);
419 $
.post("../../../library/ajax/user_settings.php", {
422 csrf_token_form
: <?php
echo js_escape(CsrfUtils
::collectCsrfToken()); ?
>
427 // edit prescriptions dialog.
428 // called from stats.php.
430 function editScripts(url
) {
431 var AddScript
= function() {
432 var __this
= $
(this
);
433 __this
.find("#clearButton").css("display", "");
434 __this
.find("#backButton").css("display", "");
435 __this
.find("#addButton").css("display", "none");
437 var iam
= top
.frames
.editScripts
;
438 iam
.location
.href
= '<?php echo $GLOBALS['webroot
'] ?>/controller.php?prescription&edit&id=0&pid=' +
<?php
echo js_url($pid); ?
>;
440 var ListScripts
= function() {
441 var __this
= $
(this
);
442 __this
.find("#clearButton").css("display", "none");
443 __this
.find("#backButton").css("display", "none");
444 __this
.find("#addButton").css("display", "");
445 var iam
= top
.frames
.editScripts
446 iam
.location
.href
= '<?php echo $GLOBALS['webroot
'] ?>/controller.php?prescription&list&id=' +
<?php
echo js_url($pid); ?
>;
449 let title
= <?php
echo xlj('Prescriptions'); ?
>;
450 let w
= 960; // for weno width
452 dlgopen(url
, 'editScripts', w
, 400, '', '', {
454 text
: <?php
echo xlj('Add'); ?
>,
457 class: 'btn-primary btn-sm',
461 text
: <?php
echo xlj('Clear'); ?
>,
464 style
: 'display:none;',
465 class: 'btn-primary btn-sm',
469 text
: <?php
echo xlj('Back'); ?
>,
472 style
: 'display:none;',
473 class: 'btn-primary btn-sm',
477 text
: <?php
echo xlj('Quit'); ?
>,
480 class: 'btn-secondary btn-sm'
483 onClosed
: 'refreshme',
486 dialogId
: 'editscripts',
493 * async function fetchHtml(...)
496 * @param {boolean} embedded
497 * @param {boolean} sessionRestore
500 async
function fetchHtml(url
, embedded
= false, sessionRestore
= false) {
501 if (sessionRestore
=== true) {
502 // restore cookie before fetch.
503 top
.restoreSession();
505 let csrf
= new FormData
;
507 csrf
.append("csrf_token_form", <?php
echo js_escape(CsrfUtils
::collectCsrfToken()); ?
>);
508 if (embedded
=== true) {
509 // special formatting in certain widgets.
510 csrf
.append("embeddedScreen", true);
513 const response
= await
fetch(url
, {
515 credentials
: 'same-origin',
518 return await response
.text();
522 * async function placeHtml(...) will await fetch of html then place in divId.
523 * This function will return a promise for use to init various items regarding
524 * inserted HTML if needed.
525 * If divId does not exist, then will skip.
529 * @param {string} divId id
530 * @param {boolean} embedded
531 * @param {boolean} sessionRestore
532 * @returns {object} promise
534 async
function placeHtml(url
, divId
, embedded
= false, sessionRestore
= false) {
535 const contentDiv
= document
.getElementById(divId
);
537 await
fetchHtml(url
, embedded
, sessionRestore
).then(fragment
=> {
538 contentDiv
.innerHTML
= fragment
;
543 if (typeof load_location
=== 'undefined') {
544 function load_location(location
) {
545 top
.restoreSession();
546 document
.location
= location
;
551 var msg_updation
= '';
553 if ($GLOBALS['erx_enable']) {
554 $soap_status = sqlStatement("select soap_import_status,pid from patient_data where pid=? and soap_import_status in ('1','3')", array($pid));
555 while ($row_soapstatus = sqlFetchArray($soap_status)) { ?
>
556 top
.restoreSession();
557 let reloadRequired
= false;
560 url
: "../../soap_functions/soap_patientfullmedication.php",
563 patient
: <?php
echo js_escape($row_soapstatus['pid']); ?
>,
566 success
: function(thedata
) {
567 if (!thedata
.includes("Nothing")) {
568 reloadRequired
= true;
570 msg_updation +
= thedata
;
577 top
.restoreSession();
580 url
: "../../soap_functions/soap_allergy.php",
583 patient
: <?php
echo js_escape($row_soapstatus['pid']); ?
>,
586 success
: function(thedata
) {
587 if (!thedata
.includes("Nothing")) {
588 reloadRequired
= true;
590 msg_updation +
= "\n" + thedata
;
597 if (reloadRequired
) {
598 document
.location
.reload();
602 if ($GLOBALS['erx_import_status_message']) { ?
>
612 placeHtml("stats.php", "stats_div", true);
613 placeHtml("pnotes_fragment.php", 'pnotes_ps_expand').then(() => {
614 // must be delegated event!
615 $
(this
).on("click", ".complete_btn", function() {
617 let csrf
= new FormData
;
618 csrf
.append("csrf_token_form", <?php
echo js_escape(CsrfUtils
::collectCsrfToken()); ?
>);
619 fetch("pnotes_fragment.php?docUpdateId=" +
encodeURIComponent(btn
.attr('data-id')), {
621 credentials
: 'same-origin',
625 placeHtml("pnotes_fragment.php", 'pnotes_ps_expand');
629 placeHtml("disc_fragment.php", "disclosures_ps_expand");
630 placeHtml("labdata_fragment.php", "labdata_ps_expand");
631 placeHtml("track_anything_fragment.php", "track_anything_ps_expand");
632 <?php
if ($vitals_is_registered && AclMain
::aclCheckCore('patients', 'med')) { ?
>
633 // Initialize the Vitals form if it is registered and user is authorized.
634 placeHtml("vitals_fragment.php", "vitals_ps_expand");
637 <?php
if ($GLOBALS['enable_cdr'] && $GLOBALS['enable_cdr_crw']) { ?
>
638 placeHtml("clinical_reminders_fragment.php", "clinical_reminders_ps_expand", true, true).then(() => {
639 // (note need to place javascript code here also to get the dynamic link to work)
640 $
(".medium_modal").on('click', function(e
) {
643 dlgopen('', '', 800, 200, '', '', {
645 text
: <?php
echo xlj('Close'); ?
>,
647 style
: 'secondary btn-sm'
649 onClosed
: 'refreshme',
652 dialogId
: 'demreminder',
654 url
: $
(this
).attr('href')
661 <?php
if ($GLOBALS['enable_cdr'] && $GLOBALS['enable_cdr_prw']) { ?
>
662 placeHtml("patient_reminders_fragment.php", "patient_reminders_ps_expand", false, true);
667 // Initialize for each applicable LBF form.
668 $gfres = sqlStatement("SELECT grp_form_id
669 FROM layout_group_properties
670 WHERE grp_form_id LIKE 'LBF%'
671 AND grp_group_id = ''
674 ORDER BY grp_seq, grp_title");
675 while ($gfrow = sqlFetchArray($gfres)) { ?
>
676 $
(<?php
echo js_escape("#" . $gfrow['grp_form_id'] . "_ps_expand"); ?
>).load("lbf_fragment.php?formname=" +
<?php
echo js_url($gfrow['grp_form_id']); ?
>, {
677 csrf_token_form
: <?php
echo js_escape(CsrfUtils
::collectCsrfToken()); ?
>
682 // modal for dialog boxes
683 $
(".large_modal").on('click', function(e
) {
686 dlgopen('', '', 1000, 600, '', '', {
688 text
: <?php
echo xlj('Close'); ?
>,
690 style
: 'secondary btn-sm'
696 url
: $
(this
).attr('href')
700 $
(".rx_modal").on('click', function(e
) {
703 var title
= <?php
echo xlj('Amendments'); ?
>;
704 dlgopen('', 'editAmendments', 800, 300, '', title
, {
705 onClosed
: 'refreshme',
710 url
: $
(this
).attr('href')
714 // modal for image viewer
715 $
(".image_modal").on('click', function(e
) {
718 dlgopen('', '', 400, 300, '', <?php
echo xlj('Patient Images'); ?
>, {
723 url
: $
(this
).attr('href')
727 $
(".deleter").on('click', function(e
) {
730 dlgopen('', '', 600, 360, '', '', {
732 text
: <?php
echo xlj('Close'); ?
>,
734 style
: 'secondary btn-sm'
736 //onClosed: 'imdeleted',
741 url
: $
(this
).attr('href')
745 $
(".iframe1").on('click', function(e
) {
748 dlgopen('', '', 350, 300, '', '', {
750 text
: <?php
echo xlj('Close'); ?
>,
752 style
: 'secondary btn-sm'
758 url
: $
(this
).attr('href')
761 // for patient portal
762 $
(".small_modal").on('click', function(e
) {
765 dlgopen('', '', 550, 550, '', '', {
767 text
: <?php
echo xlj('Close'); ?
>,
769 style
: 'secondary btn-sm'
775 url
: $
(this
).attr('href')
779 function openReminderPopup() {
781 dlgopen('', 'reminders', 500, 250, '', '', {
783 text
: <?php
echo xlj('Close'); ?
>,
785 style
: 'secondary btn-sm'
791 url
: $
("#reminder_popup_link").attr('href')
795 <?php
if ($GLOBALS['patient_birthday_alert']) {
796 // To display the birthday alert:
797 // 1. The patient is not deceased
798 // 2. The birthday is today (or in the past depending on global selection)
799 // 3. The notification has not been turned off (or shown depending on global selection) for this year
800 $birthdayAlert = new BirthdayReminder($pid, $_SESSION['authUserID']);
801 if ($birthdayAlert->isDisplayBirthdayAlert()) {
803 // show the active reminder modal
804 dlgopen('', 'bdayreminder', 300, 170, '', false, {
809 url
: $
("#birthday_popup").attr('href')
812 <?php
} elseif ($active_reminders ||
$all_allergy_alerts) { ?
>
815 <?php
} elseif ($active_reminders ||
$all_allergy_alerts) { ?
>
819 // $(".card-title").on('click', "button", (e) => {
820 // console.debug("click");
821 // updateUserVisibilitySetting(e);
826 * Change the preference to expand/collapse a given card.
828 * For the given e element, find the corresponding card body, determine if it is collapsed
829 * or shown, and then save the state to the user preferences via an async fetch call POST'ing
830 * the updated setting.
832 * @var e element The Button that was clicked to collapse/expand the card
834 async
function updateUserVisibilitySetting(e
) {
835 const targetID
= e
.target
.getAttribute("data-target");
836 const target
= document
.querySelector(targetID
);
837 const targetStr
= targetID
.substring(1);
839 let formData
= new FormData();
840 formData
.append("csrf_token_form", <?php
echo js_escape(CsrfUtils
::collectCsrfToken()); ?
>);
841 formData
.append("target", targetStr
);
842 formData
.append("mode", (target
.classList
.contains("show")) ?
0 : 1);
844 const response
= await
fetch("../../../library/ajax/user_settings.php", {
846 credentials
: 'same-origin',
850 const update
= await response
.text();
854 // Update the User's visibility setting when the card header is clicked
855 function cardTitleButtonClickListener() {
856 const buttons
= document
.querySelectorAll(".card-title button[data-toggle='collapse']");
857 buttons
.forEach((b
) => {
858 b
.addEventListener("click", (e
) => {
859 updateUserVisibilitySetting(e
);
864 // JavaScript stuff to do when a new patient is set.
866 function setMyPatient() {
868 if (isset($_GET['set_pid'])) {
869 $date_of_death = is_patient_deceased($pid);
870 if (!empty($date_of_death)) {
871 $date_of_death = $date_of_death['date_deceased'];
874 parent
.left_nav
.setPatient(<?php
echo js_escape($result['fname'] . " " . $result['lname']) .
875 "," . js_escape($pid) . "," . js_escape($result['pubpid']) . ",'',";
876 if (empty($date_of_death)) {
877 echo js_escape(" " . xl('DOB') . ": " . oeFormatShortDate($result['DOB_YMD']) . " " . xl('Age') . ": " . getPatientAgeDisplay($result['DOB_YMD']));
879 echo js_escape(" " . xl('DOB') . ": " . oeFormatShortDate($result['DOB_YMD']) . " " . xl('Age at death') . ": " . oeFormatAge($result['DOB_YMD'], $date_of_death));
881 var EncounterDateArray
= new Array;
882 var CalendarCategoryArray
= new Array;
883 var EncounterIdArray
= new Array;
886 //Encounter details are stored to javacript as array.
887 $result4 = sqlStatement("SELECT fe.encounter,fe.date,openemr_postcalendar_categories.pc_catname FROM form_encounter AS fe " .
888 " left join openemr_postcalendar_categories on fe.pc_catid=openemr_postcalendar_categories.pc_catid WHERE fe.pid = ? order by fe.date desc", array($pid));
889 if (sqlNumRows($result4) > 0) {
890 while ($rowresult4 = sqlFetchArray($result4)) { ?
>
891 EncounterIdArray
[Count
] = <?php
echo js_escape($rowresult4['encounter']); ?
>;
892 EncounterDateArray
[Count
] = <?php
echo js_escape(oeFormatShortDate(date("Y-m-d", strtotime($rowresult4['date'])))); ?
>;
893 CalendarCategoryArray
[Count
] = <?php
echo js_escape(xl_appt_category($rowresult4['pc_catname'])); ?
>;
899 parent
.left_nav
.setPatientEncounter(EncounterIdArray
, EncounterDateArray
, CalendarCategoryArray
);
901 } // end setting new pid
903 parent
.left_nav
.syncRadios();
904 <?php
if ((isset($_GET['set_pid'])) && (isset($_GET['set_encounterid'])) && (intval($_GET['set_encounterid']) > 0)) {
905 $query_result = sqlQuery("SELECT `date` FROM `form_encounter` WHERE `encounter` = ?", array($encounter)); ?
>
906 encurl
= 'encounter/encounter_top.php?set_encounter=' +
<?php
echo js_url($encounter); ?
> +
'&pid=' +
<?php
echo js_url($pid); ?
>;
907 parent
.left_nav
.setEncounter(<?php
echo js_escape(oeFormatShortDate(date("Y-m-d", strtotime($query_result['date'])))); ?
>, <?php
echo js_escape($encounter); ?
>, 'enc');
908 top
.restoreSession();
909 parent
.left_nav
.loadFrame('enc2', 'enc', 'patient_file/' + encurl
);
910 <?php
} // end setting new encounter id (only if new pid is also set)
914 $
(window
).on('load', function() {
918 document
.addEventListener("DOMContentLoaded", () => {
919 cardTitleButtonClickListener();
924 /* Bad practice to override here, will get moved to base style theme */
926 box
-shadow
: 1px
1px
1px
hsl(0 0%
0%
/ .2);
930 /* Short term fix. This ensures the problem list, allergies, medications, and immunization cards handle long lists without interuppting
931 the UI. This should be configurable and should go in a more appropriate place */
938 if (!empty($GLOBALS['right_justify_labels_demographics']) && ($_SESSION['language_direction'] == 'ltr')) { ?
>
939 div
.tab td
.label_custom
, div
.label_custom
{
940 text
-align
: right
!important
;
943 div
.tab td
.data
, div
.data
{
951 // This is for layout font size override.
953 getLayoutProperties('DEM', $grparr, 'grp_size');
954 if (!empty($grparr['']['grp_size'])) {
955 $FONTSIZE = round($grparr['']['grp_size'] * 1.333333);
956 $FONTSIZE = round($FONTSIZE * 0.0625, 2);
959 /* Override font sizes in the theme. */
961 font
-size
: <?php
echo attr($FONTSIZE); ?
>rem
;
965 font
-size
: <?php
echo attr($FONTSIZE); ?
>rem
;
969 font
-size
: <?php
echo attr($FONTSIZE); ?
>rem
;
973 font
-size
: <?php
echo attr($FONTSIZE); ?
>rem
;
982 background
: var(--bg
) !important
;
986 background
: var(--white
);
991 .section
-header
-dynamic
{
995 <title
><?php
echo xlt("Dashboard{{patient file}}"); ?
></title
>
998 <body
class="mt-1 patient-demographic bg-light">
1001 // Create and fire the patient demographics view event
1002 $viewEvent = new ViewEvent($pid);
1003 $viewEvent = $GLOBALS["kernel"]->getEventDispatcher()->dispatch($viewEvent, ViewEvent
::EVENT_HANDLE
, 10);
1004 $thisauth = AclMain
::aclCheckCore('patients', 'demo');
1006 if (!$thisauth ||
!$viewEvent->authorized()) {
1007 echo $twig->getTwig()->render('core/unauthorized-partial.html.twig', ['pageTitle' => xl("Medical Dashboard")]);
1012 <div id
="container_div" class="<?php echo $oemr_ui->oeContainer(); ?> mb-2">
1013 <a href
='../reminder/active_reminder_popup.php' id
='reminder_popup_link' style
='display: none' onclick
='top.restoreSession()'></a
>
1014 <a href
='../birthday_alert/birthday_pop.php?pid=<?php echo attr_url($pid); ?>&user_id=<?php echo attr_url($_SESSION['authUserID
']); ?>' id
='birthday_popup' style
='display: none;' onclick
='top.restoreSession()'></a
>
1018 if ($result['squad'] && !AclMain
::aclCheckCore('squads', $result['squad'])) {
1024 require_once("$include_root/patient_file/summary/dashboard_header.php");
1027 $list_id = "dashboard"; // to indicate nav item is active, count and give correct id
1028 // Collect the patient menu then build it
1029 $menuPatient = new PatientMenuRole($twig);
1030 $menuPatient->displayHorizNavBarMenu();
1031 // Get the document ID of the patient ID card if access to it is wanted here.
1032 $idcard_doc_id = false;
1033 if ($GLOBALS['patient_id_category_name']) {
1034 $idcard_doc_id = get_document_by_catg($pid, $GLOBALS['patient_id_category_name'], 3);
1037 <div
class="main mb-1">
1038 <!-- start main content div
-->
1039 <div
class="form-row">
1041 $t = $twig->getTwig();
1043 $allergy = (AclMain
::aclCheckIssue('allergy')) ?
1 : 0;
1044 $pl = (AclMain
::aclCheckIssue('medical_problem')) ?
1 : 0;
1045 $meds = (AclMain
::aclCheckIssue('medication')) ?
1 : 0;
1046 $rx = (!$GLOBALS['disable_prescriptions'] && AclMain
::aclCheckCore('patients', 'rx')) ?
1 : 0;
1047 $cards = max(1, ($allergy +
$pl +
$meds));
1049 $colInt = 12 / $cards;
1050 $col .= "col-md-" . $colInt;
1053 * Helper function to return only issues with an outcome not equal to resolved
1055 * @param array $i An array of issues
1058 function filterActiveIssues(array $i): array
1060 return array_filter($i, function ($_i) {
1061 return ($_i['outcome'] != 1) && (empty($_i['enddate']) ||
(strtotime($_i['enddate']) > strtotime('now')));
1066 if ($allergy === 1) {
1067 $allergyService = new AllergyIntoleranceService();
1068 $_rawAllergies = filterActiveIssues($allergyService->getAll(['lists.pid' => $pid])->getData());
1069 $id = 'allergy_ps_expand';
1071 'title' => xl('Allergies'),
1072 'card_container_class_list' => ['flex-fill', 'mx-1'],
1074 'forceAlwaysOpen' => false,
1075 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1076 'linkMethod' => "javascript",
1077 'list' => $_rawAllergies,
1078 'listTouched' => (!empty(getListTouch($pid, 'allergy'))) ?
true : false,
1080 'btnLabel' => 'Edit',
1081 'btnLink' => "return load_location('{$GLOBALS['webroot']}/interface/patient_file/summary/stats_full.php?active=all&category=allergy')"
1083 echo "<div class=\"$col\">";
1084 echo $t->render('patient/card/allergies.html.twig', $viewArgs);
1088 $patIssueService = new PatientIssuesService();
1090 // MEDICAL PROBLEMS CARD
1092 $_rawPL = $patIssueService->search(['lists.pid' => $pid, 'lists.type' => 'medical_problem'])->getData();
1093 $id = 'medical_problem_ps_expand';
1095 'title' => xl('Medical Problems'),
1096 'card_container_class_list' => ['flex-fill', 'mx-1'],
1098 'forceAlwaysOpen' => false,
1099 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1100 'linkMethod' => "javascript",
1101 'list' => filterActiveIssues($_rawPL),
1102 'listTouched' => (!empty(getListTouch($pid, 'medical_problem'))) ?
true : false,
1104 'btnLabel' => 'Edit',
1105 'btnLink' => "return load_location('{$GLOBALS['webroot']}/interface/patient_file/summary/stats_full.php?active=all&category=medical_problem')"
1107 echo "<div class=\"$col\">";
1108 echo $t->render('patient/card/medical_problems.html.twig', $viewArgs);
1114 $_rawMedList = $patIssueService->search(['lists.pid' => $pid, 'lists.type' => 'medication'])->getData();
1115 $id = 'medication_ps_expand';
1117 'title' => xl('Medications'),
1118 'card_container_class_list' => ['flex-fill', 'mx-1'],
1120 'forceAlwaysOpen' => false,
1121 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1122 'linkMethod' => "javascript",
1123 'list' => filterActiveIssues($_rawMedList),
1124 'listTouched' => (!empty(getListTouch($pid, 'medication'))) ?
true : false,
1126 'btnLabel' => 'Edit',
1127 'btnLink' => "return load_location('{$GLOBALS['webroot']}/interface/patient_file/summary/stats_full.php?active=all&category=medication')"
1129 echo "<div class=\"$col\">";
1130 echo $t->render('patient/card/medication.html.twig', $viewArgs);
1134 // Render the Prescriptions card if turned on
1136 if ($GLOBALS['erx_enable'] && $display_current_medications_below == 1) {
1137 $sql = "SELECT * FROM prescriptions WHERE patient_id = ? AND active = '1'";
1138 $res = sqlStatement($sql, [$pid]);
1141 while ($row = sqlFetchArray($res)) {
1142 $row['unit'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_units'), $row['unit']);
1143 $row['form'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_form'), $row['form']);
1144 $row['route'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_route'), $row['route']);
1145 $row['interval'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_interval'), $row['interval']);
1148 $id = "current_prescriptions_ps_expand";
1150 'title' => xl('Current Medications'),
1152 'forceAlwaysOpen' => false,
1153 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1158 echo $t->render('patient/card/erx.html.twig', $viewArgs);
1161 $id = "prescriptions_ps_expand";
1163 'title' => xl("Prescriptions"),
1164 'card_container_class_list' => ['flex-fill', 'mx-1'],
1166 'forceAlwaysOpen' => false,
1167 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1168 'btnLabel' => "Edit",
1169 'auth' => AclMain
::aclCheckCore('patients', 'rx', '', ['write', 'addonly']),
1172 if ($GLOBALS['erx_enable']) {
1173 $viewArgs['title'] = 'Prescription History';
1174 $viewArgs['btnLabel'] = 'Add';
1175 $viewArgs['btnLink'] = "{$GLOBALS['webroot']}/interface/eRx.php?page=compose";
1176 } elseif ($GLOBALS['weno_rx_enable']) {
1177 // weno plus button which opens their iframe
1178 $viewArgs['weno'] = true;
1179 $viewArgs['title'] = "WENO ComposeRx";
1180 $viewArgs['btnLabel'] = 'Add';
1181 $viewArgs['btnLink'] = "{$GLOBALS['webroot']}/interface/weno/indexrx.php";
1182 $viewArgs['btnClass'] = "iframe";
1183 $viewArgs['linkMethod'] = "javascript";
1184 $viewArgs['btnLink'] = "editScripts('{$GLOBALS['webroot']}/controller.php?prescription&list&id=" . attr_url($pid) . "')";
1186 $viewArgs['btnLink'] = "editScripts('{$GLOBALS['webroot']}/controller.php?prescription&list&id=" . attr_url($pid) . "')";
1187 $viewArgs['linkMethod'] = "javascript";
1188 $viewArgs['btnClass'] = "iframe";
1193 $c = new Controller();
1194 // This is a hacky way to get a Smarty template from the controller and injecting it into
1195 // a Twig template. This reduces the amount of refactoring that is required but ideally the
1196 // Smarty template should be upgraded to Twig
1198 echo $c->act(['prescription' => '', 'fragment' => '', 'patient_id' => $pid]);
1199 $viewArgs['content'] = ob_get_contents();
1202 echo "<div class=\"col\">";
1203 echo $t->render('patient/card/rx.html.twig', $viewArgs);
1210 <div
class="col-md-8">
1212 if ($deceased > 0) :
1213 echo $twig->getTwig()->render('patient/partials/deceased.html.twig', [
1214 'deceasedDays' => deceasedDays($deceased),
1218 $sectionRenderEvents = $ed->dispatch(new SectionEvent('primary'), SectionEvent
::EVENT_HANDLE
);
1219 $sectionCards = $sectionRenderEvents->getCards();
1221 foreach ($sectionCards as $card) {
1222 $_auth = $card->getAcl();
1223 if (!AclMain
::aclCheckCore($_auth[0], $_auth[1])) {
1228 if ($card->canAdd()) {
1230 } elseif ($card->canEdit()) {
1235 'title' => $card->getTitle(),
1236 'id' => $card->getIdentifier(),
1237 'initiallyCollapsed' => $card->isInitiallyCollapsed(),
1238 'card_bg_color' => $card->getBackgroundColorClass(),
1239 'card_text_color' => $card->getTextColorClass(),
1240 'forceAlwaysOpen' => !$card->canCollapse(),
1241 'btnLabel' => $btnLabel,
1242 'btnLink' => 'test',
1245 echo $t->render($card->getTemplateFile(), array_merge($viewArgs, $card->getTemplateVariables()));
1248 if (!$GLOBALS['hide_billing_widget']) :
1249 $forceBillingExpandAlways = ($GLOBALS['force_billing_widget_open']) ?
true : false;
1250 $patientbalance = get_patient_balance($pid, false);
1251 $insurancebalance = get_patient_balance($pid, true) - $patientbalance;
1252 $totalbalance = $patientbalance +
$insurancebalance;
1253 $unallocated_amt = get_unallocated_patient_balance($pid);
1255 $id = "billing_ps_expand";
1256 $dispatchResult = $ed->dispatch(new CardRenderEvent('billing'), CardRenderEvent
::EVENT_HANDLE
);
1259 'title' => xl('Billing'),
1261 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1263 'patientBalance' => $patientbalance,
1264 'insuranceBalance' => $insurancebalance,
1265 'totalBalance' => $totalbalance,
1266 'unallocated' => $unallocated_amt,
1267 'forceAlwaysOpen' => $forceBillingExpandAlways,
1268 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1269 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1272 if (!empty($result['billing_note'])) {
1273 $viewArgs['billingNote'] = $result['billing_note'];
1276 if (!empty($result3['provider'])) {
1277 $viewArgs['provider'] = true;
1278 $viewArgs['insName'] = $insco_name;
1279 $viewArgs['copay'] = $result3['copay'];
1280 $viewArgs['effDate'] = $result3['effdate'];
1281 $viewArgs['effDateEnd'] = $result3['effdate_end'];
1284 echo $twig->getTwig()->render('patient/card/billing.html.twig', $viewArgs);
1285 endif; // End the hide_billing_widget
1287 // if anyone wants to render anything before the patient demographic list
1288 $GLOBALS["kernel"]->getEventDispatcher()->dispatch(new RenderEvent($pid), RenderEvent
::EVENT_SECTION_LIST_RENDER_BEFORE
, 10);
1290 if (AclMain
::aclCheckCore('patients', 'demo')) :
1291 $dispatchResult = $ed->dispatch(new CardRenderEvent('demographic'), CardRenderEvent
::EVENT_HANDLE
);
1292 // Render the Demographics box
1294 'title' => xl("Demographics"),
1295 'id' => "demographics_ps_expand",
1296 'btnLabel' => "Edit",
1297 'btnLink' => "demographics_full.php",
1298 'linkMethod' => "html",
1299 'auth' => ACLMain
::aclCheckCore('patients', 'demo', '', 'write'),
1300 'requireRestore' => (!isset($_SESSION['patient_portal_onsite_two'])) ?
true : false,
1301 'initiallyCollapsed' => (getUserSetting("demographics_ps_expand") == 0) ?
true : false,
1303 'result' => $result,
1304 'result2' => $result2,
1305 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1306 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1308 echo $twig->getTwig()->render('patient/card/tab_base.html.twig', $viewArgs);
1313 for ($y = 1; count($insurance_array) > $y; $y++
) {
1314 $insInBinder .= ',?';
1316 $sql = "SELECT * FROM insurance_data WHERE pid = ? AND type IN(" . $insInBinder . ") ORDER BY type, date DESC";
1318 $params = array_merge($params, $insurance_array);
1319 $res = sqlStatement($sql, $params);
1320 $prior_ins_type = '';
1322 while ($row = sqlFetchArray($res)) {
1323 if ($row['provider']) {
1324 // since the query is sorted by DATE DESC can use prior ins type to identify
1325 // unless insurance date_end is applicable
1326 $row['isOld'] = (!empty($row['date_end']) && $row['date_end'] <= date("Y-m-d")) ?
true : false;
1327 if (!$row['isOld']) {
1328 $row['isOld'] = (strcmp($row['type'], $prior_ins_type) == 0) ?
true : false;
1330 $icobj = new InsuranceCompany($row['provider']);
1331 $adobj = $icobj->get_address();
1332 $insco_name = trim($icobj->get_name());
1334 'name' => trim($icobj->get_name()),
1336 'line1' => $adobj->get_line1(),
1337 'line2' => $adobj->get_line2(),
1338 'city' => $adobj->get_city(),
1339 'state' => $adobj->get_state(),
1340 'postal' => $adobj->get_zip(),
1341 'country' => $adobj->get_country()
1344 $row['policy_type'] = (!empty($row['policy_type'])) ?
$policy_types[$row['policy_type']] : false;
1345 $row['dispFromDate'] = $row['date'] ?
true : false;
1346 $mname = ($row['subscriber_mname'] != "") ?
$row['subscriber_mname'] : "";
1347 $row['subscriber_full_name'] = str_replace("%mname%", $mname, "{$row['subscriber_fname']} %mname% {$row['subscriber_lname']}");
1348 $row['until_date'] = $row['isOld'] ?
$row['isOld'] : xlt('Present');
1350 $prior_ins_type = $row['type'];
1352 $row['isOld'] = (strcmp($row['type'], $prior_ins_type) == 0) ?
true : false;
1353 $row['dispFromDate'] = $row['date'] ?
true : false;
1355 'name' => 'Self-Pay',
1365 $row['policy_type'] = false;
1366 $mname = ''; //($row['subscriber_mname'] != "") ? $row['subscriber_mname'] : "";
1367 $row['subscriber_full_name'] = ' '; // str_replace("%mname%", $mname, "{$row['subscriber_fname']} %mname% {$row['subscriber_lname']}");
1368 $row['until_date'] = ($row['isOld']) ?
$row['isOld'] : xlt("Present");
1369 $prior_ins_type = $row['type'];
1370 if ($row['type'] != 'primary') {
1377 if ($GLOBALS["enable_eligibility_requests"]) {
1378 if (($_POST['status_update'] ??
'') === 'true') {
1379 unset($_POST['status_update']);
1380 $showEligibility = true;
1381 $ok = EDI270
::requestEligibleTransaction($pid);
1384 EDI270
::showEligibilityInformation($pid, false);
1385 $output = ob_get_contents();
1392 EDI270
::showEligibilityInformation($pid, true);
1393 $output = ob_get_contents();
1398 EDI270
::showEligibilityInformation($pid, true);
1399 $output = ob_get_contents();
1403 $id = "insurance_ps_expand";
1404 $dispatchResult = $ed->dispatch(new CardRenderEvent('insurance'), CardRenderEvent
::EVENT_HANDLE
);
1406 'title' => xl("Insurance"),
1408 'btnLabel' => "Edit",
1409 'btnLink' => "demographics_full.php",
1410 'linkMethod' => 'html',
1411 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1413 'eligibility' => $output,
1414 'enable_eligibility_requests' => $GLOBALS['enable_eligibility_requests'],
1415 'auth' => AclMain
::aclCheckCore('patients', 'demo', '', 'write'),
1416 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1417 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1420 if (count($insArr) > 0) {
1421 echo $twig->getTwig()->render('patient/card/insurance.html.twig', $viewArgs);
1423 endif; // end if demographics authorized
1425 if (AclMain
::aclCheckCore('patients', 'notes')) :
1426 $dispatchResult = $ed->dispatch(new CardRenderEvent('note'), CardRenderEvent
::EVENT_HANDLE
);
1427 // Notes expand collapse widget
1428 $id = "pnotes_ps_expand";
1430 'title' => xl("Messages"),
1432 'btnLabel' => "Edit",
1433 'btnLink' => "pnotes_full.php?form_active=1",
1434 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1435 'linkMethod' => "html",
1436 'bodyClass' => "notab",
1437 'auth' => AclMain
::aclCheckCore('patients', 'notes', '', 'write'),
1438 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1439 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1441 echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs);
1442 endif; // end if notes authorized
1444 if (AclMain
::aclCheckCore('patients', 'reminder') && $GLOBALS['enable_cdr'] && $GLOBALS['enable_cdr_prw']) :
1445 // patient reminders collapse widget
1446 $dispatchResult = $ed->dispatch(new CardRenderEvent('reminder'), CardRenderEvent
::EVENT_HANDLE
);
1447 $id = "patient_reminders_ps_expand";
1449 'title' => xl('Patient Reminders'),
1451 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1452 'btnLabel' => 'Edit',
1453 'btnLink' => '../reminder/patient_reminders.php?mode=simple&patient_id=' . attr_url($pid),
1454 'linkMethod' => 'html',
1455 'bodyClass' => 'notab collapse show',
1456 'auth' => AclMain
::aclCheckCore('patients', 'reminder', '', 'write'),
1457 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1458 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1460 echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs);
1461 endif; //end if prw is activated
1463 if (AclMain
::aclCheckCore('patients', 'disclosure')) :
1464 $authWriteDisclosure = AclMain
::aclCheckCore('patients', 'disclosure', '', 'write');
1465 $authAddonlyDisclosure = AclMain
::aclCheckCore('patients', 'disclosure', '', 'addonly');
1466 $dispatchResult = $ed->dispatch(new CardRenderEvent('disclosure'), CardRenderEvent
::EVENT_HANDLE
);
1467 // disclosures expand collapse widget
1468 $id = "disclosures_ps_expand";
1470 'title' => xl('Disclosures'),
1472 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1473 'btnLabel' => 'Edit',
1474 'btnLink' => 'disclosure_full.php',
1475 'linkMethod' => 'html',
1476 'bodyClass' => 'notab collapse show',
1477 'auth' => ($authWriteDisclosure ||
$authAddonlyDisclosure),
1478 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1479 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1481 echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs);
1482 endif; // end if disclosures authorized
1484 if ($GLOBALS['amendments'] && AclMain
::aclCheckCore('patients', 'amendment')) :
1485 $dispatchResult = $ed->dispatch(new CardRenderEvent('amendment'), CardRenderEvent
::EVENT_HANDLE
);
1486 // Amendments widget
1487 $sql = "SELECT * FROM amendments WHERE pid = ? ORDER BY amendment_date DESC";
1488 $result = sqlStatement($sql, [$pid]);
1490 while ($row = sqlFetchArray($result)) {
1491 $amendments[] = $row;
1494 $id = "amendments_ps_expand";
1496 'title' => xl('Amendments'),
1498 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1499 'btnLabel' => 'Edit',
1500 'btnLink' => $GLOBALS['webroot'] . "/interface/patient_file/summary/list_amendments.php?id=" . attr_url($pid),
1502 'linkMethod' => 'html',
1503 'bodyClass' => 'notab collapse show',
1504 'auth' => AclMain
::aclCheckCore('patients', 'amendment', '', ['write', 'addonly']),
1505 'amendments' => $amendments,
1506 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1507 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1509 echo $twig->getTwig()->render('patient/card/amendments.html.twig', $viewArgs);
1510 endif; // end amendments authorized
1512 if (AclMain
::aclCheckCore('patients', 'lab')) :
1513 $dispatchResult = $ed->dispatch(new CardRenderEvent('lab'), CardRenderEvent
::EVENT_HANDLE
);
1514 // labdata expand collapse widget
1515 // check to see if any labdata exist
1516 $spruch = "SELECT procedure_report.date_collected AS date
1517 FROM procedure_report
1518 JOIN procedure_order ON procedure_report.procedure_order_id = procedure_order.procedure_order_id
1519 WHERE procedure_order.patient_id = ?
1520 ORDER BY procedure_report.date_collected DESC";
1521 $existLabdata = sqlQuery($spruch, array($pid));
1522 $widgetAuth = ($existLabdata) ?
true : false;
1524 $id = "labdata_ps_expand";
1526 'title' => xl('Labs'),
1528 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1529 'btnLabel' => 'Trend',
1530 'btnLink' => "../summary/labdata.php",
1531 'linkMethod' => 'html',
1532 'bodyClass' => 'collapse show',
1533 'auth' => $widgetAuth,
1534 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1535 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1537 echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs);
1538 endif; // end labs authorized
1540 if ($vitals_is_registered && AclMain
::aclCheckCore('patients', 'med')) :
1541 $dispatchResult = $ed->dispatch(new CardRenderEvent('vital_sign'), CardRenderEvent
::EVENT_HANDLE
);
1542 // vitals expand collapse widget
1543 // check to see if any vitals exist
1544 $existVitals = sqlQuery("SELECT * FROM form_vitals WHERE pid=?", array($pid));
1545 $widgetAuth = ($existVitals) ?
true : false;
1547 $id = "vitals_ps_expand";
1549 'title' => xl('Vitals'),
1551 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1552 'btnLabel' => 'Trend',
1553 'btnLink' => "../encounter/trend_form.php?formname=vitals&context=dashboard",
1554 'linkMethod' => 'html',
1555 'bodyClass' => 'collapse show',
1556 'auth' => $widgetAuth,
1557 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1558 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1560 echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs);
1561 endif; // end vitals
1563 // if anyone wants to render anything after the patient demographic list
1564 $GLOBALS["kernel"]->getEventDispatcher()->dispatch(new RenderEvent($pid), RenderEvent
::EVENT_SECTION_LIST_RENDER_AFTER
, 10);
1566 // This generates a section similar to Vitals for each LBF form that
1567 // supports charting. The form ID is used as the "widget label".
1568 $gfres = sqlStatement("SELECT grp_form_id AS option_id, grp_title AS title, grp_aco_spec
1569 FROM layout_group_properties
1570 WHERE grp_form_id LIKE 'LBF%'
1571 AND grp_group_id = ''
1573 AND grp_activity = 1
1574 ORDER BY grp_seq, grp_title");
1576 while ($gfrow = sqlFetchArray($gfres)) :
1577 // $jobj = json_decode($gfrow['notes'], true);
1578 $LBF_ACO = empty($gfrow['grp_aco_spec']) ?
false : explode('|', $gfrow['grp_aco_spec']);
1579 if ($LBF_ACO && !AclMain
::aclCheckCore($LBF_ACO[0], $LBF_ACO[1])) {
1583 // vitals expand collapse widget
1584 $widgetAuth = false;
1585 if (!$LBF_ACO || AclMain
::aclCheckCore($LBF_ACO[0], $LBF_ACO[1], '', 'write')) {
1586 // check to see if any instances exist for this patient
1587 $existVitals = sqlQuery("SELECT * FROM forms WHERE pid = ? AND formdir = ? AND deleted = 0", [$pid, $vitals_form_id]);
1588 $widgetAuth = $existVitals;
1591 $dispatchResult = $ed->dispatch(new CardRenderEvent($gfrow['title']), CardRenderEvent
::EVENT_HANDLE
);
1593 'title' => xl($gfrow['title']),
1594 'id' => $vitals_form_id,
1595 'initiallyCollapsed' => (getUserSetting($vitals_form_id) == 0) ?
true : false,
1596 'btnLabel' => 'Trend',
1597 'btnLink' => "../encounter/trend_form.php?formname=vitals&context=dashboard",
1598 'linkMethod' => 'html',
1599 'bodyClass' => 'notab collapse show',
1600 'auth' => $widgetAuth,
1601 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1602 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1604 echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs);
1605 endwhile; // end while
1607 </div
> <!-- end left column div
-->
1608 <div
class="col-md-4">
1609 <!-- start right column div
-->
1612 $GLOBALS['portal_onsite_two_enable'],
1613 $GLOBALS['rest_fhir_api'],
1614 $GLOBALS['rest_api'],
1615 $GLOBALS['rest_portal_api'],
1617 foreach ($_extAccess as $_) {
1619 $portalCard = new PortalCard($GLOBALS);
1624 $sectionRenderEvents = $ed->dispatch(new SectionEvent('secondary'), SectionEvent
::EVENT_HANDLE
);
1625 $sectionCards = $sectionRenderEvents->getCards();
1627 $t = $twig->getTwig();
1629 foreach ($sectionCards as $card) {
1630 $_auth = $card->getAcl();
1631 $auth = AclMain
::aclCheckCore($_auth[0], $_auth[1]);
1637 if ($card->canAdd()) {
1639 } elseif ($card->canEdit()) {
1645 'title' => $card->getTitle(),
1646 'id' => $card->getIdentifier() . "_expand",
1648 'linkMethod' => 'html',
1649 'initiallyCollapsed' => $card->isInitiallyCollapsed(),
1650 'card_bg_color' => $card->getBackgroundColorClass(),
1651 'card_text_color' => $card->getTextColorClass(),
1652 'forceAlwaysOpen' => !$card->canCollapse(),
1653 'btnLabel' => $btnLabel,
1654 'btnLink' => "javascript:$('#patient_portal').collapse('toggle')",
1657 echo $t->render($card->getTemplateFile(), array_merge($viewArgs, $card->getTemplateVariables()));
1660 if ($GLOBALS['erx_enable']) :
1661 $dispatchResult = $ed->dispatch(new CardRenderEvent('demographics'), CardRenderEvent
::EVENT_HANDLE
);
1662 echo $twig->getTwig()->render('patient/partials/erx.html.twig', [
1663 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1664 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1668 // If there is an ID Card or any Photos show the widget
1669 $photos = pic_array($pid, $GLOBALS['patient_photo_category_name']);
1670 if ($photos or $idcard_doc_id) {
1671 $id = "photos_ps_expand";
1672 $dispatchResult = $ed->dispatch(new CardRenderEvent('patient_photo'), CardRenderEvent
::EVENT_HANDLE
);
1674 'title' => xl("ID Card / Photos"),
1676 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1677 'btnLabel' => 'Edit',
1678 'linkMethod' => "javascript",
1679 'bodyClass' => 'collapse show',
1681 'patientIDCategoryID' => $GLOBALS['patient_id_category_name'],
1682 'patientPhotoCategoryName' => $GLOBALS['patient_photo_category_name'],
1683 'photos' => $photos,
1684 'idCardDocID' => $idcard_doc_id,
1685 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1686 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1688 echo $twig->getTwig()->render('patient/card/photo.html.twig', $viewArgs);
1691 // Advance Directives
1692 if ($GLOBALS['advance_directives_warning']) {
1693 // advance directives expand collapse widget
1695 $counterFlag = false; //flag to record whether any categories contain ad records
1696 $query = "SELECT id FROM categories WHERE name='Advance Directive'";
1697 $myrow2 = sqlQuery($query);
1700 $parentId = $myrow2['id'];
1701 $query = "SELECT id, name FROM categories WHERE parent=?";
1702 $resNew1 = sqlStatement($query, array($parentId));
1703 while ($myrows3 = sqlFetchArray($resNew1)) {
1704 $categoryId = $myrows3['id'];
1705 $nameDoc = $myrows3['name'];
1706 $query = "SELECT documents.date, documents.id
1708 INNER JOIN categories_to_documents ON categories_to_documents.document_id=documents.id
1709 WHERE categories_to_documents.category_id=?
1710 AND documents.foreign_id=?
1711 AND documents.deleted = 0
1712 ORDER BY documents.date DESC";
1713 $resNew2 = sqlStatement($query, array($categoryId, $pid));
1714 $limitCounter = 0; // limit to one entry per category
1715 while (($myrows4 = sqlFetchArray($resNew2)) && ($limitCounter == 0)) {
1716 $dateTimeDoc = $myrows4['date'];
1717 // remove time from datetime stamp
1718 $tempParse = explode(" ", $dateTimeDoc);
1719 $dateDoc = $tempParse[0];
1720 $idDoc = $myrows4['id'];
1724 'docName' => $nameDoc,
1725 'docDate' => $dateDoc,
1727 $advDirArr[] = $tmp;
1728 $limitCounter = $limitCounter +
1;
1729 $counterFlag = true;
1733 $id = "adv_directives_ps_expand";
1735 $dispatchResult = $ed->dispatch(new CardRenderEvent('advance_directive'), CardRenderEvent
::EVENT_HANDLE
);
1737 'title' => xl("Advance Directives"),
1739 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1740 'btnLabel' => 'Edit',
1741 'linkMethod' => "javascript",
1742 'btnLink' => "return advdirconfigure();",
1743 'bodyClass' => 'collapse show',
1745 'advDirArr' => $advDirArr,
1746 'counterFlag' => $counterFlag,
1747 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1748 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1750 echo $twig->getTwig()->render('patient/card/adv_dir.html.twig', $viewArgs);
1752 } // close advanced dir block
1754 // Show Clinical Reminders for any user that has rules that are permitted.
1755 $clin_rem_check = resolve_rules_sql('', '0', true, '', $_SESSION['authUser']);
1756 $cdr = $GLOBALS['enable_cdr'];
1757 $cdr_crw = $GLOBALS['enable_cdr_crw'];
1758 if (!empty($clin_rem_check) && $cdr && $cdr_crw && AclMain
::aclCheckCore('patients', 'alert')) {
1759 // clinical summary expand collapse widget
1760 $id = "clinical_reminders_ps_expand";
1761 $dispatchResult = $ed->dispatch(new CardRenderEvent('clinical_reminders'), CardRenderEvent
::EVENT_HANDLE
);
1763 'title' => xl("Clinical Reminders"),
1765 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1766 'btnLabel' => "Edit",
1767 'btnLink' => "../reminder/clinical_reminders.php?patient_id=" . attr_url($pid),
1768 'linkMethod' => "html",
1769 'auth' => AclMain
::aclCheckCore('patients', 'alert', '', 'write'),
1770 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1771 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1773 echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs);
1776 $displayAppts = false;
1777 $displayRecurrAppts = false;
1778 $displayPastAppts = false;
1780 // Show current and upcoming appointments.
1781 // Recurring appointment support and Appointment Display Sets
1782 // added to Appointments by Ian Jardine ( epsdky ).
1783 if (isset($pid) && !$GLOBALS['disable_calendar'] && AclMain
::aclCheckCore('patients', 'appt')) {
1784 $displayAppts = true;
1785 $current_date2 = date('Y-m-d');
1787 $apptNum = (int) $GLOBALS['number_of_appts_to_show'];
1788 $apptNum2 = ($apptNum != 0) ?
abs($apptNum) : 10;
1790 $mode1 = !$GLOBALS['appt_display_sets_option'];
1791 $colorSet1 = $GLOBALS['appt_display_sets_color_1'];
1792 $colorSet2 = $GLOBALS['appt_display_sets_color_2'];
1793 $colorSet3 = $GLOBALS['appt_display_sets_color_3'];
1794 $colorSet4 = $GLOBALS['appt_display_sets_color_4'];
1795 $extraAppts = ($mode1) ?
1 : 6;
1796 $extraApptDate = '';
1801 $events = fetchNextXAppts($current_date2, $pid, $apptNum2 +
$extraAppts, true);
1805 $apptNumber = count($events);
1807 if ($apptNumber <= $apptNum2) {
1808 $extraApptDate = '';
1810 } elseif ($mode1 && $apptNumber == $apptNum2 +
1) {
1811 $extraApptDate = $events[$apptNumber - 1]['pc_eventDate'];
1816 } elseif ($apptNumber == $apptNum2 +
6) {
1817 $extraApptDate = $events[$apptNumber - 1]['pc_eventDate'];
1822 } else { // mode 2 - $apptNum2 < $apptNumber < $apptNum2 + 6
1823 $extraApptDate = '';
1828 $limitApptIndx = $apptNum2 - 1;
1829 $limitApptDate = $events[$limitApptIndx]['pc_eventDate'] ??
'';
1831 switch ($selectNum) {
1833 $lastApptIndx = $apptNumber - 1;
1834 $thisNumber = $lastApptIndx - $limitApptIndx;
1835 for ($i = 1; $i <= $thisNumber; ++
$i) {
1836 if ($events[$limitApptIndx +
$i]['pc_eventDate'] != $limitApptDate) {
1837 $extraApptDate = $events[$limitApptIndx +
$i]['pc_eventDate'];
1838 $events = array_slice($events, 0, $limitApptIndx +
$i);
1842 // Break in the loop to improve performance
1845 for ($i = 1; $i <= $limitApptIndx; ++
$i) {
1846 if ($events[$limitApptIndx - $i]['pc_eventDate'] != $limitApptDate) {
1847 $firstApptIndx = $apptNum2 - $i;
1851 // Break in the loop to improve performance
1854 if ($extraApptDate) {
1855 if ($extraApptDate != $limitApptDate) {
1856 $apptStyle2 = " style='background-color:" . attr($colorSet3) . ";'";
1858 $apptStyle2 = " style='background-color:" . attr($colorSet4) . ";'";
1866 $therapyGroupCategories = array();
1867 $query = sqlStatement("SELECT pc_catid FROM openemr_postcalendar_categories WHERE pc_cattype = 3 AND pc_active = 1");
1868 while ($result = sqlFetchArray($query)) {
1869 $therapyGroupCategories[] = $result['pc_catid'];
1872 // Build the UI Loop
1874 foreach ($events as $row) {
1876 $dayname = date("D", strtotime($row['pc_eventDate']));
1877 $displayMeridiem = ($GLOBALS['time_display_format'] == 0) ?
"" : "am";
1878 $disphour = substr($row['pc_startTime'], 0, 2) +
0;
1879 $dispmin = substr($row['pc_startTime'], 3, 2);
1880 if ($disphour >= 12 && $GLOBALS['time_display_format'] == 1) {
1881 $displayMeridiem = "pm";
1882 if ($disphour > 12) {
1887 // Note the translaution occurs here instead of in teh Twig file for some specific concatenation needs
1888 $etitle = xl('(Click to edit)');
1889 if ($row['pc_hometext'] != "") {
1890 $etitle = xl('Comments') . ": " . ($row['pc_hometext']) . "\r\n" . $etitle;
1893 $row['etitle'] = $etitle;
1895 if ($extraApptDate && $count > $firstApptIndx) {
1896 $apptStyle = $apptStyle2;
1898 if ($row['pc_eventDate'] != $priorDate) {
1899 $priorDate = $row['pc_eventDate'];
1900 $toggleSet = !$toggleSet;
1903 $bgColor = ($toggleSet) ?
$colorSet2 : $colorSet1;
1906 $row['pc_eventTime'] = sprintf("%02d", $disphour) . ":{$dispmin}";
1907 $row['pc_status'] = generate_display_field(array('data_type' => '1', 'list_id' => 'apptstat'), $row['pc_apptstatus']);
1908 if ($row['pc_status'] == 'None') {
1909 $row['pc_status'] = 'Scheduled';
1912 if (in_array($row['pc_catid'], $therapyGroupCategories)) {
1913 $row['groupName'] = getGroup($row['pc_gid'])['group_name'];
1916 $row['uname'] = text($row['ufname'] . " " . $row['ulname']);
1917 $row['bgColor'] = $bgColor;
1918 $row['dayName'] = $dayname;
1919 $row['displayMeridiem'] = $displayMeridiem;
1920 $row['jsEvent'] = attr_js(preg_replace("/-/", "", $row['pc_eventDate'])) . ', ' . attr_js($row['pc_eid']);
1925 // Show Recall if one exists
1926 $query = sqlStatement("SELECT * FROM `medex_recalls` WHERE `r_pid` = ?", [(int)$pid]);
1928 while ($result2 = sqlFetchArray($query)) {
1929 //tabYourIt('recall', 'main/messages/messages.php?go=' + choice);
1930 //parent.left_nav.loadFrame('1', tabNAME, url);
1932 'date' => $result2['r_eventDate'],
1933 'reason' => $result2['r_reason'],
1937 $id = "recall_ps_expand";
1938 $dispatchResult = $ed->dispatch(new CardRenderEvent('recall'), CardRenderEvent
::EVENT_HANDLE
);
1939 echo $twig->getTwig()->render('patient/card/recall.html.twig', [
1940 'title' => xl('Recall'),
1942 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
1943 'recalls' => $recallArr,
1944 'recallsAvailable' => ($count < 1 && empty($count2)) ?
false : true,
1945 'prependedInjection' => $dispatchResult->getPrependedInjection(),
1946 'appendedInjection' => $dispatchResult->getAppendedInjection(),
1949 } // End of Appointments Widget.
1951 /* Widget that shows recurrences for appointments. */
1953 if (isset($pid) && !$GLOBALS['disable_calendar'] && $GLOBALS['appt_recurrences_widget'] && AclMain
::aclCheckCore('patients', 'appt')) {
1954 $displayRecurrAppts = true;
1959 //Fetch patient's recurrences. Function returns array with recurrence appointments' category, recurrence pattern (interpreted), and end date.
1960 $recurrences = fetchRecurrences($pid);
1961 if (!empty($recurrences)) {
1962 foreach ($recurrences as $row) {
1963 if (!recurrence_is_current($row['pc_endDate'])) {
1967 if (ends_in_a_week($row['pc_endDate'])) {
1968 $row['close_to_end'] = true;
1974 /* End of recurrence widget */
1976 // Show PAST appointments.
1977 // added by Terry Hill to allow reverse sorting of the appointments
1979 if ($GLOBALS['num_past_appointments_to_show'] < 0) {
1981 ($showpast = -1 * $GLOBALS['num_past_appointments_to_show']);
1983 $showpast = $GLOBALS['num_past_appointments_to_show'];
1986 if (isset($pid) && !$GLOBALS['disable_calendar'] && $showpast > 0 && AclMain
::aclCheckCore('patients', 'appt')) {
1987 $displayPastAppts = true;
1989 $pastAppts = fetchXPastAppts($pid, $showpast, $direction); // This line added by epsdky
1993 foreach ($pastAppts as $row) {
1995 $dayname = date("D", strtotime($row['pc_eventDate']));
1996 $displayMeridiem = ($GLOBALS['time_display_format'] == 0) ?
"" : "am";
1997 $disphour = substr($row['pc_startTime'], 0, 2) +
0;
1998 $dispmin = substr($row['pc_startTime'], 3, 2);
1999 if ($disphour >= 12) {
2000 $displayMeridiem = "pm";
2001 if ($disphour > 12 && $GLOBALS['time_display_format'] == 1) {
2006 $petitle = xl('(Click to edit)');
2007 if ($row['pc_hometext'] != "") {
2008 $petitle = xl('Comments') . ": " . ($row['pc_hometext']) . "\r\n" . $petitle;
2010 $row['etitle'] = $petitle;
2012 $row['pc_status'] = generate_display_field(array('data_type' => '1', 'list_id' => 'apptstat'), $row['pc_apptstatus']);
2014 $row['dayName'] = $dayname;
2015 $row['displayMeridiem'] = $displayMeridiem;
2016 $row['pc_eventTime'] = sprintf("%02d", $disphour) . ":{$dispmin}";
2017 $row['uname'] = text($row['ufname'] . " " . $row['ulname']);
2018 $row['jsEvent'] = attr_js(preg_replace("/-/", "", $row['pc_eventDate'])) . ', ' . attr_js($row['pc_eid']);
2019 $past_appts[] = $row;
2022 // END of past appointments
2024 // Display the Appt card
2025 $id = "appointments_ps_expand";
2026 $dispatchResult = $ed->dispatch(new CardRenderEvent('appointment'), CardRenderEvent
::EVENT_HANDLE
);
2027 echo $twig->getTwig()->render('patient/card/appointments.html.twig', [
2028 'title' => xl("Appointments"),
2030 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
2031 'btnLabel' => "Add",
2032 'btnLink' => "return newEvt()",
2033 'linkMethod' => "javascript",
2035 'recurrAppts' => $recurr,
2036 'pastAppts' => $past_appts,
2037 'displayAppts' => $displayAppts,
2038 'displayRecurrAppts' => $displayRecurrAppts,
2039 'displayPastAppts' => $displayPastAppts,
2040 'extraApptDate' => $extraApptDate,
2041 'therapyGroupCategories' => $therapyGroupCategories,
2042 'auth' => $resNotNull && (AclMain
::aclCheckCore('patients', 'appt', '', 'write') || AclMain
::aclCheckCore('patients', 'appt', '', 'addonly')),
2043 'resNotNull' => $resNotNull,
2044 'prependedInjection' => $dispatchResult->getPrependedInjection(),
2045 'appendedInjection' => $dispatchResult->getAppendedInjection(),
2048 echo "<div id=\"stats_div\"></div>";
2051 // Determine if track_anything form is in use for this site.
2052 $tmp = sqlQuery("SELECT count(*) AS count FROM registry WHERE directory = 'track_anything' AND state = 1");
2053 $track_is_registered = $tmp['count'];
2054 if ($track_is_registered) {
2055 $spruch = "SELECT id FROM forms WHERE pid = ? AND formdir = ?";
2056 $existTracks = sqlQuery($spruch, array($pid, "track_anything"));
2057 $id = "track_anything_ps_expand";
2058 $dispatchResult = $ed->dispatch(new CardRenderEvent('track_anything'), CardRenderEvent
::EVENT_HANDLE
);
2059 echo $twig->getTwig()->render('patient/card/loader.html.twig', [
2060 'title' => xl("Tracks"),
2062 'initiallyCollapsed' => (getUserSetting($id) == 0) ?
true : false,
2063 'btnLink' => "../../forms/track_anything/create.php",
2064 'linkMethod' => "html",
2065 'prependedInjection' => $dispatchResult->getPrependedInjection(),
2066 'appendedInjection' => $dispatchResult->getAppendedInjection(),
2068 } // end track_anything
2071 echo $twig->getTwig()->render('patient/partials/delete.html.twig', [
2072 'isAdmin' => AclMain
::aclCheckCore('admin', 'super'),
2073 'allowPatientDelete' => $GLOBALS['allow_pat_delete'],
2074 'csrf' => CsrfUtils
::collectCsrfToken(),
2079 </div
> <!-- end right column div
-->
2080 </div
> <!-- end div
.main
> row
:first
-->
2081 </div
> <!-- end main content div
-->
2082 </div
><!-- end container div
-->
2083 <?php
$oemr_ui->oeBelowContainerDiv(); ?
>
2085 // Array of skip conditions for the checkSkipConditions() function.
2087 <?php
echo ($condition_str ??
''); ?
>
2089 checkSkipConditions();
2093 var isPost
= <?php
echo js_escape($showEligibility ??
false); ?
>;
2094 var listId
= '#' +
<?php
echo js_escape($list_id); ?
>;
2096 $
(listId
).addClass("active");
2097 if (isPost
=== true) {
2098 $
("#eligibility").click();
2099 $
("#eligibility").get(0).scrollIntoView();
2104 <?php
$ed->dispatch(new RenderEvent($pid), RenderEvent
::EVENT_RENDER_POST_PAGELOAD
, 10); ?
>