From ab4ed0595e4316647eaff1287340ed1c39a535f0 Mon Sep 17 00:00:00 2001 From: Robert Down RN Date: Wed, 15 Sep 2021 01:38:31 -0400 Subject: [PATCH] Medical Dashboard UI Improvements (#4623) Update the UI/UX of the Medical Dashboard screen --- .../patient_file/summary/dashboard_header.php | 145 +- .../patient_file/summary/demographics.php | 2616 +++++++---------- interface/patient_file/summary/stats.php | 676 ++--- .../patient_file/summary/vitals_fragment.php | 5 +- library/ajax/user_settings.php | 5 + library/classes/Controller.class.php | 8 +- library/clinical_rules.php | 20 +- library/options.inc.php | 36 +- library/patient.inc | 36 +- src/Common/Twig/TwigExtension.php | 51 + src/Menu/PatientMenuRole.php | 4 +- src/OeUI/OemrUI.php | 2 +- templates/core/unauthorized.html.twig | 7 + templates/patient/card/adv_dir.html.twig | 20 + templates/patient/card/amendments.html.twig | 11 + templates/patient/card/appointments.html.twig | 100 + .../patient/card/appointments_past.html.twig | 12 + templates/patient/card/billing.html.twig | 41 + templates/patient/card/card_base.html.twig | 25 + templates/patient/card/demographics.html.twig | 10 + templates/patient/card/eligibility.html.twig | 0 templates/patient/card/erx.html.twig | 19 + .../patient/card/immunizations.html.twig | 17 + templates/patient/card/insurance.html.twig | 101 + templates/patient/card/loader.html.twig | 9 + .../patient/card/medical_problems.html.twig | 41 + templates/patient/card/photo.html.twig | 11 + templates/patient/card/recall.html.twig | 18 + templates/patient/card/rx.html.twig | 5 + templates/patient/card/tab_base.html.twig | 10 + templates/patient/card/tp_il.html.twig | 15 + templates/patient/dashboard_header.html.twig | 47 + templates/prescription/general_fragment.html | 58 +- 33 files changed, 2145 insertions(+), 2036 deletions(-) create mode 100644 templates/core/unauthorized.html.twig create mode 100644 templates/patient/card/adv_dir.html.twig create mode 100644 templates/patient/card/amendments.html.twig create mode 100644 templates/patient/card/appointments.html.twig create mode 100644 templates/patient/card/appointments_past.html.twig create mode 100644 templates/patient/card/billing.html.twig create mode 100644 templates/patient/card/card_base.html.twig create mode 100644 templates/patient/card/demographics.html.twig create mode 100644 templates/patient/card/eligibility.html.twig create mode 100644 templates/patient/card/erx.html.twig create mode 100644 templates/patient/card/immunizations.html.twig create mode 100644 templates/patient/card/insurance.html.twig create mode 100644 templates/patient/card/loader.html.twig create mode 100644 templates/patient/card/medical_problems.html.twig create mode 100644 templates/patient/card/photo.html.twig create mode 100644 templates/patient/card/recall.html.twig create mode 100644 templates/patient/card/rx.html.twig create mode 100644 templates/patient/card/tab_base.html.twig create mode 100644 templates/patient/card/tp_il.html.twig create mode 100644 templates/patient/dashboard_header.html.twig diff --git a/interface/patient_file/summary/dashboard_header.php b/interface/patient_file/summary/dashboard_header.php index 3ec028864d3..e9743804881 100644 --- a/interface/patient_file/summary/dashboard_header.php +++ b/interface/patient_file/summary/dashboard_header.php @@ -16,99 +16,74 @@ use OpenEMR\Common\Acl\AclMain; use OpenEMR\Common\Csrf\CsrfUtils; +use OpenEMR\Common\Twig\TwigContainer; $url_webroot = $GLOBALS['webroot']; $portal_login_href = $url_webroot . "/interface/patient_file/summary/create_portallogin.php"; -?> -
- pageHeading() . "\r\n"; ?> - -

+$twigContainer = new TwigContainer(); +$t = $twigContainer->getTwig(); - 1 && $deceased_days < 90) { - $num_of_days = $deceased_days . " " . xl("days ago"); - } elseif ($deceased_days >= 90 && $deceased_days < 731) { - $num_of_days = "~" . round($deceased_days / 30) . " " . xl("months ago"); // function intdiv available only in php7 - } elseif ($deceased_days >= 731) { - $num_of_days = xl("More than") . " " . round($deceased_days / 365) . " " . xl("years ago"); - } +function deceasedDays($days_deceased) +{ + $deceased_days = intval($days_deceased['days_deceased']); + if ($deceased_days == 0) { + $num_of_days = xl("Today"); + } elseif ($deceased_days == 1) { + $num_of_days = $deceased_days . " " . xl("day ago"); + } elseif ($deceased_days > 1 && $deceased_days < 90) { + $num_of_days = $deceased_days . " " . xl("days ago"); + } elseif ($deceased_days >= 90 && $deceased_days < 731) { + $num_of_days = "~" . round($deceased_days / 30) . " " . xl("months ago"); // function intdiv available only in php7 + } elseif ($deceased_days >= 731) { + $num_of_days = xl("More than") . " " . round($deceased_days / 365) . " " . xl("years ago"); + } - if (strlen($days_deceased['date_deceased']) > 10 && $GLOBALS['date_display_format'] < 1) { - $deceased_date = substr($days_deceased['date_deceased'], 0, 10); - } else { - $deceased_date = oeFormatShortDate($days_deceased['date_deceased']); - } + if (strlen($days_deceased['date_deceased']) > 10 && $GLOBALS['date_display_format'] < 1) { + $deceased_date = substr($days_deceased['date_deceased'], 0, 10); + } else { + $deceased_date = oeFormatShortDate($days_deceased['date_deceased']); + } - //echo xlt("Deceased") . " - " . text(oeFormatShortDate($days_deceased['date_deceased'])) . " (" . text($num_of_days) . ")" ; - echo xlt("Deceased") . " - " . text($deceased_date) . " (" . text($num_of_days) . ")" ; - ?> -

- -
+ return xlt("Deceased") . " - " . text($deceased_date) . " (" . text($num_of_days) . ")"; +} -
+function portalAuthorized($pid) +{ + if (!$GLOBALS['portal_onsite_two_enable'] && !$GLOBALS['portal_onsite_two_address']) { + return false; + } + + $return = [ + 'allowed' => false, + 'created' => false, + ]; + + $portalStatus = sqlQuery("SELECT allow_patient_portal FROM patient_data WHERE pid = ?", [$pid]); + if ($portalStatus['allow_patient_portal'] == 'YES') { + $return['allowed'] = true; + $portalLogin = sqlQuery("SELECT pid FROM `patient_access_onsite` WHERE `pid`=?", [$pid]); + if ($portalLogin) { + $return['created'] = false; + } + return $return; + } +} - - - - - - - - - - - - - - - - +$deceased = is_patient_deceased($pid); - -

- -

- -
- -
+$viewArgs = [ + 'pageHeading' => $oemr_ui->pageHeading(), + 'isDeceased' => ($deceased > 0) ? true : false, + 'deceasedDays' => deceasedDays($deceased), + 'isAdmin' => AclMain::aclCheckCore('admin', 'super'), + 'allowPatientDelete' => $GLOBALS['allow_pat_delete'], + 'urlWebRoot' => $url_webroot, + 'pid' => $pid, + 'csrf' => CsrfUtils::collectCsrfToken(), + 'erxEnable' => $GLOBALS['erx_enable'], + 'portalAuthorized' => portalAuthorized($pid), + 'portalLoginHref' => $portal_login_href, +]; -
-
+echo $t->render('patient/dashboard_header.html.twig', $viewArgs); diff --git a/interface/patient_file/summary/demographics.php b/interface/patient_file/summary/demographics.php index 09f75d1ade8..d6d4fee6537 100644 --- a/interface/patient_file/summary/demographics.php +++ b/interface/patient_file/summary/demographics.php @@ -1,23 +1,23 @@ -* @author Sharon Cohen -* @author Stephen Waite -* @author Ranganath Pathak -* @author Tyler Wrenn -* @copyright Copyright (c) 2017-2020 Brady Miller -* @copyright Copyright (c) 2017 Sharon Cohen -* @copyright Copyright (c) 2018-2020 Stephen Waite -* @copyright Copyright (c) 2018 Ranganath Pathak -* @copyright Copyright (c) 2020 Tyler Wrenn -* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 -*/ + * + * Patient summary screen. + * + * @package OpenEMR + * @link http://www.open-emr.org + * @author Brady Miller + * @author Sharon Cohen + * @author Stephen Waite + * @author Ranganath Pathak + * @author Tyler Wrenn + * @copyright Copyright (c) 2017-2020 Brady Miller + * @copyright Copyright (c) 2017 Sharon Cohen + * @copyright Copyright (c) 2018-2020 Stephen Waite + * @copyright Copyright (c) 2018 Ranganath Pathak + * @copyright Copyright (c) 2020 Tyler Wrenn + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ require_once("../../globals.php"); require_once("$srcdir/patient.inc"); @@ -38,6 +38,9 @@ use OpenEMR\Menu\PatientMenuRole; use OpenEMR\OeUI\OemrUI; use OpenEMR\Reminder\BirthdayReminder; +use OpenEMR\Common\Twig\TwigContainer; + +$twig = new TwigContainer(null, $GLOBALS['kernel']); // Set session for pid (via setpid). Also set session for encounter (if applicable) if (isset($_GET['set_pid'])) { @@ -58,7 +61,7 @@ $active_reminders = false; $all_allergy_alerts = false; if ($GLOBALS['enable_cdr']) { -//CDR Engine stuff + //CDR Engine stuff if ($GLOBALS['enable_allergy_check'] && $GLOBALS['enable_alert_log']) { //Check for new allergies conflicts and throw popup if any exist(note need alert logging to support this) $new_allergy_alerts = allergy_conflict($pid, 'new', $_SESSION['authUser']); @@ -112,9 +115,9 @@ function pic_array($pid, $picture_directory) { $pics = array(); $sql_query = "select documents.id from documents join categories_to_documents " . - "on documents.id = categories_to_documents.document_id " . - "join categories on categories.id = categories_to_documents.category_id " . - "where categories.name like ? and documents.foreign_id = ? and documents.deleted = 0"; + "on documents.id = categories_to_documents.document_id " . + "join categories on categories.id = categories_to_documents.category_id " . + "where categories.name like ? and documents.foreign_id = ? and documents.deleted = 0"; if ($query = sqlStatement($sql_query, array($picture_directory, $pid))) { while ($results = sqlFetchArray($query)) { array_push($pics, $results['id']); @@ -127,17 +130,16 @@ function pic_array($pid, $picture_directory) // Get the document ID of the first document in a specific catg. function get_document_by_catg($pid, $doc_catg) { - $result = array(); if ($pid and $doc_catg) { - $result = sqlQuery("SELECT d.id, d.date, d.url FROM " . - "documents AS d, categories_to_documents AS cd, categories AS c " . - "WHERE d.foreign_id = ? " . - "AND cd.document_id = d.id " . - "AND c.id = cd.category_id " . - "AND c.name LIKE ? " . - "ORDER BY d.date DESC LIMIT 1", array($pid, $doc_catg)); + $result = sqlQuery("SELECT d.id, d.date, d.url + FROM documents AS d, categories_to_documents AS cd, categories AS c + WHERE d.foreign_id = ? + AND cd.document_id = d.id + AND c.id = cd.category_id + AND c.name LIKE ? + ORDER BY d.date DESC LIMIT 1", array($pid, $doc_catg)); } return ($result['id'] ?? false); @@ -155,21 +157,21 @@ function image_widget($doc_id, $doc_catg) $viewable_types = array('.png', '.jpg', '.jpeg', '.png', '.bmp', '.PNG', '.JPG', '.JPEG', '.PNG', '.BMP'); if (in_array($extension, $viewable_types)) { // extension matches list $to_url = " " . - " " . attr($doc_catg) . ":" . attr($image_file) . " " . - text($doc_catg) . '
 ' . text($image_file) . - ""; + "/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'" . + " onclick='top.restoreSession();' class='image_modal'>" . + " " . attr($doc_catg) . ":" . attr($image_file) . " " . + text($doc_catg) . '
 ' . text($image_file) . + ""; } else { $to_url = " " . - "" . - xlt("View") . "  " . - text("$doc_catg - $image_file") . - " "; + "&patient_id=" . attr_url($pid) . "&document_id=" . attr_url($doc_id) . "'" . + " onclick='top.restoreSession()' class='btn btn-primary btn-sm'>" . + "" . + xlt("View") . "  " . + text("$doc_catg - $image_file") . + " "; } echo ""; @@ -178,8 +180,7 @@ function image_widget($doc_id, $doc_catg) } // Determine if the Vitals form is in use for this site. -$tmp = sqlQuery("SELECT count(*) AS count FROM registry WHERE " . -"directory = 'vitals' AND state = 1"); +$tmp = sqlQuery("SELECT count(*) AS count FROM registry WHERE directory = 'vitals' AND state = 1"); $vitals_is_registered = $tmp['count']; // Get patient/employer/insurance information. @@ -191,1273 +192,995 @@ function image_widget($doc_id, $doc_catg) if (!empty($result3['provider'])) { // Use provider in case there is an ins record w/ unassigned insco $insco_name = getInsuranceProvider($result3['provider']); } + +$arrOeUiSettings = array( + 'heading_title' => xl('Medical Record Dashboard'), + 'include_patient_name' => true, + 'expandable' => false, + 'expandable_files' => array(), //all file names need suffix _xpd + 'action' => "", //conceal, reveal, search, reset, link or back + 'action_title' => "", + 'action_href' => "", //only for actions - reset, link or back + 'show_help_icon' => true, + 'help_file_name' => "medical_dashboard_help.php" +); +$oemr_ui = new OemrUI($arrOeUiSettings); ?> + + - - + $(window).on('load', function() { + setMyPatient(); + }); - -<?php echo xlt("Dashboard{{patient file}}"); ?> + #DEM .data td { + font-size: rem; + } - xl('Medical Record Dashboard'), - 'include_patient_name' => true, - 'expandable' => false, - 'expandable_files' => array(),//all file names need suffix _xpd - 'action' => "",//conceal, reveal, search, reset, link or back - 'action_title' => "", - 'action_href' => "",//only for actions - reset, link or back - 'show_help_icon' => true, - 'help_file_name' => "medical_dashboard_help.php" -); -$oemr_ui = new OemrUI($arrOeUiSettings); -?> - + :root { + --white: #fff; + --bg: hsl(0 0% 90%); + } - -
- + body { + background: var(--bg) !important; + } - ' id='birthday_popup' style='display: none;' onclick='top.restoreSession()'> - + <?php echo xlt("Dashboard{{patient file}}"); ?> + + + + getEventDispatcher()->dispatch(ViewEvent::EVENT_HANDLE, $viewEvent, 10); + $thisauth = AclMain::aclCheckCore('patients', 'demo'); - if ( - !$thisauth || - !$viewEvent->authorized() - ) { - echo "

(" . xlt('Demographics not authorized') . ")

\n"; - echo "\n\n"; + if (!$thisauth || !$viewEvent->authorized()) { + echo $twig->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xlt("Medical Dashboard")]); exit(); - }?> + } + ?> - -
- -
+
+ + ' id='birthday_popup' style='display: none;' onclick='top.restoreSession()'> - displayHorizNavBarMenu(); - // Get the document ID of the patient ID card if access to it is wanted here. - $idcard_doc_id = false; - if ($GLOBALS['patient_id_category_name']) { - $idcard_doc_id = get_document_by_catg($pid, $GLOBALS['patient_id_category_name']); - } - ?> -
-
-
-
- - -
- -
- - - - - - - - - - - - - - - - -
-
- -
- -
-     - 0) { ?> -     - - -
- - getEventDispatcher()->dispatch(RenderEvent::EVENT_SECTION_LIST_RENDER_BEFORE, new RenderEvent($pid), 10); - ?> - -
- -
-
    - -
-
- -
-
-
-
- displayHorizNavBarMenu(); + // Get the document ID of the patient ID card if access to it is wanted here. + $idcard_doc_id = false; + if ($GLOBALS['patient_id_category_name']) { + $idcard_doc_id = get_document_by_catg($pid, $GLOBALS['patient_id_category_name']); + } + ?> +
+ +
+
+ xl('Billing'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'hideBtn' => true, + 'patientBalance' => $patientbalance, + 'insuranceBalance' => $insurancebalance, + 'totalBalance' => $totalbalance, + 'forceAlwaysOpen' => $forceBillingExpandAlways, + ]; + + if (!empty($result['billing_note'])) { + $viewArgs['billingNote'] = $result['billing_note']; } - if ($insurance_count > 0) { - // Insurance expand collapse widget - $widgetTitle = xl("Insurance"); - $widgetLabel = "insurance"; - $widgetButtonLabel = xl("Edit"); - $widgetButtonLink = "demographics_full.php"; - $widgetButtonClass = ""; - $linkMethod = "html"; - $bodyClass = ""; - $widgetAuth = AclMain::aclCheckCore('patients', 'demo', '', 'write'); - $fixedWidth = false; - expand_collapse_widget( - $widgetTitle, - $widgetLabel, - $widgetButtonLabel, - $widgetButtonLink, - $widgetButtonClass, - $linkMethod, - $bodyClass, - $widgetAuth, - $fixedWidth - ); - - if ($insurance_count > 0) { - ?> - -
    - -
  • > -
  • - -
  • -
- - -
- -
- - get_address(); - $insco_name = trim($icobj->get_name()); - ?> - - - - - - - - - - - - - - -
- - - - - - - : -
- - '; - if (trim($adobj->get_line1())) { - echo text($adobj->get_line1()) . '
'; - echo text($adobj->get_city() . ', ' . $adobj->get_state() . ' ' . $adobj->get_zip()); - } - } else { - echo "" . xlt('Unassigned') . ""; - } - ?> -
- :
- :
- : -
-
- :
- - -
- : -
- : -
- : - -
-
- :
-
- - - -
- - -
:
-
-
- - - - -
- - -
- - : - -
- - : - - - - -
- : - - -
-
-
-
- - -
-
- -

- -
- -
-
- -
- - -
- - - -
- -
-
...
-
- -
- - - -
- -
-
...
-
- -
- - - -
- -
-
...
-
-
- - - -
- -

- -    -
- -
- - - -
- getTwig()->render('patient/card/billing.html.twig', $viewArgs); + endif; // End the hide_billing_widget + + // if anyone wants to render anything before the patient demographic list + $GLOBALS["kernel"]->getEventDispatcher()->dispatch(RenderEvent::EVENT_SECTION_LIST_RENDER_BEFORE, new RenderEvent($pid), 10); + + if (AclMain::aclCheckCore('patients', 'demo')) : + // Render the Demographics box + $viewArgs = [ + 'title' => xl("Demographics"), + 'id' => "demographics_ps_expand", + 'btnText' => "Edit", + 'btnLink' => "demographics_full.php", + 'linkMethod' => "html", + 'auth' => ACLMain::aclCheckCore('patients', 'demo', '', 'write'), + 'requireRestore' => (!isset($_SESSION['patient_portal_onsite_two'])) ? true : false, + 'initiallyCollapsed' => getUserSetting("demographics_ps_expand") == true ? true : false, + 'tabID' => "DEM", + 'result' => $result, + 'result2' => $result2, + ]; + echo $twig->getTwig()->render('patient/card/tab_base.html.twig', $viewArgs); + + // Insurance + $insArr = []; + $sql = "SELECT * FROM insurance_data WHERE pid = ? AND type IN(?) ORDER BY date DESC"; + $params[] = $pid; + $params[] = implode(", ", $insurance_array); + $res = sqlStatement($sql, $params); + while ($row = sqlFetchArray($res)) { + $insCount = ($row['provider']) ? $insCount++ : $insCount; + if ($row['provider']) { + $row['isOld'] = (strcmp($enddate, 'Present') != 0) ? true : false; + $icobj = new InsuranceCompany($row['provider']); + $adobj = $icobj->get_address(); + $insco_name = trim($icobj->get_name()); + $row['insco'] = [ + 'name' => trim($icobj->get_name()), + 'address' => [ + 'line1' => $adobj->get_line1(), + 'line2' => $adobj->get_line2(), + 'city' => $adobj->get_city(), + 'state' => $adobj->get_state(), + 'postal' => $adobj->get_zip(), + 'country' => $adobj->get_country() + ], + ]; + $row['policy_type'] = (!empty($row['policy_type'])) ? $policy_types[$row['policy_type']] : false; + } + $row['dispFromDate'] = ((strcmp($row['date'], '0000-00-00') != 0) || $row['date'] == "") ? true : false; + $mname = ($row['subscriber_mname'] != "") ? $row['subscriber_mname'] : ""; + $row['subscriber_full_name'] = str_replace("%mname%", $mname, "{$row['subscriber_fname']} %mname% {$row['subscriber_lname']}"); + $insArr[] = $row; + } - $fixedWidth = false; - expand_collapse_widget( - $widgetTitle, - $widgetLabel, - $widgetButtonLabel, - $widgetButtonLink, - $widgetButtonClass, - $linkMethod, - $bodyClass, - $widgetAuth, - $fixedWidth - ); - ?> -
-
...
-
- -
- - - -
- -
-
...
-
- -
- + $id = "insurance_ps_expand"; + $viewArgs = [ + 'title' => xl("Insurance"), + 'id' => $id, + 'btnText' => "Edit", + 'btnLink' => "demographics_full.php", + 'linkMethod' => 'html', + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'ins' => $insArr, + 'eligibility' => $output, + 'enable_oa' => $GLOBALS['enable_oa'], + 'auth' => AclMain::aclCheckCore('patients', 'demo', '', 'write'), + ]; + + if (count($insArr) > 0) { + echo $twig->getTwig()->render('patient/card/insurance.html.twig', $viewArgs); + } + endif; // end if demographics authorized + + if (AclMain::aclCheckCore('patients', 'notes')) : + // Notes expand collapse widget + $id = "pnotes_ps_expand"; + $viewArgs = [ + 'title' => xl("Messages"), + 'id' => $id, + 'btnLabel' => "Edit", + 'btnLink' => "pnotes_full.php?form_active=1", + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'linkMethod' => "html", + 'bodyClass' => "notab", + 'auth' => AclMain::aclCheckCore('patients', 'notes', '', 'write'), + ]; + echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs); + endif; // end if notes authorized + + if (AclMain::aclCheckCore('patients', 'reminder') && $GLOBALS['enable_cdr'] && $GLOBALS['enable_cdr_prw']) : + // patient reminders collapse widget + $id = "patient_reminders_ps_expand"; + $viewArgs = [ + 'title' => xl('Patient Reminders'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Edit', + 'btnLink' => '../reminder/patient_reminders.php?mode=simple&patient_id=' . attr_url($pid), + 'linkMethod' => 'html', + 'bodyClass' => 'notab collapse show', + 'auth' => AclMain::aclCheckCore('patients', 'reminder', '', 'write') + ]; + echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs); + endif; //end if prw is activated + + if (AclMain::aclCheckCore('patients', 'disclosure')) : + // disclosures expand collapse widget + $id = "disclosures_ps_expand"; + $viewArgs = [ + 'title' => xl('Disclosures'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Edit', + 'btnLink' => 'disclosure_full.php', + 'linkMethod' => 'html', + 'bodyClass' => 'notab collapse show', + 'auth' => AclMain::aclCheckCore('patients', 'disclosure', '', 'write') + ]; + echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs); + endif; // end if disclosures authorized + + if ($GLOBALS['amendments'] && AclMain::aclCheckCore('patients', 'amendment')) : + // Amendments widget + $sql = "SELECT * FROM amendments WHERE pid = ? ORDER BY amendment_date DESC"; + $result = sqlStatement($sql, [$pid]); + $amendments = []; + while ($row = sqlFetchArray($result)) { + $amendments[] = $row; + } -getEventDispatcher()->dispatch(RenderEvent::EVENT_SECTION_LIST_RENDER_AFTER, new RenderEvent($pid), 10); -// This generates a section similar to Vitals for each LBF form that -// supports charting. The form ID is used as the "widget label". -// -$gfres = sqlStatement("SELECT grp_form_id AS option_id, grp_title AS title, grp_aco_spec " . - "FROM layout_group_properties WHERE " . - "grp_form_id LIKE 'LBF%' AND grp_group_id = '' AND grp_repeats > 0 AND grp_activity = 1 " . - "ORDER BY grp_seq, grp_title"); -while ($gfrow = sqlFetchArray($gfres)) { - // $jobj = json_decode($gfrow['notes'], true); - $LBF_ACO = empty($gfrow['grp_aco_spec']) ? false : explode('|', $gfrow['grp_aco_spec']); - if ($LBF_ACO && !AclMain::aclCheckCore($LBF_ACO[0], $LBF_ACO[1])) { - continue; - } ?> -
- xl('Amendments'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Edit', + 'btnLink' => $GLOBALS['webroot'] . "/interface/patient_file/summary/list_amendments.php?id=" . attr_url($pid), + 'btnCLass' => 'rx_modal', + 'linkMethod' => 'html', + 'bodyClass' => 'notab collapse show', + 'auth' => AclMain::aclCheckCore('patients', 'amendment', '', 'write'), + 'amendments' => $amendments, + ]; + echo $twig->getTwig()->render('patient/card/amendments.html.twig', $viewArgs); + endif; // end amendments authorized + + if (AclMain::aclCheckCore('patients', 'lab')) : + // labdata expand collapse widget + // check to see if any labdata exist + $spruch = "SELECT procedure_report.date_collected AS date + FROM procedure_report + JOIN procedure_order ON procedure_report.procedure_order_id = procedure_order.procedure_order_id + WHERE procedure_order.patient_id = ? + ORDER BY procedure_report.date_collected DESC"; + $existLabdata = sqlQuery($spruch, array($pid)); + $widgetAuth = ($existLabdata) ? true : false; + + $id = "labdata_ps_expand"; + $viewArgs = [ + 'title' => xl('Labs'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Trend', + 'btnLink' => "../summary/labdata.php", + 'linkMethod' => 'html', + 'bodyClass' => 'collapse show', + 'auth' => $widgetAuth, + ]; + echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs); + endif; // end labs authorized + + if ($vitals_is_registered && AclMain::aclCheckCore('patients', 'med')) : + // vitals expand collapse widget + // check to see if any vitals exist + $existVitals = sqlQuery("SELECT * FROM form_vitals WHERE pid=?", array($pid)); + $widgetAuth = ($existVitals) ? true : false; + + $id = "vitals_ps_expand"; + $viewArgs = [ + 'title' => xl('Vitals'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Trend', + 'btnLink' => "../encounter/trend_form.php?formname=vitals", + 'linkMethod' => 'html', + 'bodyClass' => 'collapse show', + 'auth' => $widgetAuth, + ]; + echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs); + endif; // end vitals + + // if anyone wants to render anything after the patient demographic list + $GLOBALS["kernel"]->getEventDispatcher()->dispatch(RenderEvent::EVENT_SECTION_LIST_RENDER_AFTER, new RenderEvent($pid), 10); + + // This generates a section similar to Vitals for each LBF form that + // supports charting. The form ID is used as the "widget label". + $gfres = sqlStatement("SELECT grp_form_id AS option_id, grp_title AS title, grp_aco_spec + FROM layout_group_properties + WHERE grp_form_id LIKE 'LBF%' + AND grp_group_id = '' + AND grp_repeats > 0 + AND grp_activity = 1 + ORDER BY grp_seq, grp_title"); + + while ($gfrow = sqlFetchArray($gfres)) : + // $jobj = json_decode($gfrow['notes'], true); + $LBF_ACO = empty($gfrow['grp_aco_spec']) ? false : explode('|', $gfrow['grp_aco_spec']); + if ($LBF_ACO && !AclMain::aclCheckCore($LBF_ACO[0], $LBF_ACO[1])) { + continue; + } - $fixedWidth = false; - expand_collapse_widget( - $widgetTitle, - $widgetLabel, - $widgetButtonLabel, - $widgetButtonLink, - $widgetButtonClass, - $linkMethod, - $bodyClass, - $widgetAuth, - $fixedWidth - ); ?> -
-
...
-
- -
- - - - + // vitals expand collapse widget + $widgetAuth = false; + if (!$LBF_ACO || AclMain::aclCheckCore($LBF_ACO[0], $LBF_ACO[1], '', 'write')) { + // check to see if any instances exist for this patient + $existVitals = sqlQuery("SELECT * FROM forms WHERE pid = ? AND formdir = ? AND deleted = 0", [$pid, $vitals_form_id]); + $widgetAuth = $existVitals; + } - -
-
+ $viewArgs = [ + 'title' => xl($gfrow['title']), + 'id' => $vitals_form_id, + 'initiallyCollapsed' => getUserSetting($vitals_form_id) == true ? true : false, + 'btnLabel' => 'Trend', + 'btnLink' => "../encounter/trend_form.php?formname=vitals", + 'linkMethod' => 'html', + 'bodyClass' => 'notab collapse show', + 'auth' => $widgetAuth, + ]; + echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs); + endwhile; // end while + ?> +
+
+ -
- xl("ID Card / Photos"), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Edit', + 'linkMethod' => "javascript", + 'bodyClass' => 'collapse show', + 'auth' => false, + 'patientIDCategoryID' => $GLOBALS['patient_id_category_name'], + 'patientPhotoCategoryName' => $GLOBALS['patient_photo_category_name'], + 'photos' => $photos, + 'idCardDocID' => $idcard_doc_id, + ]; + echo $twig->getTwig()->render('patient/card/photo.html.twig', $viewArgs); } - ?> -
-
-
- " . - text(xl_document_category($nameDoc)) . " " . - text($dateDoc); - echo "
"; + $tmp = [ + 'pid' => $pid, + 'docID' => $idDoc, + 'docName' => $nameDoc, + 'docDate' => $dateDoc, + ]; + $advDirArr[] = $tmp; $limitCounter = $limitCounter + 1; $counterFlag = true; } } - } - if (!$counterFlag) { - echo "  " . xlt('None{{Advanced_Directives}}'); - } ?> -
- xl("Advance Directives"), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Edit', + 'linkMethod' => "javascript", + 'btnLink' => "return advdirconfigure();", + 'bodyClass' => 'collapse show', + 'auth' => true, + 'advDirArr' => $advDirArr, + 'counterFlag' => $counterFlag, + ]; + echo $twig->getTwig()->render('patient/card/adv_dir.html.twig', $viewArgs); + } } // close advanced dir block - // Show Clinical Reminders for any user that has rules that are permitted. + // Show Clinical Reminders for any user that has rules that are permitted. $clin_rem_check = resolve_rules_sql('', '0', true, '', $_SESSION['authUser']); - if ( - !empty($clin_rem_check) && $GLOBALS['enable_cdr'] && $GLOBALS['enable_cdr_crw'] && - AclMain::aclCheckCore('patients', 'alert') - ) { + $cdr = $GLOBALS['enable_cdr']; + $cdr_crw = $GLOBALS['enable_cdr_crw']; + if (!empty($clin_rem_check) && $cdr && $cdr_crw && AclMain::aclCheckCore('patients', 'alert')) { // clinical summary expand collapse widget - $widgetTitle = xl("Clinical Reminders"); - $widgetLabel = "clinical_reminders"; - $widgetButtonLabel = xl("Edit"); - $widgetButtonLink = "../reminder/clinical_reminders.php?patient_id=" . attr_url($pid); - ; - $widgetButtonClass = ""; - $linkMethod = "html"; - $bodyClass = "summary_item small"; - $widgetAuth = AclMain::aclCheckCore('patients', 'alert', '', 'write'); - $fixedWidth = false; - expand_collapse_widget($widgetTitle, $widgetLabel, $widgetButtonLabel, $widgetButtonLink, $widgetButtonClass, $linkMethod, $bodyClass, $widgetAuth, $fixedWidth); - echo "
"; - echo "
" . xlt('Loading') . "...

"; - echo "
"; + $id = "clinical_reminders_ps_expand"; + $viewArgs = [ + 'title' => xl("Clinical Reminders"), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => "Edit", + 'btnLink' => "../reminder/clinical_reminders.php?patient_id=" . attr_url($pid), + 'linkMethod' => "html", + 'auth' => AclMain::aclCheckCore('patients', 'alert', '', 'write'), + ]; + echo $twig->getTwig()->render('patient/card/loader.html.twig', $viewArgs); } // end if crw - // Show current and upcoming appointments. - // - // Recurring appointment support and Appointment Display Sets - // added to Appointments by Ian Jardine ( epsdky ). - // + $displayAppts = false; + $displayRecurrAppts = false; + $displayPastAppts = false; + + // Show current and upcoming appointments. + // Recurring appointment support and Appointment Display Sets + // added to Appointments by Ian Jardine ( epsdky ). if (isset($pid) && !$GLOBALS['disable_calendar'] && AclMain::aclCheckCore('patients', 'appt')) { - // + $displayAppts = true; $current_date2 = date('Y-m-d'); $events = array(); - $apptNum = (int)$GLOBALS['number_of_appts_to_show']; - if ($apptNum != 0) { - $apptNum2 = abs($apptNum); - } else { - $apptNum2 = 10; - } + $apptNum = (int) $GLOBALS['number_of_appts_to_show']; + $apptNum2 = ($apptNum != 0) ? abs($apptNum) : 10; - // $mode1 = !$GLOBALS['appt_display_sets_option']; $colorSet1 = $GLOBALS['appt_display_sets_color_1']; $colorSet2 = $GLOBALS['appt_display_sets_color_2']; $colorSet3 = $GLOBALS['appt_display_sets_color_3']; $colorSet4 = $GLOBALS['appt_display_sets_color_4']; - // - if ($mode1) { - $extraAppts = 1; - } else { - $extraAppts = 6; - } + $extraAppts = ($mode1) ? 1 : 6; + $extraApptDate = ''; + + $past_appts = []; + $recallArr = []; $events = fetchNextXAppts($current_date2, $pid, $apptNum2 + $extraAppts, true); - ////// + if ($events) { $selectNum = 0; $apptNumber = count($events); @@ -1578,12 +1303,10 @@ function setMyPatient() { // } - // $limitApptIndx = $apptNum2 - 1; $limitApptDate = $events[$limitApptIndx]['pc_eventDate'] ?? ''; - // + switch ($selectNum) { - // case 2: $lastApptIndx = $apptNumber - 1; $thisNumber = $lastApptIndx - $limitApptIndx; @@ -1594,8 +1317,7 @@ function setMyPatient() { break; } } - - // + // Break in the loop to improve performance case 1: $firstApptIndx = 0; for ($i = 1; $i <= $limitApptIndx; ++$i) { @@ -1604,11 +1326,9 @@ function setMyPatient() { break; } } - - // + // Break in the loop to improve performance } - // if ($extraApptDate) { if ($extraApptDate != $limitApptDate) { $apptStyle2 = " style='background-color:" . attr($colorSet3) . ";'"; @@ -1617,20 +1337,8 @@ function setMyPatient() { } } } - // appointments expand collapse widget - $widgetTitle = xl("Appointments"); - $widgetLabel = "appointments"; - $widgetButtonLabel = xl("Add"); - $widgetButtonLink = "return newEvt();"; - $widgetButtonClass = ""; - $linkMethod = "javascript"; - $bodyClass = "summary_item small"; - $widgetAuth = $resNotNull // $resNotNull reflects state of query in fetchAppointments - && (AclMain::aclCheckCore('patients', 'appt', '', 'write') || AclMain::aclCheckCore('patients', 'appt', '', 'addonly')); - $fixedWidth = false; - expand_collapse_widget($widgetTitle, $widgetLabel, $widgetButtonLabel, $widgetButtonLink, $widgetButtonClass, $linkMethod, $bodyClass, $widgetAuth, $fixedWidth); + $count = 0; - // $toggleSet = true; $priorDate = ""; $therapyGroupCategories = array(); @@ -1639,24 +1347,22 @@ function setMyPatient() { $therapyGroupCategories[] = $result['pc_catid']; } - // - foreach ($events as $row) { ////// + // Build the UI Loop + $appts = []; + foreach ($events as $row) { $count++; - $dayname = date("l", strtotime($row['pc_eventDate'])); ////// - if ($GLOBALS['time_display_format'] == 0) { - $dispampm = ""; - } else { - $dispampm = "am"; - } + $dayname = date("D", strtotime($row['pc_eventDate'])); + $displayMeridiem = ($GLOBALS['time_display_format'] == 0) ? "" : "am"; $disphour = substr($row['pc_startTime'], 0, 2) + 0; $dispmin = substr($row['pc_startTime'], 3, 2); if ($disphour >= 12 && $GLOBALS['time_display_format'] == 1) { - $dispampm = "pm"; + $displayMeridiem = "pm"; if ($disphour > 12) { $disphour -= 12; } } + // Note the translaution occurs here instead of in teh Twig file for some specific concatenation needs $etitle = xl('(Click to edit)'); if ($row['pc_hometext'] != "") { $etitle = xl('Comments') . ": " . ($row['pc_hometext']) . "\r\n" . $etitle; @@ -1670,122 +1376,75 @@ function setMyPatient() { $toggleSet = !$toggleSet; } - if ($toggleSet) { - $apptStyle = " style='background-color:" . attr($colorSet2) . ";'"; - } else { - $apptStyle = " style='background-color:" . attr($colorSet1) . ";'"; - } + $bgColor = ($toggleSet) ? $colorSet2 : $colorSet1; } - echo "
"; - if (!in_array($row['pc_catid'], $therapyGroupCategories)) { - echo ""; - } else { - echo ""; - } - - echo "" . text(oeFormatShortDate($row['pc_eventDate'])) . ", "; - echo text(sprintf("%02d", $disphour) . ":$dispmin " . xl($dispampm) . " (" . xl($dayname)) . ") "; - if ($row['pc_recurrtype']) { - echo "" . xla("Repeating event") . ""; - } + $row['pc_eventTime'] = sprintf("%02d", $disphour) . ":{$dispmin}"; + $row['pc_status'] = generate_display_field(array('data_type' => '1', 'list_id' => 'apptstat'), $row['pc_apptstatus']); - echo " '1', 'list_id' => 'apptstat'), $row['pc_apptstatus']) . "'>"; - echo "
" . xlt('Status') . "( " . text($row['pc_apptstatus']) . " )
"; - echo text(xl_appt_category($row['pc_catname'])) . "\n"; if (in_array($row['pc_catid'], $therapyGroupCategories)) { - echo "
" . xlt('Group name') . ": " . text(getGroup($row['pc_gid'])['group_name']) . "\n"; - } - - if ($row['pc_hometext']) { - echo " Com"; + $row['groupName'] = getGroup($row['pc_gid'])['group_name']; } - echo "
" . text($row['ufname'] . " " . $row['ulname']); - echo !in_array($row['pc_catid'], $therapyGroupCategories) ? '
' : ''; - echo "
\n"; + $row['uname'] = text($row['ufname'] . " " . $row['ulname']); + $row['bgColor'] = $bgColor; + $row['dayName'] = $dayname; + $row['displayMeridiem'] = $displayMeridiem; + $row['jsEvent'] = attr_js(preg_replace("/-/", "", $row['pc_eventDate'])) . ', ' . attr_js($row['pc_eid']); + $appts[] = $row; } if ($resNotNull) { - if ($count < 1) { - echo "  " . xlt('No Appointments'); - } else { ////// - if ($extraApptDate) { - echo "
" . text($extraApptDate) . " ( + )
"; - } - } // Show Recall if one exists - $query = sqlStatement("SELECT * FROM medex_recalls WHERE r_pid = ?", array($pid)); - + $query = sqlStatement("SELECT * FROM medex_recalls WHERE r_pid = ?", [$pid]); + $recallArr = []; while ($result2 = sqlFetchArray($query)) { //tabYourIt('recall', 'main/messages/messages.php?go=' + choice); //parent.left_nav.loadFrame('1', tabNAME, url); - echo "  Recall: " . text(oeFormatShortDate($result2['r_eventDate'])) . " (" . text($result2['r_reason']) . ") "; + $recallArr[] = [ + 'date' => $result2['r_eventDate'], + 'reason' => $result2['r_reason'], + ]; $count2++; } - //if there is no appt and no recall - if (($count < 1) && empty($count2)) { - echo "

  " . xlt('No Recall') . ""; - } - $count = 0; - echo ""; + $id = "recall_ps_expand"; + echo $twig->getTwig()->render('patient/card/recall.html.twig', [ + 'title' => xl('Recall'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'recalls' => $recallArr, + 'recallsAvailable' => ($count < 1 && empty($count2)) ? false : true, + ]); } } // End of Appointments Widget. - - /* Widget that shows recurrences for appointments. */ - if ( - isset($pid) && !$GLOBALS['disable_calendar'] && $GLOBALS['appt_recurrences_widget'] && - AclMain::aclCheckCore('patients', 'appt') - ) { - $widgetTitle = xl("Recurrent Appointments"); - $widgetLabel = "recurrent_appointments"; - $widgetButtonLabel = xl("Add"); - $widgetButtonLink = "return newEvt();"; - $widgetButtonClass = ""; - $linkMethod = "javascript"; - $bodyClass = "summary_item small"; - $widgetAuth = false; - $fixedWidth = false; - expand_collapse_widget($widgetTitle, $widgetLabel, $widgetButtonLabel, $widgetButtonLink, $widgetButtonClass, $linkMethod, $bodyClass, $widgetAuth, $fixedWidth); + /* Widget that shows recurrences for appointments. */ + $recurr = []; + if (isset($pid) && !$GLOBALS['disable_calendar'] && $GLOBALS['appt_recurrences_widget'] && AclMain::aclCheckCore('patients', 'appt')) { + $displayRecurrAppts = true; $count = 0; $toggleSet = true; $priorDate = ""; //Fetch patient's recurrences. Function returns array with recurrence appointments' category, recurrence pattern (interpreted), and end date. $recurrences = fetchRecurrences($pid); - if (empty($recurrences)) { //if there are no recurrent appointments: - echo "
"; - echo "" . "  " . xlt('None{{Appointment}}') . ""; - echo "
"; - } else { + if (!empty($recurrences)) { foreach ($recurrences as $row) { - //checks if there are recurrences and if they are current (git didn't end yet) if (!recurrence_is_current($row['pc_endDate'])) { continue; } - echo "
"; - echo "" . xlt('Appointment Category') . ": " . xlt($row['pc_catname']) . ""; - echo "
"; - echo "" . xlt('Recurrence') . ': ' . text($row['pc_recurrspec']) . ""; - echo "
"; - $red_text = ""; //if ends in a week, make font red if (ends_in_a_week($row['pc_endDate'])) { - $red_text = " class=\"text-danger\" "; + $row['close_to_end'] = true; } - - echo "" . xlt('End Date') . ': ' . text(oeFormatShortDate($row['pc_endDate'])) . ""; - echo "
"; + $recurr[] = $row; } - - echo ""; } } - /* End of recurrence widget */ + /* End of recurrence widget */ - // Show PAST appointments. - // added by Terry Hill to allow reverse sorting of the appointments + // Show PAST appointments. + // added by Terry Hill to allow reverse sorting of the appointments $direction = "ASC"; if ($GLOBALS['num_past_appointments_to_show'] < 0) { $direction = "DESC"; @@ -1794,42 +1453,30 @@ function setMyPatient() { $showpast = $GLOBALS['num_past_appointments_to_show']; } - if ( - isset($pid) && !$GLOBALS['disable_calendar'] && $showpast > 0 && - AclMain::aclCheckCore('patients', 'appt') - ) { - $query = "SELECT e.pc_eid, e.pc_aid, e.pc_title, e.pc_eventDate, " . - "e.pc_startTime, e.pc_hometext, u.fname, u.lname, u.mname, " . - "c.pc_catname, e.pc_apptstatus " . - "FROM openemr_postcalendar_events AS e, users AS u, " . - "openemr_postcalendar_categories AS c WHERE " . - "e.pc_pid = ? AND e.pc_eventDate < CURRENT_DATE AND " . - "u.id = e.pc_aid AND e.pc_catid = c.pc_catid " . - "ORDER BY e.pc_eventDate " . escape_sort_order($direction) . " , e.pc_startTime DESC " . - "LIMIT " . escape_limit($showpast); + if (isset($pid) && !$GLOBALS['disable_calendar'] && $showpast > 0 && AclMain::aclCheckCore('patients', 'appt')) { + $displayPastAppts = true; + $query = "SELECT e.pc_eid, e.pc_aid, e.pc_title, e.pc_eventDate, e.pc_startTime, e.pc_hometext, u.fname, u.lname, u.mname, c.pc_catname, e.pc_apptstatus + FROM openemr_postcalendar_events AS e, + users AS u, + openemr_postcalendar_categories AS c + WHERE e.pc_pid = ? + AND e.pc_eventDate < CURRENT_DATE + AND u.id = e.pc_aid + AND e.pc_catid = c.pc_catid + ORDER BY e.pc_eventDate " . escape_sort_order($direction) . " , e.pc_startTime DESC LIMIT " . escape_limit($showpast); $pres = sqlStatement($query, array($pid)); - // appointments expand collapse widget - $widgetTitle = xl("Past Appointments"); - $widgetLabel = "past_appointments"; - $widgetButtonLabel = ''; - $widgetButtonLink = ''; - $widgetButtonClass = ''; - $linkMethod = "javascript"; - $bodyClass = "summary_item small"; - $widgetAuth = false; //no button - $fixedWidth = false; - expand_collapse_widget($widgetTitle, $widgetLabel, $widgetButtonLabel, $widgetButtonLink, $widgetButtonClass, $linkMethod, $bodyClass, $widgetAuth, $fixedWidth); $count = 0; + while ($row = sqlFetchArray($pres)) { $count++; - $dayname = date("l", strtotime($row['pc_eventDate'])); - $dispampm = "am"; + $dayname = date("D", strtotime($row['pc_eventDate'])); + $displayMeridiem = "am"; $disphour = substr($row['pc_startTime'], 0, 2) + 0; $dispmin = substr($row['pc_startTime'], 3, 2); if ($disphour >= 12) { - $dispampm = "pm"; + $displayMeridiem = "pm"; if ($disphour > 12 && $GLOBALS['time_display_format'] == 1) { $disphour -= 12; } @@ -1840,99 +1487,76 @@ function setMyPatient() { $petitle = xl('Comments') . ": " . ($row['pc_hometext']) . "\r\n" . $petitle; } - echo ""; - echo "" . text(xl($dayname) . ", " . oeFormatShortDate($row['pc_eventDate'])) . " " . xlt("Status") . "("; - echo " " . generate_display_field(array('data_type' => '1', 'list_id' => 'apptstat'), $row['pc_apptstatus']) . ")
"; // can't use special char parser on this - echo text("$disphour:$dispmin ") . xlt($dispampm) . " "; - echo text($row['fname'] . " " . $row['lname']) . "

\n"; - } - - if (isset($pres) && $res != null) { - if ($count < 1) { - echo "  " . xlt('None{{Appointment}}'); - } - - echo ""; + $row['pc_status'] = generate_display_field(array('data_type' => '1', 'list_id' => 'apptstat'), $row['pc_apptstatus']); + $row['dayName'] = $dayname; + $row['pc_eventTime'] = sprintf("%02d", $disphour) . ":{$dispmin}"; + $row['uname'] = text($row['fname'] . " " . $row['lname']); + $past_appts[] = $row; } } - // END of past appointments + // END of past appointments + + // Display the Appt card + $id = "appointments_ps_expand"; + echo $twig->getTwig()->render('patient/card/appointments.html.twig', [ + 'title' => xl("Appointments"), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => "Add", + 'btnLink' => "return newEvt()", + 'linkMethod' => "javascript", + 'appts' => $appts, + 'recurrAppts' => $recurr, + 'pastAppts' => $past_appts, + 'displayAppts' => $displayAppts, + 'displayRecurrAppts' => $displayRecurrAppts, + 'displayPastAppts' => $displayPastAppts, + 'extraApptDate' => $extraApptDate, + 'therapyGroupCategories' => $therapyGroupCategories, + 'auth' => $resNotNull && (AclMain::aclCheckCore('patients', 'appt', '', 'write') || AclMain::aclCheckCore('patients', 'appt', '', 'addonly')), + 'resNotNull' => $resNotNull, + ]); + + echo "
"; + + // TRACK ANYTHING + // Determine if track_anything form is in use for this site. + $tmp = sqlQuery("SELECT count(*) AS count FROM registry WHERE directory = 'track_anything' AND state = 1"); + $track_is_registered = $tmp['count']; + if ($track_is_registered) { + $spruch = "SELECT id FROM forms WHERE pid = ? AND formdir = ?"; + $existTracks = sqlQuery($spruch, array($pid, "track_anything")); + $id = "track_anything_ps_expand"; + echo $twig->getTwig()->render('patient/card/loader.html.twig', [ + 'title' => xl("Tracks"), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLink' => "../../forms/track_anything/create.php", + 'linkMethod' => "html" + ]); + } // end track_anything ?> - - -
-
-
...
-
-
-
- - "; - // track_anything expand collapse widget - $widgetTitle = xl("Tracks"); - $widgetLabel = "track_anything"; - $widgetButtonLabel = xl("Tracks"); - $widgetButtonLink = "../../forms/track_anything/create.php"; - $widgetButtonClass = ""; - $widgetAuth = ""; // don't show the button - $linkMethod = "html"; - $bodyClass = "notab"; - // check to see if any tracks exist - $spruch = "SELECT id " . - "FROM forms " . - "WHERE pid = ? " . - "AND formdir = ? "; - $existTracks = sqlQuery($spruch, array($pid, "track_anything")); - - $fixedWidth = false; - expand_collapse_widget( - $widgetTitle, - $widgetLabel, - $widgetButtonLabel, - $widgetButtonLink, - $widgetButtonClass, - $linkMethod, - $bodyClass, - $widgetAuth, - $fixedWidth - ); - ?> -
-
...
-
-
- - - - - - -oeBelowContainerDiv(); ?> - - + + + + oeBelowContainerDiv(); ?> + + diff --git a/interface/patient_file/summary/stats.php b/interface/patient_file/summary/stats.php index 3fffb91286f..8bb93575fba 100644 --- a/interface/patient_file/summary/stats.php +++ b/interface/patient_file/summary/stats.php @@ -10,9 +10,15 @@ * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ +use OpenEMR\Common\Twig\TwigContainer; + require_once("../../globals.php"); require_once("$srcdir/lists.inc"); require_once("$srcdir/options.inc.php"); +require_once("$srcdir/sql.inc"); + +$twigContainer = new TwigContainer(null, $kernel); +$t = $twigContainer->getTwig(); use OpenEMR\Common\Acl\AclMain; use OpenEMR\Common\Csrf\CsrfUtils; @@ -20,6 +26,84 @@ if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) { CsrfUtils::csrfNotVerified(); } + +/** + * Return an array of list data for a given issue type and patient + * + * @var $pid string Patient ID + * @var $type string Issue Type + * @return + */ +function getListData($pid, $type) +{ + $sqlArr = [ + "SELECT * FROM lists WHERE pid = ? AND type = ? AND", + dateEmptySql('enddate') + ]; + + if ($GLOBALS['erx_enable'] && $GLOBALS['erx_medication_display'] && $type == 'medication') { + $sqlArr[] = "and erx_uploaded != '1'"; + } + + if ($GLOBALS['erx_enable'] && $GLOBALS['erx_allergy_display'] && $type == 'allergy') { + $sqlArr[] = "and erx_uploaded != '1'"; + } + + $sqlArr[] = "ORDER BY begdate"; + + $sql = implode(" ", $sqlArr); + $res = sqlStatement($sql, [$pid, $type]); + $list = []; + + while ($row = sqlFetchArray($res)) { + if (!$row['enddate'] && !$row['returndate']) { + $rowclass = "noend_noreturn"; + } elseif (!$row['enddate'] && $row['returndate']) { + $rowclass = "noend"; + } elseif ($row['enddate'] && !$row['returndate']) { + $rowclass = "noreturn"; + } + + if ($type == "allergy") { + $reaction = ""; + if (!empty($row['reaction'])) { + $reaction = getListItemTitle("reaction", $row['reaction']); + $row['reactionTitle'] = $reaction; + } + if (!empty($row['severity_al'])) { + $severity = getListItemTitle("severity_ccda", $row['severity_al']); + // Collapse the SNOMED-CT 272141005 List to 3 groups + // Not great to hard code this here, this should be abstracted + // to a better place to handle more comprehensive, centralized class + // @todo Find a better home for this + if (in_array($row['severity_al'], ['severe', 'life_threatening_severity', 'fatal'])) { + $row['critical'] = true; + } + $row['severity'] = $severity; + } + } + + $list[] = $row; + } + + return $list; +} + +function getPrescriptions($pid) +{ + $sql = "SELECT * FROM prescriptions WHERE patient_id = ? AND active = '1'"; + $res = sqlStatement($sql, [$pid]); + $rx = []; + while ($row = sqlFetchArray($res)) { + $row['unit'] = generate_display_field(['data_type' => '1', 'list_id' => 'drug_units'], $row['unit']); + $row['form'] = generate_display_field(['data_type' => '1', 'list_id' => 'drug_form'], $row['form']); + $row['route'] = generate_display_field(['data_type' => '1', 'list_id' => 'drug_route'], $row['route']); + $row['interval'] = generate_display_field(['data_type' => '1', 'list_id' => 'drug_interval'], $row['interval']); + + $rx[] = $row; + } + return $rx; +} ?> -
- - - $arr) { - // Skip if user has no access to this issue type. + // Skip if user has no access to this issue type. if (!AclMain::aclCheckIssue($key)) { continue; } - - $query = "SELECT * FROM lists WHERE pid = ? AND type = ? AND "; - $query .= dateEmptySql('enddate'); - if ($GLOBALS['erx_enable'] && $GLOBALS['erx_medication_display'] && $key == 'medication') { - $query .= "and erx_uploaded != '1' "; - } - - if ($GLOBALS['erx_enable'] && $GLOBALS['erx_allergy_display'] && $key == 'allergy') { - $query .= "and erx_uploaded != '1' "; - } - - $query .= "ORDER BY begdate"; - $pres = sqlStatement($query, array($pid, $key)); if ($old_key == "medication" && $GLOBALS['erx_enable'] && $erx_upload_complete == 1) { - $display_current_medications_below = 0; - ?> -
-
- - - 0 || $arr[4] == 1) { - $old_key = $key; - if ($_POST['embeddedScreen']) { - if ($GLOBALS['erx_enable'] && $key == "medication") { - $query_uploaded = "SELECT * FROM lists WHERE pid = ? AND type = 'medication' AND "; - $query_uploaded .= dateEmptySql('enddate'); - $query_uploaded .= "and erx_uploaded != '1' "; - $query_uploaded .= "ORDER BY begdate"; - $res_uploaded = sqlStatement($query_uploaded, array($pid)); - if (sqlNumRows($res_uploaded) == 0) { - $erx_upload_complete = 1; - continue; - } - } + $issues = getListData($pid, $key); - echo " - - - "; - if (sqlNumRows($pres) == 0) { - if (getListTouch($pid, $key)) { - // Data entry has happened to this type, so can display an explicit None. - echo " \n"; - } else { - // Data entry has not happened to this type, so show 'Nothing Recorded" - echo " \n"; - } + $listData = getListData($pid, $key); + $id = $key . "_ps_expand"; + $viewArgs = [ + 'title' => xl($arr[0]), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'linkMethod' => "javascript", + 'list' => $listData, + 'auth' => AclMain::aclCheckIssue($key, '', ['write', 'addonly']) + ]; + + $btnLinkBase = "return load_location('{$GLOBALS['webroot']}/interface/__page__')"; + if (in_array($key, ["allergy", "medication"]) && $GLOBALS["erx_enable"]) { + $viewArgs['btnLabel'] = "Add"; + $btnLinkPage = "eRx.php?page=medentry"; + } else { + $viewArgs['btnLabel'] = "Edit"; + $btnLinkPage = "patient_file/summary/stats_full.php?active=all&category=" . attr_url($key); } + $viewArgs['btnLink'] = str_replace("__page__", $btnLinkPage, $btnLinkBase); - while ($row = sqlFetchArray($pres)) { - // output each issue for the $ISSUE_TYPE - if (!$row['enddate'] && !$row['returndate']) { - $rowclass = "noend_noreturn"; - } elseif (!$row['enddate'] && $row['returndate']) { - $rowclass = "noend"; - } elseif ($row['enddate'] && !$row['returndate']) { - $rowclass = "noreturn"; - } - - echo " \n"; - - //turn allergies red and bold and show the reaction (if exist) - if ($key == "allergy") { - $reaction = ""; - if (!empty($row['reaction'])) { - $reaction = " (" . getListItemTitle("reaction", $row['reaction']) . ")"; - } - - echo " \n"; - } else { - echo " \n"; - } - - echo " \n"; + if (count($listData) == 0) { + $viewArgs['listTouched'] = (getListTouch($pid, $key)) ? true : false; } - echo "
- '1', 'list_id' => 'drug_units'), $row['unit']); + $row['form'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_form'), $row['form']); + $row['route'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_route'), $row['route']); + $row['interval'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_interval'), $row['interval']); + $unit = ($row['size'] > 0) ? text($row['size']) . " " . $row['unit'] : ""; + $row['unit'] = $unit; + $rxArr[] = $row; } - $res = sqlStatement("select * from prescriptions where patient_id=? and active='1'", array($pid)); - ?> - - - - - - xl('Current Medications'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'auth' => false, + 'rxList' => $rxArr, + ]; - while ($row_currentMed = sqlFetchArray($res)) { - $runit = generate_display_field(array('data_type' => '1','list_id' => 'drug_units'), $row_currentMed['unit']); - $rin = generate_display_field(array('data_type' => '1','list_id' => 'drug_form'), $row_currentMed['form']); - $rroute = generate_display_field(array('data_type' => '1','list_id' => 'drug_route'), $row_currentMed['route']); - $rint = generate_display_field(array('data_type' => '1','list_id' => 'drug_interval'), $row_currentMed['interval']); - ?> - - - - - -
0) { - $unit = text($row_currentMed['size']) . " " . $runit . " "; -} + echo $t->render('patient/card/erx.html.twig', $viewArgs); - echo $unit . " " . text($row_currentMed['dosage']) . " " . $rin . " " . $rroute . " " . $rint; -?>
-
"; - // Issues expand collapse widget - $widgetTitle = $arr[0]; - $widgetLabel = $key; - if (($key == "allergy" || $key == "medication") && $GLOBALS['erx_enable']) { - $widgetButtonLabel = xl("Add"); - $widgetButtonLink = "load_location(\"${GLOBALS['webroot']}/interface/eRx.php?page=medentry\")"; - } else { - $widgetButtonLabel = xl("Edit"); - $widgetButtonLink = "load_location(\"${GLOBALS['webroot']}/interface/patient_file/summary/stats_full.php?active=all&category=" . attr_url($key) . "\")"; + // + if (count($issues) > 0 || $arr[4] == 1) { + $old_key = $key; + if ($GLOBALS['erx_enable'] && $key = "medication") { + $sqlUploadedArr = [ + "SELECT * FROM lists WHERE pid = ? AND type = 'medication' AND", + dateEmptySql('enddate'), + "AND erx_uploaded != '1' ORDER BY begdate", + ]; + $sqlUploaded = implode(" ", $sqlUploadedArr); + $resUploaded = sqlStatement($sqlUploaded, [$pid]); + if (sqlNumRows($resUploaded) == 0) { + $erx_upload_complete = 1; + continue; } - - $widgetButtonClass = ""; - $linkMethod = "javascript"; - $bodyClass = "summary_item small"; - $widgetAuth = AclMain::aclCheckIssue($key, '', array('write', 'addonly')); - $fixedWidth = false; - expand_collapse_widget($widgetTitle, $widgetLabel, $widgetButtonLabel, $widgetButtonLink, $widgetButtonClass, $linkMethod, $bodyClass, $widgetAuth, $fixedWidth); - } else { // end embeddedScreen - ?> -
- - )">() -
  " . xlt('None{{Issues}}') . "
  " . xlt('Nothing Recorded') . "
  " . text($row['title'] . $reaction) . "  " . text($row['title']) . "
"; - if ($_POST['embeddedScreen']) { - echo "
"; - } + echo $t->render('patient/card/medical_problems.html.twig', $viewArgs); } } -?> - - - 0) { - $dres = sqlStatement("SELECT tp.id, tp.value FROM forms, " . - "form_" . add_escape_custom($formname) . - " AS tp WHERE forms.pid = ? AND " . - "forms.formdir = ? AND tp.id = forms.form_id AND " . - "tp.rownbr = -1 AND tp.colnbr = -1 AND tp.value LIKE '0%' " . - "ORDER BY tp.value DESC", array($pid, $formname)); +// Render Cards for 2 specific forms +foreach (['treatment_protocols', 'injury_log'] as $formname) { + if (sqlNumRows(sqlStatement("SHOW TABLES LIKE form_{$formname}")) > 0) { + $sql = "SELECT tp.id, tp.value + FROM forms, form_{$formname} AS tp + WHERE forms.pid = ? + AND forms.formdir = ? + AND tp.id = forms.form_id + AND tp.rownbr = -1 + AND tp.colnbr = -1 + AND tp.value LIKE '0%' + ORDER BY tp.value DESC"; + $dres = sqlStatement($sql, [$pid, $formname]); if (sqlNumRows($dres) > 0 && $need_head) { - $need_head = false; - echo " \n"; - echo " \n"; - echo " \n"; - } + $formRows = []; + while ($row = sqlFetchArray($dres)) { + list($completed, $start_date, $template_name) = explode('|', $row['value'], 3); + $formRows['startDate'] = $start_date; + $formRws['templateName'] = $template_name; + $formRows['id'] = $row['id']; + } - while ($row = sqlFetchArray($dres)) { - list($completed, $start_date, $template_name) = explode('|', $row['value'], 3); - echo " \n"; - echo " \n"; - echo " \n"; + $id = "injury_log"; + echo $t->render('patient/card/tp_il.html.twig', [ + 'title' => xl("Injury Log"), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'formName' => $formname, + 'formRows' => $formRows, + ]); } } } -?> -
\n"; - echo " Injury Log\n"; - echo "
  "; - echo "" . - text($start_date) . " " . - text($template_name) . "
- - -
- - - "; - // Issues expand collapse widget - $widgetTitle = xl('Immunizations'); - $widgetLabel = "immunizations"; - $widgetButtonLabel = xl("Edit"); - $widgetButtonLink = "javascript:load_location(\"${GLOBALS['webroot']}/interface/patient_file/summary/immunizations.php\")"; - $widgetButtonClass = ""; - $linkMethod = "javascript"; - $bodyClass = "summary_item small"; - $widgetAuth = true; - $fixedWidth = false; - expand_collapse_widget($widgetTitle, $widgetLabel, $widgetButtonLabel, $widgetButtonLink, $widgetButtonClass, $linkMethod, $bodyClass, $widgetAuth, $fixedWidth); - } else { ?> - -\n"; - echo " \n"; - echo "
- - - () - -
- - -
  " . xlt('None{{Immunizations}}') . "
\n"; - } +// Render the Immunizations card if turned on +if (!$GLOBALS['disable_immunizations'] && !$GLOBALS['weight_loss_clinic']) : + $sql = "SELECT i1.id AS id, i1.immunization_id AS immunization_id, i1.cvx_code AS cvx_code, c.code_text_short AS cvx_text, + IF(i1.administered_date, concat(i1.administered_date,' - ',c.code_text_short), + IF(i1.note,substring(i1.note,1,20),c.code_text_short)) AS immunization_data + FROM immunizations i1 + LEFT JOIN code_types ct ON ct.ct_key = 'CVX' + LEFT JOIN codes c ON c.code_type = ct.ct_id AND i1.cvx_code = c.code + WHERE i1.patient_id = ? + AND i1.added_erroneously = 0 + ORDER BY i1.administered_date DESC"; + $result = sqlStatement($sql, [$pid]); + + $imxList = []; while ($row = sqlFetchArray($result)) { - echo "  "; - echo "" . - text($row['immunization_data']); + $row['immunization_data'] = text($row['immunization_data']); // Figure out which name to use (ie. from cvx list or from the custom list) if ($GLOBALS['use_custom_immun_list']) { - echo generate_display_field(array('data_type' => '1','list_id' => 'immunizations'), $row['immunization_id']); + $row['field'] = generate_display_field(array('data_type' => '1', 'list_id' => 'immunizations'), $row['immunization_id']); } else { if (!(empty($row['cvx_text']))) { - echo htmlspecialchars(xl($row['cvx_text']), ENT_NOQUOTES); + $row['field'] = htmlspecialchars(xl($row['cvx_text']), ENT_NOQUOTES); } else { - echo generate_display_field(array('data_type' => '1','list_id' => 'immunizations'), $row['immunization_id']); + $row['field'] = generate_display_field(array('data_type' => '1', 'list_id' => 'immunizations'), $row['immunization_id']); } } - echo "
\n"; + $row['url'] = attr_js("immunizations.php?mode=edit&id=" . urlencode($row['id']) . "&csrf_token_form=" . urlencode(CsrfUtils::collectCsrfToken())); + $imxList[] = $row; } - ?> - -
"; - } ?> - - - - - - - - -
- - - - - - - -act(['prescription' => '', 'fragment' => '', 'patient_id' => $pid]); + $viewArgs['content'] = ob_get_contents(); + ob_end_clean(); + + echo $t->render('patient/card/rx.html.twig', $viewArgs); +endif; + +// Render Old Medications card if ($erx_upload_complete == 1) { - echo ""; + $id = "old_medication_ps_expand"; + $viewArgs = [ + 'title' => xl('Old Medication'), + 'label' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Edit', + 'btnLink' => "return load_location(\"${GLOBALS['webroot']}/interface/patient_file/summary/stats_full.php?active=all&category=medication\")", + 'linkMethod' => 'javascript', + 'auth' => true, + 'list' => $rxList, + ]; + + echo $t->render('patient/card/medical_problems.html.twig', $viewArgs); } - ?> -
- - - - - - - - - '1','list_id' => 'drug_units'), $row_currentMed['unit']); - $rin = generate_display_field(array('data_type' => '1','list_id' => 'drug_form'), $row_currentMed['form']); - $rroute = generate_display_field(array('data_type' => '1','list_id' => 'drug_route'), $row_currentMed['route']); - $rint = generate_display_field(array('data_type' => '1','list_id' => 'drug_interval'), $row_currentMed['interval']); - ?> - - - - - -
0) { - $unit = text($row_currentMed['size']) . " " . $runit . " "; - } - - echo $unit . " " . text($row_currentMed['dosage']) . " " . $rin . " " . $rroute . " " . $rint; ?>
-
- - render('patient/card/immunizations.html.twig', [ + 'title' => xl('Immunizations'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'btnLabel' => 'Edit', + 'btnLink' => 'immunizations.php', + 'linkMethod' => 'html', + 'imx' => $imxList, + ]); +endif; // End immunizations + +// Render the Prescriptions card if turned on +if (!$GLOBALS['disable_prescriptions'] && AclMain::aclCheckCore('patients', 'rx')) : + if (!$GLOBALS['erx_enable'] && $display_current_medications_below == 1) { + $sql = "SELECT * FROM prescriptions WHERE patient_id = ? AND active = '1'"; + $res = sqlStatement($sql, [$pid]); + + $rxArr = []; + while ($row = sqlFetchArray($res)) { + $row['unit'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_units'), $row['unit']); + $row['form'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_form'), $row['form']); + $row['route'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_route'), $row['route']); + $row['interval'] = generate_display_field(array('data_type' => '1', 'list_id' => 'drug_interval'), $row['interval']); + $rxArr[] = $row; } + $id = "current_prescriptions_ps_expand"; + $viewArgs = [ + 'title' => xl('Current Medications'), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'auth' => false, + 'rxList' => $rxArr, + ]; + + echo $t->render('patient/card/erx.html.twig', $viewArgs); + } - $bodyClass = "summary_item small"; - $widgetAuth = AclMain::aclCheckCore('patients', 'rx', '', array('write','addonly')); - $fixedWidth = false; - expand_collapse_widget($widgetTitle, $widgetLabel, $widgetButtonLabel, $widgetButtonLink, $widgetButtonClass, $linkMethod, $bodyClass, $widgetAuth, $fixedWidth); - if ($GLOBALS['weno_rx_enable']) { - echo ""; - } - } else { ?> - -
- + $id = "prescriptions_ps_expand"; + $viewArgs = [ + 'title' => xl("Prescriptions"), + 'id' => $id, + 'initiallyCollapsed' => (getUserSetting($id) == 0) ? false : true, + 'linkMethod' => "html", + 'btnLabel' => "Edit", + 'auth' => AclMain::aclCheckCore('patients', 'rx', '', ['write', 'addonly']), + ]; + + if ($GLOBALS['erx_enable']) { + $viewArgs['title'] = 'Prescription History'; + $viewArgs['btnLabel'] = 'Add/Edit eRx'; + $viewArgs['btnLink'] = "{$GLOBALS['webroot']}/interface/eRx.php?page=compose"; + } else { + $viewArgs['btnLink'] = "editScripts('{$GLOBALS['webroot']}/controller.php?prescription&list&id=" . attr_url($pid) . "')"; + $viewArgs['linkMethod'] = "javascript"; + $viewArgs['btnClass'] = "iframe rx_modal"; + } - act(array("prescription" => "", "fragment" => "", "patient_id" => $pid)); - ?> - - "; - } ?> - -
"; - // Old Medication Widget - $widgetTitle = "Old Medication"; - $widgetLabel = "old_medication"; - $widgetButtonLabel = xl("Edit"); - $widgetButtonLink = "load_location(\"${GLOBALS['webroot']}/interface/patient_file/summary/stats_full.php?active=all&category=medication\")"; - $widgetButtonClass = ""; - $linkMethod = "javascript"; - $bodyClass = "summary_item small"; - $widgetAuth = true; - $fixedWidth = false; - expand_collapse_widget($widgetTitle, $widgetLabel, $widgetButtonLabel, $widgetButtonLink, $widgetButtonClass, $linkMethod, $bodyClass, $widgetAuth, $fixedWidth); - $query_uploaded_old = "SELECT * FROM lists WHERE pid = ? AND type = 'medication' AND "; - $query_uploaded_old .= dateEmptySql('enddate'); - $query_uploaded_old .= "ORDER BY begdate"; - $res_uploaded_old = sqlStatement($query_uploaded_old, array($pid)); - echo ""; - while ($row = sqlFetchArray($res_uploaded_old)) { - // output each issue for the $ISSUE_TYPE - if (!$row['enddate'] && !$row['returndate']) { - $rowclass = "noend_noreturn"; - } elseif (!$row['enddate'] && $row['returndate']) { - $rowclass = "noend"; - } elseif ($row['enddate'] && !$row['returndate']) { - $rowclass = "noreturn"; - } - - echo " \n"; - echo " \n"; - echo " \n"; + $sql = [ + "SELECT * FROM lists WHERE pid = ? AND type = 'medication' AND", + dateEmptySql('enddate'), + "ORDER BY begdate" + ]; + $res = sqlStatement(implode(" ", $sql), [$pid]); + + $rxList = []; + while ($row = sqlFetchArray($res)) { + $rxList[] = $row; } - echo "
  " . text($row['title']) . "
"; - echo "
-
- diff --git a/interface/patient_file/summary/vitals_fragment.php b/interface/patient_file/summary/vitals_fragment.php index c2e59a29b45..8da9c061bb8 100644 --- a/interface/patient_file/summary/vitals_fragment.php +++ b/interface/patient_file/summary/vitals_fragment.php @@ -19,8 +19,7 @@ } ?> -
-
+
-
-
diff --git a/library/ajax/user_settings.php b/library/ajax/user_settings.php index 987b70aff3b..2abd34cf86c 100644 --- a/library/ajax/user_settings.php +++ b/library/ajax/user_settings.php @@ -15,6 +15,7 @@ require_once(dirname(__FILE__) . "/../user.inc"); use OpenEMR\Common\Csrf\CsrfUtils; +use Symfony\Component\HttpFoundation\Response; if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) { CsrfUtils::csrfNotVerified(); @@ -36,3 +37,7 @@ if ((isset($_POST['target'])) && (isset($_POST['setting']))) { setUserSetting($_POST['target'], $_POST['setting']); } + +// @todo This is crude, but if we make it here thre should be a proper response, so for now send a 200 but really we need better Response handling +$res = new Response(); +$res->send(); diff --git a/library/classes/Controller.class.php b/library/classes/Controller.class.php index c3e8b1e6e62..5931acd46c6 100644 --- a/library/classes/Controller.class.php +++ b/library/classes/Controller.class.php @@ -79,10 +79,10 @@ public function act($qarray) $_POST['process'] = "true"; } - $args = array_reverse(array_keys($qarray)); - $c_name = preg_replace("/[^A-Za-z0-9_]/", "", array_pop($args)); - $parts = explode("_", $c_name); - $name = ""; + $args = array_reverse(array_keys($qarray)); + $c_name = preg_replace("/[^A-Za-z0-9_]/", "", array_pop($args)); + $parts = explode("_", $c_name); + $name = ""; foreach ($parts as $p) { $name .= ucfirst($p); diff --git a/library/clinical_rules.php b/library/clinical_rules.php index ad29983de5d..cabd15337ed 100644 --- a/library/clinical_rules.php +++ b/library/clinical_rules.php @@ -68,7 +68,9 @@ function clinical_summary_widget($patient_id, $mode, $dateTarget = '', $organize // Display the actions $current_targets = array(); + echo "
"; foreach ($actions as $action) { + echo "
"; // Deal with plan names first if (isset($action['is_plan']) && $action['is_plan']) { echo "
"; @@ -147,32 +149,34 @@ function clinical_summary_widget($patient_id, $mode, $dateTarget = '', $organize if ($action['due_status']) { // Color code the status (red for past due, purple for due, green for not due and black for soon due) if ($action['due_status'] == "past_due") { - echo "  ("; + echo ""; } elseif ($action['due_status'] == "due") { - echo "  ("; + echo ""; } elseif ($action['due_status'] == "not_due") { - echo "  ("; + echo " '1','list_id' => 'rule_reminder_due_opt'), $action['due_status']) . ")"; + echo generate_display_field(array('data_type' => '1','list_id' => 'rule_reminder_due_opt'), $action['due_status']); } // Display the tooltip if (!empty($tooltip)) { - echo " " . $tooltip . "
"; - } else { - echo "
"; + echo " {$tooltip}"; } + echo "
"; + // Add the target(and rule id and room for future elements as needed) to the $current_targets array. // Only when $mode is reminders-due if ($mode == "reminders-due" && $GLOBALS['enable_alert_log']) { $target_temp = $action['category'] . ":" . $action['item']; $current_targets[$target_temp] = array('rule_id' => $action['rule_id'],'due_status' => $action['due_status']); } + echo "
"; } + echo "
"; // Compare the current with most recent action log (this function will also log the current actions) // Only when $mode is reminders-due diff --git a/library/options.inc.php b/library/options.inc.php index 3219e8733dd..74e64a0973b 100644 --- a/library/options.inc.php +++ b/library/options.inc.php @@ -53,8 +53,10 @@ use OpenEMR\Common\Acl\AclMain; use OpenEMR\Services\FacilityService; use OpenEMR\Services\PatientService; +use OpenEMR\Common\Twig\TwigContainer; $facilityService = new FacilityService(); +$twig = new TwigContainer('options'); $date_init = ""; $membership_group_number = 0; @@ -4472,22 +4474,24 @@ function dropdown_facility( echo " \n"; } -// Expand Collapse Widget -// This forms the header and functionality component of the widget. The information that is displayed -// then follows this function followed by a closing div tag -// -// $title is the title of the section (already translated) -// $label is identifier used in the tag id's and sql columns -// $buttonLabel is the button label text (already translated) -// $buttonLink is the button link information -// $buttonClass is any additional needed class elements for the button tag -// $linkMethod is the button link method ('javascript' vs 'html') -// $bodyClass is to set class(es) of the body -// $auth is a flag to decide whether to show the button -// $fixedWidth is to flag whether width is fixed -// $forceExpandAlways is a flag to force the widget to always be expanded -// -// TODO: Convert to accordion +/** + * Expand Collapse Widget + * This forms the header and functionality component of the widget. The information that is displayed + * then follows this function followed by a closing div tag + * + * @var $title is the title of the section (already translated) + * @var $label is identifier used in the tag id's and sql columns + * @var $buttonLabel is the button label text (already translated) + * @var $buttonLink is the button link information + * @var $buttonClass is any additional needed class elements for the button tag + * @var $linkMethod is the button link method ('javascript' vs 'html') + * @var $bodyClass is to set class(es) of the body + * @var $auth is a flag to decide whether to show the button + * @var $fixedWidth is to flag whether width is fixed + * @var $forceExpandAlways is a flag to force the widget to always be expanded + * + * @todo Convert to a modern layotu + */ function expand_collapse_widget($title, $label, $buttonLabel, $buttonLink, $buttonClass, $linkMethod, $bodyClass, $auth, $fixedWidth, $forceExpandAlways = false) { if ($fixedWidth) { diff --git a/library/patient.inc b/library/patient.inc index 35ccbd30d92..f0d6182b047 100644 --- a/library/patient.inc +++ b/library/patient.inc @@ -706,7 +706,7 @@ function getByPatientDemographicsFilter( function getPatientPID($args) { $pid = "%"; - $given = "pid, id, lname, fname, mname, providerID, DATE_FORMAT(DOB,'%m/%d/%Y') as DOB_TS"; + $given = "pid, id, lname, fname, mname, suffix, providerID, DATE_FORMAT(DOB,'%m/%d/%Y') as DOB_TS"; $orderby = "lname ASC, fname ASC"; $limit = "all"; $start = "0"; @@ -772,6 +772,40 @@ function getPatientName($pid) return $patientName; } +/** + * Get a patient's first name, middle name, last name and suffix if applicable. + * + * Returns a properly formatted, complete name when applicable. Example name + * would be "John B Doe Jr". No additional punctuation is added. Spaces are + * correctly omitted if the middle name of suffix does not apply. + * + * @var $pid int The Patient ID + * @returns string The Full Name + */ +function getPatientFullNameAsString(int $pid): string +{ + $ptData = getPatientPID(["pid" => $pid]); + $pt = $ptData[0]; + + if (empty($pt['lname'])) { + return ""; + } + + $name = $pt['fname']; + + if ($pt['mname']) { + $name .= " {$pt['mname']}"; + } + + $name .= " {$pt['lname']}"; + + if ($pt['suffix']) { + $name .= " {$pt['suffix']}"; + } + + return $name; +} + /* return a patient's name in the format FIRST LAST */ function getPatientNameFirstLast($pid) { diff --git a/src/Common/Twig/TwigExtension.php b/src/Common/Twig/TwigExtension.php index 4bfa33ab7cc..f6cc173dab1 100644 --- a/src/Common/Twig/TwigExtension.php +++ b/src/Common/Twig/TwigExtension.php @@ -50,6 +50,39 @@ function ($frow, $currentValue) { return $the_form; } ), + + new \Twig\TwigFunction( + 'tabRow', + function ($formType, $result1, $result2) { + ob_start(); + display_layout_tabs($formType, $result1, $result2); + $output = ob_get_contents(); + ob_end_clean(); + return $output; + } + ), + + new \Twig\TwigFunction( + 'tabData', + function ($formType, $result1, $result2) { + ob_start(); + display_layout_tabs_data($formType, $result1, $result2); + $output = ob_get_contents(); + ob_end_clean(); + return $output; + } + ), + + new \Twig\TwigFunction( + 'imageWidget', + function ($id, $category) { + ob_start(); + image_widget($id, $category); + $output = ob_get_contents(); + ob_end_clean(); + return $output; + } + ), ]; } @@ -121,6 +154,24 @@ function ($string) { function ($string) { return xls($string); } + ), + new \Twig\TwigFilter( + 'money', + function ($amount) { + return oeFormatMoney($amount); + } + ), + new \Twig\TwigFilter( + 'shortDate', + function ($string) { + return oeFormatShortDate($string); + } + ), + new \Twig\TwigFilter( + 'xlDocCategory', + function ($string) { + return xl_document_category($string); + } ) ]; } diff --git a/src/Menu/PatientMenuRole.php b/src/Menu/PatientMenuRole.php index 69175017a3b..030cfe9d0bf 100644 --- a/src/Menu/PatientMenuRole.php +++ b/src/Menu/PatientMenuRole.php @@ -196,7 +196,7 @@ public function displayHorizNavBarMenu() -EOB; + EOB; echo $str_bot . "\r\n"; return; } diff --git a/src/OeUI/OemrUI.php b/src/OeUI/OemrUI.php index b198fe9a5a1..b6d63a7f2a2 100644 --- a/src/OeUI/OemrUI.php +++ b/src/OeUI/OemrUI.php @@ -73,7 +73,7 @@ public function __construct($arrOeUiSettings = array()) { global $v_js_includes; - $this->heading = (!empty($arrOeUiSettings['include_patient_name']) && !empty($arrOeUiSettings['heading_title'])) ? ($arrOeUiSettings['heading_title'] ?? '') . " - " . getPatientNameFirstLast($_SESSION['pid']) : ($arrOeUiSettings['heading_title'] ?? ''); + $this->heading = (!empty($arrOeUiSettings['include_patient_name']) && !empty($arrOeUiSettings['heading_title'])) ? ($arrOeUiSettings['heading_title'] ?? '') . " - " . getPatientFullNameAsString($_SESSION['pid']) : ($arrOeUiSettings['heading_title'] ?? ''); $this->expandable = $arrOeUiSettings['expandable'] ?? null; $this->arrFiles = $arrOeUiSettings['expandable_files'] ?? null; $this->arrAction = array(($arrOeUiSettings['action'] ?? null), ($arrOeUiSettings['action_title'] ?? null), ($arrOeUiSettings['action_href'] ?? null)); diff --git a/templates/core/unauthorized.html.twig b/templates/core/unauthorized.html.twig new file mode 100644 index 00000000000..bcacc20bfa7 --- /dev/null +++ b/templates/core/unauthorized.html.twig @@ -0,0 +1,7 @@ +
+

+ {{ pageTitle|text ~ " Not Authorized"|xlt }} +

+
+ + diff --git a/templates/patient/card/adv_dir.html.twig b/templates/patient/card/adv_dir.html.twig new file mode 100644 index 00000000000..0aa31b166c5 --- /dev/null +++ b/templates/patient/card/adv_dir.html.twig @@ -0,0 +1,20 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +{% if counterFlag %} +
+ {% for a in advDirArr %} +
+
+ {{ a.docName|xlDocCategory|text }} + {{ a.docDate|shortDate|text }} +
+
+ {% endfor %} + {{ a }} +
+{% else %} + {{ "None{{Advanced_Directives}}"|xlt }} +{% endif %} + +{% endblock %} diff --git a/templates/patient/card/amendments.html.twig b/templates/patient/card/amendments.html.twig new file mode 100644 index 00000000000..a0e580e8e16 --- /dev/null +++ b/templates/patient/card/amendments.html.twig @@ -0,0 +1,11 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +{% if amendments|length > 0 %} + {% for a in amendments %} + {{ a.amendment_date|text }} {{ a.amendment_desc|text }}
+ {% endfor %} +{% else %} +

{{ "None{{Amendment}}"|xlt }}

+{% endif %} +{% endblock %} diff --git a/templates/patient/card/appointments.html.twig b/templates/patient/card/appointments.html.twig new file mode 100644 index 00000000000..9f1963609d2 --- /dev/null +++ b/templates/patient/card/appointments.html.twig @@ -0,0 +1,100 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% macro appointmentDetail(appointment) %} + {% set a = appointment %} +
+
+
+ {% if a.pc_catid not in therapyGroupCategories %} + + {% endif %} + {{ a.pc_catname|xlt }} + {% if a.pc_hometext %} {% endif %} + {% if a.pc_recurrtype %} {% endif %} + {% if a.pc_catid not in therapyGroupCategories %} + + {% endif %} +
+ + {{ a.dayName|xlt }},  + {{ a.pc_eventDate|shortDate|text }} + {{ a.pc_eventTime|text }} {{ a.displayMeridiem|xlt }} + +
+
+ {{ a.uname|text }} + {{ a.pc_statu|text }} + {% if a.pc_catid in therapyGroupCategories %} + {{ "Group name"|xlt }}: {{ a.groupName|text }} + {% endif %} + +
+
+{% endmacro %} + +{% macro additionalAppointment(appointmentDate) %} +
+
+ {{ appointmentDate|text }} (+) +
+
+{% endmacro %} + +{% macro sectionHeader(title, iconClasses) %} +
+
+  {{ title }} +
+
+{% endmacro %} + +{% macro noItems(text) %} +
+ {{ text }} +
+{% endmacro %} + +{% block content %} +
+ +{% if displayAppts %} + {{ _self.sectionHeader("Future Appointments", "fa-history fa-flip-horizontal")}} + {% if appts|length > 0 %} + {% for a in appts %} + {{ _self.appointmentDetail(a)}} + {% endfor %} + {% if extraApptDate %} + {{ _self.additionalAppointment(extraApptDate) }} + {% endif %} + {% else %} + {{ _self.noItems("No Appointments"|xlt)}} + {% endif %} +{% endif %} + +{% if displayRecurrAppts %} + {{ _self.sectionHeader("Recurring Appointments"|xlt, "fa-retweet")}} + {% if recurrAppts|length > 0 %} + {% for r in recurrAppts %} +
+
{{ r.pc_title|text }}
+
{{ r.pc_recurrspec|text }} {{ "until"|xlt }} {{ r.pc_endDate|text }}
+
+ {% endfor %} + {% else %} + {{ _self.noItems("No Recurring Appointments{{Appointments}}"|xlt)}} + {% endif %} +{% endif %} + +{% if displayPastAppts %} + {{ _self.sectionHeader("Past Appointments"|xlt, "fa-history")}} + {% if pastAppts|length > 0 %} + {% for pa in pastAppts %} + {{ _self.appointmentDetail(pa) }} + {% endfor %} + {% else %} + {{ _self.noItems("No Past Appointments{{Appointment}}"|xlt)}} + {% endif %} +{% endif %} + +
+{% endblock %} diff --git a/templates/patient/card/appointments_past.html.twig b/templates/patient/card/appointments_past.html.twig new file mode 100644 index 00000000000..73bd56eaf33 --- /dev/null +++ b/templates/patient/card/appointments_past.html.twig @@ -0,0 +1,12 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +{% for a in appt %} + + {{ a.dayname|xl|text }} {{ a.pc_eventDate|shortDate }} {{ "Status"|xlt }} + ({{ a.category }}) + + echo text("$disphour:$dispmin ") . xlt($displayMeridiem) . " "; + echo text($row['fname'] . " " . $row['lname']) . "
\n"; +{% endfor %} +{% endblock %} diff --git a/templates/patient/card/billing.html.twig b/templates/patient/card/billing.html.twig new file mode 100644 index 00000000000..8eb5fc8835f --- /dev/null +++ b/templates/patient/card/billing.html.twig @@ -0,0 +1,41 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +
+
+
{{ "Patient Balance Due"|xlt }}
+
{{ patientBalance|money|text }}
+
+
+
{{ "Insurance Balance Due"|xlt }}
+
{{ insuranceBalance|money|text }}
+
+
+
{{ "Total Balance Due"|xlt }}
+
{{ totalBalance|money|text }}
+
+ {% if billingNote %} +
+
{{ "Billing Note"|xlt }}
+
{{ billingNote|text }}
+
+ {% endif %} + {% if provider %} +
+
{{ "Primary Insurance"|xlt }}
+
{{ insName|text }}
+
+ {% if copay %} +
+
{{ "Copay"|xlt }}
+
{{ copay|text }}
+
+ {% endif %} +
+
{{ "Effective Date"|xlt }}
+
{{ effDate|shortDate|text }}
+
+ {% endif %} + +
+{% endblock %} diff --git a/templates/patient/card/card_base.html.twig b/templates/patient/card/card_base.html.twig new file mode 100644 index 00000000000..aa4a8b08da4 --- /dev/null +++ b/templates/patient/card/card_base.html.twig @@ -0,0 +1,25 @@ +
+
+
+ {% if forceAlwaysOpen == true %} + {{ title }} + {% else %} + + {% endif %} + {% if auth %} + {% if btnLabel == "Add" %} + {% set btnIcon = "fa-plus" %} + {% else %} + {% set btnIcon = "fa-pencil-alt" %} + {% endif %} + {# Display the Edit button #} +   + {% endif %} +
+
+
+ {% block content %}{% endblock %} +
+
+
+
diff --git a/templates/patient/card/demographics.html.twig b/templates/patient/card/demographics.html.twig new file mode 100644 index 00000000000..d06ef8e996b --- /dev/null +++ b/templates/patient/card/demographics.html.twig @@ -0,0 +1,10 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +
    + {{ tabRow('DEM', result, result2) }} +
+
+ {{ tabData('DEM', result, result2) }} +
+{% endblock %} diff --git a/templates/patient/card/eligibility.html.twig b/templates/patient/card/eligibility.html.twig new file mode 100644 index 00000000000..e69de29bb2d diff --git a/templates/patient/card/erx.html.twig b/templates/patient/card/erx.html.twig new file mode 100644 index 00000000000..94bbead0005 --- /dev/null +++ b/templates/patient/card/erx.html.twig @@ -0,0 +1,19 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +
+{% if rxList|length > 0 %} + + {% for rx in rxList %} +
+ {{ rx.drug|text }}
+ {{ rx.dosage|text }} {{ rx.form }}{{ rx.unit }}{{ rx.route }} {{ rx.interval }} +
+ {% endfor %} +{% else %} +
+ {{ "None{{Prescriptions}}"|xlt }} +
+{% endif %} +
+{% endblock %} diff --git a/templates/patient/card/immunizations.html.twig b/templates/patient/card/immunizations.html.twig new file mode 100644 index 00000000000..874835070ab --- /dev/null +++ b/templates/patient/card/immunizations.html.twig @@ -0,0 +1,17 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +
+{% if imx|length == 0 %} +
+ {{ "None{{Immunizations}}"|xlt }} +
+{% else %} + {% for i in imx %} + + {% endfor %} +{% endif %} +
+{% endblock %} diff --git a/templates/patient/card/insurance.html.twig b/templates/patient/card/insurance.html.twig new file mode 100644 index 00000000000..a1d76f1a986 --- /dev/null +++ b/templates/patient/card/insurance.html.twig @@ -0,0 +1,101 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} + +
+{% for c in ins %} +
+
+ {{ (c.idOld) ? "Old"|xlt ~ " " ~ c.type|capitalize : c.type|capitalize}} {{ "Insurance"|xlt }} + {% if c.dispFromDate == true %}{{ "from"|xlt}} {{ c.date|shortDate|text }} {% endif %} + {{ "until"|xlt }} {{ "Present"|xlt }} +
+
+
+ {% if c.insco is defined %} + {{ "Insurer"|xlt }} +
+ {{ c.insco.name|text|text }}
+ {{ c.insco.address.line1|text }}
+ {{ (c.insco.address.line2 != "") ? c.insco.address.line2|text ~ "
"|raw }} + {{ c.insco.address.city|text }} {{ c.insco.address.state|text }}, {{ c.insco.address.postal|text }} +
+ {% else %} + {{ "Unassigned"|xlt }} + {% endif %} +
+
+ {% set showState = (c.subscriber_state != "") ? true : false %} + {% set showCountry = (c.subscriber_country != "") ? true : false %} + {% set showPostal = (c.subscriber_postal_code != "") ? true : false %} + {{ "Subscriber"|xlt }} +
+ {{ c.subscriber_full_name|text }}{{ c.subscriber_relationship != "" ? " (" ~ c.subscriber_relationship|capitalize|text ~ ")" : "" }}
+ {{ c.subscriber_street|text }}
+ {{ c.subscriber_city|text }}{{ showState == true ? " " ~ c.subscriber_state|text : ""}}{{ showPostal == true ? ", " ~ c.subscriber_postal_code : "" }} + {{ showCountry == true ? " " ~ c.subscriber_country|text : ""}} +
+ {% if c.subscriber_ss != "" %} + {{ "S.S."|xlt }} + {{ c.subscriber_ss|text }}
+ {% endif %} + {% if c.subscriber_DOB %} + {{ "D.O.B."|xlt }} + {{ c.subscriber_DOB|shortDate|text }}
+ {% endif %} + {% if c.subscriber_phone %} + {{ "Phone"|xlt }} + {{ c.subscriber_phone|text }}
+ {% endif %} +
+
+ {% set showState = (c.subscriber_employer_state != "") ? true : false %} + {% set showCountry = (c.subscriber_employer_country != "") ? true : false %} + {% set showPostal = (c.subscriber_employer_postal_code != "") ? true : false %} + {{ "Subscriber Employer"|xlt }} +
+ {{ c.subscriber_employer|text }}
+ {{ c.subscriber_employer_street|text }}
+ {{ c.subscriber_employer_city|text }}{{ showState == true ? " " ~ c.subscriber_employer_state|text : ""}}{{ showPostal == true ? ", " ~ c.subscriber_employer_postal_code|text : "" }} + {{ showCountry == true ? " " ~ c.subscriber_employer_country|text : ""}} +
+
+
+
+
+
{{ "Plan Name"|xlt }}: {{ c.plan_name|text }}
+
{{ "Policy Number"|xlt }}: {{ c.policy_number|text }}
+
{{ "Group Number"|xlt }}: {{ c.group_number|text }}
+
+
+
{{ "Copay"|xlt }}: {{ c.copay|text }}
+
{{ "Accepts Assignment"|xlt }}: {{ c.accept_assignment == true ? "Yes"|xlt : "No"|xlt }}
+ {% if c.policy_type %} +
{{ "Secondary Medicare Type"|xlt }}: {{ c.policy_type|text }}
+ {% endif %} +
+
+
+{% endfor %} +
+ {% if enable_oa %} +
+
+ +
+ {{ eligibility }} +
+ {% else %} + {{ eligibility }} + {% endif %} +
+{% endblock %} diff --git a/templates/patient/card/loader.html.twig b/templates/patient/card/loader.html.twig new file mode 100644 index 00000000000..7f6759fb187 --- /dev/null +++ b/templates/patient/card/loader.html.twig @@ -0,0 +1,9 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +
+
+ {{ "Loading"|xlt}}... +
+
+{% endblock %} diff --git a/templates/patient/card/medical_problems.html.twig b/templates/patient/card/medical_problems.html.twig new file mode 100644 index 00000000000..52952a5a10f --- /dev/null +++ b/templates/patient/card/medical_problems.html.twig @@ -0,0 +1,41 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} + +
+{% if list|length == 0 %} + {% if listTouched == true %} +
+ {% if id == "allergy_ps_expand" %} + {{ "No Known Allergies"|xlt }} + {% else %} + {{ "None{{Issues}}"|xlt }} + {% endif %} +
+ {% else %} +
+ {{ "Nothing Recorded"|xlt }} +
+ {% endif %} +{% else %} + {% for l in list %} + {% if l.critical is defined %} + {% set classes = "bg-danger text-light font-weight-bold" %} + {% endif %} +
+
+
+ {{ l.title|text }} + {% if id == "allergy_ps_expand" %} + {{ l.reactionTitle|text }} + {% endif %} +
+ {% if id == "allergy_ps_expand" %} +
{{ l.severity|text }}
+ {% endif %} +
+
+ {% endfor %} +{% endif %} +
+{% endblock %} diff --git a/templates/patient/card/photo.html.twig b/templates/patient/card/photo.html.twig new file mode 100644 index 00000000000..17db9355e2e --- /dev/null +++ b/templates/patient/card/photo.html.twig @@ -0,0 +1,11 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +{% if patientIDCategoryID %} + {{ imageWidget(patientIDCategoryID, patientPhotoCategoryName)}} + + {% for p in photos %} + {{ imageWidget(p, patientPhotoCategoryName)}} + {% endfor %} +{% endif %} +{% endblock %} diff --git a/templates/patient/card/recall.html.twig b/templates/patient/card/recall.html.twig new file mode 100644 index 00000000000..3a0ea4d4686 --- /dev/null +++ b/templates/patient/card/recall.html.twig @@ -0,0 +1,18 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +
+{% if recallsAvailable %} + {% for r in recalls %} +
+ {{ r.reason|text }} + {{ r.date|shortDate|text }} +
+ {% endfor %} +{% else %} + +{% endif %} +
+{% endblock %} diff --git a/templates/patient/card/rx.html.twig b/templates/patient/card/rx.html.twig new file mode 100644 index 00000000000..621a930a615 --- /dev/null +++ b/templates/patient/card/rx.html.twig @@ -0,0 +1,5 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} + {{ content }} +{% endblock %} diff --git a/templates/patient/card/tab_base.html.twig b/templates/patient/card/tab_base.html.twig new file mode 100644 index 00000000000..a4d39b5bd79 --- /dev/null +++ b/templates/patient/card/tab_base.html.twig @@ -0,0 +1,10 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} +
    + {{ tabRow(tabID, result, result2) }} +
+
+ {{ tabData(tabID, result, result2) }} +
+{% endblock %} diff --git a/templates/patient/card/tp_il.html.twig b/templates/patient/card/tp_il.html.twig new file mode 100644 index 00000000000..3a0f3c4bef0 --- /dev/null +++ b/templates/patient/card/tp_il.html.twig @@ -0,0 +1,15 @@ +{% extends "patient/card/card_base.html.twig" %} + +{% block content %} + + +{% for r in formRows %} + + + +{% endfor %} +
+ {{ r.startDate|text }} {{ r.templateName|text }} +
+ +{% endblock %} diff --git a/templates/patient/dashboard_header.html.twig b/templates/patient/dashboard_header.html.twig new file mode 100644 index 00000000000..812b2871d7d --- /dev/null +++ b/templates/patient/dashboard_header.html.twig @@ -0,0 +1,47 @@ +{{ pageHeading }} + +{% if isDeceased %} +
+
+ {{ deceasedDays|text }} +
+
+{% endif %} + +{% if portalAuthorized == false %} +
+
+ {{ "Patient has not authorized the Patient Portal"|xlt }} +
+
+{% endif %} + +
+
+ {% if isAdmin == true and allowPatientDelete == true %} + {{ "Delete"|xlt }} + {% endif %} + {% if erxEnable %} + {{ "NewCrop MedEntry"|xlt }} + {{ "NewCrop Account Status"|xlt }} + {% endif %} + {% if portalAuthorized != false %} + {% if portalAuthorized.created == true %} + {% set class = "btn-redo" %} + {% set text = "Reset Portal Credentials"|xlt %} + {% else %} + {% set class = "btn-save" %} + {% set text = "Create Portal Credentials"|xlt %} + {% endif %} + {{ text|text }} + {% endif %} + + + {% if erxEnable %} +
+ {% endif %} +
+ +
diff --git a/templates/prescription/general_fragment.html b/templates/prescription/general_fragment.html index 9fe9d725302..41969bb2a13 100644 --- a/templates/prescription/general_fragment.html +++ b/templates/prescription/general_fragment.html @@ -9,30 +9,34 @@ * @copyright Copyright (c) 2019 Sherwin Gaddis * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 *} - - {if empty($prescriptions)} - - - - {else} - - - - - - - - {foreach from=$prescriptions item=prescription} - {if $prescription->get_active() > 0} - - - - - - - - {/if} - {/foreach} - {/if} -
  {xlt t='None'}
{xlt t='Drug'}   {xlt t='Qty'}{xlt t='Refills'}{xlt t='Filled'}
{$prescription->drug|text} {$prescription->get_size()|text}{$prescription->get_unit_display()|text}  - {$prescription->get_dosage_display()|text}{$prescription->get_quantity()|text}{$prescription->get_refills()|text}{$prescription->get_date_added()|text}
+{if empty($prescriptions)} +{xlt t='None'} +{else} +
+ + + + + + + + + + + + {foreach from=$prescriptions item=prescription} + {if $prescription->get_active() > 0} + + + + + + + + {/if} + {/foreach} + +
{xlt t='Drug'}{xlt t='Details'}{xlt t='Qty'}{xlt t='Refills'}{xlt t='Filled'}
{$prescription->drug|text} {$prescription->get_size()|text}{$prescription->get_unit_display()|text}  + {$prescription->get_dosage_display()|text}{$prescription->get_quantity()|text}{$prescription->get_refills()|text}{$prescription->get_date_added()|text}
+
+{/if}