3 * Patient Tracker (Patient Flow Board)
5 * This program displays the information entered in the Calendar program ,
6 * allowing the user to change status and view those changed here and in the Calendar
7 * Will allow the collection of length of time spent in each status
10 * @link http://www.open-emr.org
11 * @author Terry Hill <terry@lilysystems.com>
12 * @author Brady Miller <brady.g.miller@gmail.com>
13 * @copyright Copyright (c) 2015-2017 Terry Hill <terry@lillysystems.com>
14 * @copyright Copyright (c) 2017 Brady Miller <brady.g.miller@gmail.com>
15 * @copyright Copyright (c) 2017 Ray Magauran <magauran@medexbank.com>
16 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
19 require_once "../globals.php";
20 require_once "$srcdir/patient.inc";
21 require_once "$srcdir/options.inc.php";
22 require_once "$srcdir/patient_tracker.inc.php";
23 require_once "$srcdir/user.inc";
24 require_once "$srcdir/MedEx/API.php";
26 use OpenEMR\Core\Header
;
28 // These settings are sticky user preferences linked to a given page.
29 // mdsupport - user_settings prefix
30 $uspfx = substr(__FILE__
, strlen($webserver_root)) . '.';
31 $setting_new_window = prevSetting($uspfx, 'setting_new_window', 'setting_new_window', ' ');
32 // flow board and recall board share bootstrap settings:
33 $setting_bootstrap_submenu = prevSetting('', 'setting_bootstrap_submenu', 'setting_bootstrap_submenu', ' ');
34 $setting_selectors = prevSetting($uspfx, 'setting_selectors', 'setting_selectors', 'block');
35 $form_apptcat = prevSetting($uspfx, 'form_apptcat', 'form_apptcat', '');
36 $form_apptstatus = prevSetting($uspfx, 'form_apptstatus', 'form_apptstatus', '');
37 $facility = prevSetting($uspfx, 'form_facility', 'form_facility', '');
38 $provider = prevSetting($uspfx, 'form_provider', 'form_provider', $_SESSION['authUserID']);
40 if (($_POST['setting_new_window']) ||
41 ($_POST['setting_bootstrap_submenu']) ||
42 ($_POST['setting_selectors'])) {
43 // These are not form elements. We only ever change them via ajax, so exit now.
46 if ($_POST['saveCALLback'] == "Save") {
47 $sqlINSERT = "INSERT INTO medex_outgoing (msg_pc_eid,msg_pid,campaign_uid,msg_type,msg_reply,msg_extra_text)
49 (?,?,?,'NOTES','CALLED',?)";
50 sqlQuery($sqlINSERT, array($_POST['pc_eid'], $_POST['pc_pid'], $_POST['campaign_uid'], $_POST['txtCALLback']));
53 //set default start date of flow board to value based on globals
54 if (!$GLOBALS['ptkr_date_range']) {
55 $from_date = date('Y-m-d');
56 } elseif (!is_null($_REQUEST['form_from_date'])) {
57 $from_date = DateToYYYYMMDD($_REQUEST['form_from_date']);
58 } elseif (($GLOBALS['ptkr_start_date'])=='D0') {
59 $from_date = date('Y-m-d');
60 } elseif (($GLOBALS['ptkr_start_date'])=='B0') {
61 if (date(w
)==GLOBALS
['first_day_week']) {
62 //today is the first day of the week
63 $from_date = date('Y-m-d');
64 } elseif ($GLOBALS['first_day_week']==0) {
66 $from_date = date('Y-m-d', strtotime('previous sunday'));
67 } elseif ($GLOBALS['first_day_week']==1) {
69 $from_date = date('Y-m-d', strtotime('previous monday'));
70 } elseif ($GLOBALS['first_day_week']==6) {
72 $from_date = date('Y-m-d', strtotime('previous saturday'));
75 //shouldnt be able to get here...
76 $from_date = date('Y-m-d');
79 //set default end date of flow board to value based on globals
80 if ($GLOBALS['ptkr_date_range']) {
81 if (substr($GLOBALS['ptkr_end_date'], 0, 1) == 'Y') {
82 $ptkr_time = substr($GLOBALS['ptkr_end_date'], 1, 1);
83 $ptkr_future_time = mktime(0, 0, 0, date('m'), date('d'), date('Y') +
$ptkr_time);
84 } elseif (substr($GLOBALS['ptkr_end_date'], 0, 1) == 'M') {
85 $ptkr_time = substr($GLOBALS['ptkr_end_date'], 1, 1);
86 $ptkr_future_time = mktime(0, 0, 0, date('m') +
$ptkr_time, date('d'), date('Y'));
87 } elseif (substr($GLOBALS['ptkr_end_date'], 0, 1) == 'D') {
88 $ptkr_time = substr($GLOBALS['ptkr_end_date'], 1, 1);
89 $ptkr_future_time = mktime(0, 0, 0, date('m'), date('d') +
$ptkr_time, date('Y'));
92 $to_date = date('Y-m-d', $ptkr_future_time);
93 $to_date = !is_null($_REQUEST['form_to_date']) ?
DateToYYYYMMDD($_REQUEST['form_to_date']) : $to_date;
95 $to_date = date('Y-m-d');
98 $form_patient_name = !is_null($_POST['form_patient_name']) ?
$_POST['form_patient_name'] : null;
99 $form_patient_id = !is_null($_POST['form_patient_id']) ?
$_POST['form_patient_id'] : null;
102 $lres = sqlStatement("SELECT option_id, title FROM list_options WHERE list_id = ? AND activity=1", array('apptstat'));
103 while ($lrow = sqlFetchArray($lres)) {
104 // if exists, remove the legend character
105 if ($lrow['title'][1] == ' ') {
106 $splitTitle = explode(' ', $lrow['title']);
107 array_shift($splitTitle);
108 $title = implode(' ', $splitTitle);
110 $title = $lrow['title'];
112 $statuses_list[$lrow['option_id']] = $title;
115 if ($GLOBALS['medex_enable'] == '1') {
116 $query2 = "SELECT * FROM medex_icons";
117 $iconed = sqlStatement($query2);
118 while ($icon = sqlFetchArray($iconed)) {
119 $icons[$icon['msg_type']][$icon['msg_status']]['html'] = $icon['i_html'];
121 $MedEx = new MedExApi\
MedEx('MedExBank.com');
122 $logged_in = $MedEx->login();
123 $sql = "SELECT * FROM medex_prefs LIMIT 1";
124 $preferences = sqlStatement($sql);
125 $prefs = sqlFetchArray($preferences);
127 $results = $MedEx->campaign
->events($logged_in['token']);
128 foreach ($results['events'] as $event) {
129 if ($event['M_group'] != 'REMINDER') {
132 $icon = $icons[$event['M_type']]['SCHEDULED']['html'];
133 if ($event['E_timing'] == '1') {
134 $action = xl("before");
136 if ($event['E_timing'] == '2') {
137 $action = xl("before (PM)");
139 if ($event['E_timing'] == '3') {
140 $action = xl("after");
142 if ($event['E_timing'] == '4') {
143 $action = xl("after (PM)");
145 $days = ($event['E_fire_time'] == '1') ?
xl("day") : xl("days");
146 $current_events .= $icon . " " . (int)$event['E_fire_time'] . " " . text($days) . " " . text($action) . "<br />";
149 $current_events = $icons['SMS']['FAILED']['html'] . " " . xlt("Currently off-line");
153 if (!$_REQUEST['flb_table']) {
157 <title
><?php
echo xlt('Flow Board'); ?
></title
>
159 <?php Header
::setupHeader(['datetime-picker', 'jquery-ui', 'jquery-ui-cupertino', 'opener', 'pure']); ?
>
161 <script type
="text/javascript">
162 <?php
require_once "$srcdir/restoreSession.php"; ?
>
165 <link rel
="stylesheet" href
="<?php echo $GLOBALS['web_root']; ?>/library/css/bootstrap_navbar.css?v=<?php echo $v_js_includes; ?>" type
="text/css">
166 <script type
="text/javascript" src
="<?php echo $GLOBALS['web_root']; ?>/interface/main/messages/js/reminder_appts.js?v=<?php echo $v_js_includes; ?>"></script
>
168 <link rel
="shortcut icon" href
="<?php echo $webroot; ?>/sites/default/favicon.ico" />
170 <meta charset
="utf-8">
171 <meta http
-equiv
="X-UA-Compatible" content
="IE=edge">
172 <meta name
="author" content
="OpenEMR: MedExBank">
173 <meta name
="viewport" content
="width=device-width, initial-scale=1">
184 border
: solid black
0.5pt
;
185 box
-shadow
: 3px
3px
3px
#7b777760;
194 background
-color
: white
;
203 box
-shadow
: 2px
3px
9px
#c0c0c0;
212 font
-family
: Georgia
, serif
;
215 text
-transform
: uppercase
;
218 border
-bottom
: 2px solid
#455832;
222 .ui
-datepicker
-year
{
236 text
-decoration
:none
;
242 <body
class="body_top">
244 if (($GLOBALS['medex_enable'] == '1') && (empty($_REQUEST['nomenu']))) {
245 $MedEx->display
->navigation($logged_in);
248 <div
class="container-fluid" style
="margin-top: 20px;">
249 <div
class="row-fluid" id
="flb_selectors" style
="display:<?php echo attr($setting_selectors); ?>;">
250 <div
class="col-sm-12">
251 <div
class="showRFlow" id
="show_flows" style
="text-align:center;margin:20px auto;" name
="kiosk_hide">
252 <div
class="title"><?php
echo xlt('Flow Board'); ?
></div
>
253 <div name
="div_response" id
="div_response" class="nodisplay"></div
>
255 if ($GLOBALS['medex_enable'] == '1') {
259 $last_col_width = "nodisplay";
263 <form name
="flb" id
="flb" method
="post">
264 <div
class=" text-center row divTable" style
="width: 85%;padding: 10px 10px 0;margin: 10px auto;">
265 <div
class="col-sm-<?php echo $col_width; ?> text-center" style
="margin-top:15px;">
266 <select id
="form_apptcat" name
="form_apptcat" class="form-group ui-selectmenu-button ui-button ui-widget ui-selectmenu-button-closed ui-corner-all"
267 onchange
="refineMe('apptcat');" title
="">
269 $categories = fetchAppointmentCategories();
270 echo "<option value=''>" . xlt("Visit Categories") . "</option>";
271 while ($cat = sqlFetchArray($categories)) {
272 echo "<option value='" . attr($cat['id']) . "'";
273 if ($cat['id'] == $_POST['form_apptcat']) {
274 echo " selected='true' ";
276 echo ">" . xlt($cat['category']) . "</option>";
281 <select id
="form_apptstatus" name
="form_apptstatus" class="form-group ui-selectmenu-button ui-button ui-widget ui-selectmenu-button-closed ui-corner-all"
282 onchange
="refineMe();">
283 <option value
=""><?php
echo xlt("Visit Status"); ?
></option
>
286 $apptstats = sqlStatement("SELECT * FROM list_options WHERE list_id = 'apptstat' AND activity = 1 ORDER BY seq");
287 while ($apptstat = sqlFetchArray($apptstats)) {
288 echo "<option value='" . attr($apptstat['option_id']) . "'";
289 if ($apptstat['option_id'] == $_POST['form_apptstatus']) {
290 echo " selected='true' ";
292 echo ">" . xlt($apptstat['title']) . "</option>";
298 placeholder
="<?php echo xla('Patient Name'); ?>"
299 class="form-control input-sm" id
="form_patient_name" name
="form_patient_name"
300 value
="<?php echo ($form_patient_name) ? attr($form_patient_name) : ""; ?>"
301 onKeyUp
="refineMe();">
303 <div
class="col-sm-<?php echo $col_width; ?> text-center" style
="margin-top:15px;">
304 <select
class="form-group ui-selectmenu-button ui-button ui-widget ui-selectmenu-button-closed ui-corner-all" id
="form_facility" name
="form_facility"
306 $fac_sql = sqlStatement("SELECT * FROM facility ORDER BY id");
307 while ($fac = sqlFetchArray($fac_sql)) {
308 $true = ($fac['id'] == $_POST['form_facility']) ?
"selected=true" : '';
309 $select_facs .= "<option value=" . attr($fac['id']) . " " . $true . ">" . text($fac['name']) . "</option>\n";
312 if ($count_facs < '1') {
315 ?
> onchange
="refineMe('facility');">
316 <option value
=""><?php
echo xlt('All Facilities'); ?
></option
>
317 <?php
echo $select_facs; ?
>
321 // Build a drop-down list of ACTIVE providers.
322 $query = "SELECT id, lname, fname FROM users WHERE " .
323 "authorized = 1 AND active = 1 AND username > '' ORDER BY lname, fname"; #(CHEMED) facility filter
324 $ures = sqlStatement($query);
325 while ($urow = sqlFetchArray($ures)) {
326 $provid = $urow['id'];
327 $select_provs .= " <option value='" . attr($provid) . "'";
328 if (isset($_POST['form_provider']) && $provid == $_POST['form_provider']) {
329 $select_provs .= " selected";
330 } elseif (!isset($_POST['form_provider']) && $_SESSION['userauthorized'] && $provid == $_SESSION['authUserID']) {
331 $select_provs .= " selected";
333 $select_provs .= ">" . text($urow['lname']) . ", " . text($urow['fname']) . "\n";
338 <select
class="form-group ui-selectmenu-button ui-button ui-widget ui-selectmenu-button-closed ui-corner-all" id
="form_provider" name
="form_provider" <?php
339 if ($count_provs < '2') {
342 ?
> onchange
="refineMe('provider');">
343 <option value
="" selected
><?php
echo xlt('All Providers'); ?
></option
>
349 <input placeholder
="<?php echo xla('Patient ID'); ?>"
350 class="form-control input-sm" type
="text"
351 id
="form_patient_id" name
="form_patient_id"
352 value
="<?php echo ($form_patient_id) ? attr($form_patient_id) : ""; ?>"
353 onKeyUp
="refineMe();">
355 <div
class="col-sm-<?php echo $col_width; ?>">
356 <div style
="margin: 0 auto;" class="input-append">
357 <table
class="table-hover table-condensed" style
="margin:0 auto;">
359 if ($GLOBALS['ptkr_date_range'] == '1') {
364 $style = 'display:none;';
366 <tr style
="<?php echo $style; ?>" class="align-bottom">
367 <td
class="text-right align-bottom">
368 <label
for="flow_from"><?php
echo xlt('From'); ?
>:</label
></td
>
371 id
="form_from_date" name
="form_from_date"
372 class="datepicker form-control input-sm text-center"
373 value
="<?php echo attr(oeFormatShortDate($from_date)); ?>"
374 style
="max-width:140px;min-width:85px;">
377 <tr style
="<?php echo $style; ?>">
378 <td
class="text-right">
379 <label
for="flow_to"> 
; 
;<?php
echo xlt('To'); ?
>:</label
></td
>
382 id
="form_to_date" name
="form_to_date"
383 class="datepicker form-control input-sm text-center"
384 value
="<?php echo attr(oeFormatShortDate($to_date)); ?>"
385 style
="max-width:140px;min-width:85px;">
389 <td
class="text-center" colspan
="2">
390 <a id
="filter_submit" class="btn btn-primary"><?php
echo xla('Filter'); ?
></a
>
391 <input type
="hidden" id
="kiosk" name
="kiosk"
392 value
="<?php echo attr($_REQUEST['kiosk']); ?>">
398 <div
class="col-sm-<?php echo $col_width . " " . $last_col_width; ?> text-center">
400 if ($GLOBALS['medex_enable'] == '1') {
403 <div
class="text-center" style
="margin: 0 auto;">
404 <span
class="bold" style
="text-decoration:underline;font-size:1.2em;">MedEx
<?php
echo xlt('Reminders'); ?
></span
><br
/>
405 <div
class="text-left blockquote" style
="width: 65%;margin: 5px auto;">
406 <a href
="https://medexbank.com/cart/upload/index.php?route=information/campaigns&g=rem"
408 <?php
echo $current_events; ?
>
414 <div id
="message" class="warning"></div
>
421 <div
class="row-fluid">
422 <div
class="col-md-12">
423 <div
class=" text-center row divTable" style
="width: 85%;padding: 10px 10px 0;margin: 10px auto;">
424 <div
class="col-sm-12" id
="loader">
425 <div
class="text-center">
426 <i
class="fa fa-spinner fa-pulse fa-fw" style
="font-size: 140px; color: #0000cc; padding: 20px"></i
>
427 <h2
><?php
echo xlt('Loading data'); ?
>...</h2
>
430 <div id
="flb_table" name
="flb_table">
433 //end of if !$_REQUEST['flb_table'] - this is the table we fetch via ajax during a refreshMe() call
434 // get all appts for date range and refine view client side. very fast...
435 $appointments = array();
436 $datetime = date("Y-m-d H:i:s");
437 $appointments = fetch_Patient_Tracker_Events($from_date, $to_date, '', '', '', '', $form_patient_name, $form_patient_id);
438 $appointments = sortAppointments($appointments, 'date', 'time');
439 //grouping of the count of every status
440 $appointments_status = getApptStatus($appointments);
442 $chk_prov = array(); // list of providers with appointments
443 // Scan appointments for additional info
444 foreach ($appointments as $apt) {
445 $chk_prov[$apt['uprovider_id']] = $apt['ulname'] . ', ' . $apt['ufname'] . ' ' . $apt['umname'];
449 <div
class="col-sm-12 text-center" style
='margin:5px;'>
450 <span
class="hidden-xs" id
="status_summary">
452 $statuses_output = "<span style='margin:0 10px;'><em>" . xlt('Total patients') . ':</em> <span class="badge">' . text($appointments_status['count_all']) . "</span></span>";
453 unset($appointments_status['count_all']);
454 foreach ($appointments_status as $status_symbol => $count) {
455 $statuses_output .= " | <span style='margin:0 10px;'><em>" . text(xl_list_label($statuses_list[$status_symbol])) . ":</em> <span class='badge'>" . text($count) . "</span></span>";
457 echo $statuses_output;
460 <span id
="pull_kiosk_right" class="pull-right">
461 <a id
='setting_cog'><i
class="fa fa-cog fa-2x fa-fw"> 
;</i
></a
>
463 <label
for='setting_new_window' id
='settings'>
464 <input type
='checkbox' name
='setting_new_window' id
='setting_new_window'
465 value
='<?php echo $setting_new_window; ?>' <?php
echo $setting_new_window; ?
> />
466 <?php
echo xlt('Open Patient in New Window'); ?
>
468 <a id
='refreshme'><i
class="fa fa-refresh fa-2x fa-fw"> 
;</i
></a
>
469 <span
class="fa-stack fa-lg" id
="flb_caret" onclick
="toggleSelectors();"
470 title
="<?php echo xla('Show/Hide the Selection Area'); ?>"
471 style
="color:<?php echo $color = ($setting_selectors == 'none') ? 'red' : 'black'; ?>;">
472 <i
class="fa fa-square-o fa-stack-2x"></i
>
474 class='fa fa-caret-<?php echo $caret = ($setting_selectors == 'none
') ? 'down
' : 'up
'; ?> fa-stack-1x'></i
>
477 <a
class='btn btn-primary' onclick
="print_FLB();"> <?php
echo xlt('Print'); ?
> </a
>
479 <?php
if ($GLOBALS['new_tabs_layout']) { ?
>
480 <a
class='btn btn-primary' onclick
="kiosk_FLB();"> <?php
echo xlt('Kiosk'); ?
> </a
>
485 <div
class="col-sm-12 textclear" >
487 <table
class="table table-responsive table-condensed table-hover table-bordered">
489 <tr bgcolor
="#cccff" class="small bold text-center">
490 <?php
if ($GLOBALS['ptkr_show_pid']) { ?
>
491 <td
class="dehead hidden-xs text-center" name
="kiosk_hide">
492 <?php
echo xlt('PID'); ?
>
495 <td
class="dehead text-center" style
="max-width:150px;">
496 <?php
echo xlt('Patient'); ?
>
498 <?php
if ($GLOBALS['ptkr_visit_reason'] == '1') { ?
>
499 <td
class="dehead hidden-xs text-center" name
="kiosk_hide">
500 <?php
echo xlt('Reason'); ?
>
503 <?php
if ($GLOBALS['ptkr_show_encounter']) { ?
>
504 <td
class="dehead text-center hidden-xs hidden-sm" name
="kiosk_hide">
505 <?php
echo xlt('Encounter'); ?
>
509 <?php
if ($GLOBALS['ptkr_date_range'] == '1') { ?
>
510 <td
class="dehead hidden-xs text-center" name
="kiosk_hide">
511 <?php
echo xlt('Appt Date'); ?
>
514 <td
class="dehead text-center">
515 <?php
echo xlt('Appt Time'); ?
>
517 <td
class="dehead hidden-xs text-center">
518 <?php
echo xlt('Arrive Time'); ?
>
520 <td
class="dehead visible-xs hidden-sm hidden-md hidden-lg text-center">
521 <?php
echo xlt('Arrival'); ?
>
523 <td
class="dehead hidden-xs text-center">
524 <?php
echo xlt('Appt Status'); ?
>
526 <td
class="dehead hidden-xs text-center">
527 <?php
echo xlt('Current Status'); ?
>
529 <td
class="dehead visible-xs hidden-sm hidden-md hidden-lg text-center">
530 <?php
echo xlt('Current'); ?
>
532 <td
class="dehead hidden-xs text-center" name
="kiosk_hide">
533 <?php
echo xlt('Visit Type'); ?
>
535 <?php
if (count($chk_prov) > 1) { ?
>
536 <td
class="dehead text-center hidden-xs">
537 <?php
echo xlt('Provider'); ?
>
540 <td
class="dehead text-center">
541 <?php
echo xlt('Total Time'); ?
>
543 <td
class="dehead hidden-xs text-center">
544 <?php
echo xlt('Check Out Time'); ?
>
546 <td
class="dehead visible-xs hidden-sm hidden-md hidden-lg text-center">
547 <?php
echo xlt('Out Time'); ?
>
550 if ($GLOBALS['ptkr_show_staff']) { ?
>
551 <td
class="dehead hidden-xs hidden-sm text-center" name
="kiosk_hide">
552 <?php
echo xlt('Updated By'); ?
>
556 if ($_REQUEST['kiosk'] != '1') {
557 if ($GLOBALS['drug_screen']) { ?
>
558 <td
class="dehead center hidden-xs " name
="kiosk_hide">
559 <?php
echo xlt('Random Drug Screen'); ?
>
561 <td
class="dehead center hidden-xs " name
="kiosk_hide">
562 <?php
echo xlt('Drug Screen Completed'); ?
>
571 $prev_appt_date_time = "";
572 foreach ($appointments as $appointment) {
573 // Collect appt date and set up squashed date for use below
574 $date_appt = $appointment['pc_eventDate'];
575 $date_squash = str_replace("-", "", $date_appt);
576 if (empty($appointment['room']) && ($logged_in)) {
577 //Patient has not arrived yet, display MedEx Reminder info
578 //one icon per type of response.
579 //If there was a SMS dialog, display it as a mouseover/title
580 //Display date received also as mouseover title.
587 $icon_here = array();
593 $query = "SELECT * FROM medex_outgoing WHERE msg_pc_eid =? ORDER BY msg_date";
594 $myMedEx = sqlStatement($query, array($appointment['eid']));
596 * Each row for this pc_eid in the medex_outgoing table represents an event.
597 * Every event is recorded in $prog_text.
598 * A modality is represented by an icon (eg mail icon, phone icon, text icon).
599 * The state of the Modality is represented by the color of the icon:
603 * SENT/in process = yellow
605 * Icons are displayed in their highest state.
608 while ($row = sqlFetchArray($myMedEx)) {
609 // Need to convert $row['msg_date'] to localtime (stored as GMT) & then oeFormatShortDate it.
610 // I believe there is a new GLOBAL for server timezone??? If so, it will be easy.
611 // If not we need to import it from Medex through medex_preferences. It should really be in openEMR though.
612 // Delete when we figure this out.
614 if (!empty($row['msg_extra_text'])) {
615 $local = attr($row['msg_extra_text']) . " |";
617 $prog_text .= attr(oeFormatShortDate($row['msg_date'])) . " :: " . attr($row['msg_type']) . " : " . attr($row['msg_reply']) . " | " . $local . " |";
619 if ($row['msg_reply'] == 'Other') {
620 $other_title .= $row['msg_extra_text'] . "\n";
621 $icon_extra .= str_replace(
623 attr(oeFormatShortDate($row['msg_date'])) . "\n" . xla('Patient Message') . ":\n" . attr($row['msg_extra_text']) . "\n",
624 $icons[$row['msg_type']]['EXTRA']['html']
627 } elseif ($row['msg_reply'] == "FAILED") {
628 $appointment[$row['msg_type']]['stage'] = "FAILED";
629 $icon_here[$row['msg_type']] = $icons[$row['msg_type']]['FAILED']['html'];
630 } elseif (($row['msg_reply'] == "CONFIRMED") ||
($FINAL)) {
631 $appointment[$row['msg_type']]['stage'] = "CONFIRMED";
632 $FINAL = $icons[$row['msg_type']]['CONFIRMED']['html'];
633 $icon_here[$row['msg_type']] = $FINAL;
635 } elseif ($row['msg_type'] == "NOTES") {
637 $FINAL = $icons['NOTES']['CALLED']['html'];
638 $FINAL = str_replace("Call Back: COMPLETED", attr(oeFormatShortDate($row['msg_date'])) . " :: " . xla('Callback Performed') . " | " . xla('NOTES') . ": " . $row['msg_extra_text'] . " | ", $FINAL);
639 $icon_CALL = $icon_4_call;
641 } elseif (($row['msg_reply'] == "READ") ||
($appointment[$row['msg_type']]['stage'] == "READ")) {
642 $appointment[$row['msg_type']]['stage'] = "READ";
643 $icon_here[$row['msg_type']] = $icons[$row['msg_type']]['READ']['html'];
644 } elseif (($row['msg_reply'] == "SENT") ||
($appointment[$row['msg_type']]['stage'] == "SENT")) {
645 $appointment[$row['msg_type']]['stage'] = "SENT";
646 $icon_here[$row['msg_type']] = $icons[$row['msg_type']]['SENT']['html'];
647 } elseif (($row['msg_reply'] == "To Send") ||
(empty($appointment['stage']))) {
648 if (($appointment[$row['msg_type']]['stage'] != "CONFIRMED") &&
649 ($appointment[$row['msg_type']]['stage'] != "READ") &&
650 ($appointment[$row['msg_type']]['stage'] != "SENT") &&
651 ($appointment[$row['msg_type']]['stage'] != "FAILED")) {
652 $appointment[$row['msg_type']]['stage'] = "QUEUED";
653 $icon_here[$row['msg_type']] = $icons[$row['msg_type']]['SCHEDULED']['html'];
656 //these are additional icons if present
657 if (($row['msg_reply'] == "CALL") && (!$CALLED)) {
659 $icon_4_CALL = $icons[$row['msg_type']]['CALL']['html'];
660 $icon_CALL = "<span onclick=\"doCALLback('" . attr($date_squash) . "','" . attr($appointment['eid']) . "','" . attr($appointment['pc_cattype']) . "')\">" . $icon_4_CALL . "</span>
661 <span class='hidden' name='progCALLback_" . attr($appointment['eid']) . "' id='progCALLback_" . attr($appointment['eid']) . "'>
662 <form id='notation_" . attr($appointment['eid']) . "' method='post'
664 <h4>" . xlt('Call Back Notes') . ":</h4>
665 <input type='hidden' name='pc_eid' id='pc_eid' value='" . attr($appointment['eid']) . "'>
666 <input type='hidden' name='pc_pid' id='pc_pid' value='" . attr($appointment['pc_pid']) . "'>
667 <input type='hidden' name='campaign_uid' id='campaign_uid' value='" . attr($row['campaign_uid']) . "'>
668 <textarea name='txtCALLback' id='txtCALLback' rows=6 cols=20></textarea>
669 <input type='submit' name='saveCALLback' id='saveCALLback' value='" . xla("Save") ."'>
673 } elseif ($row['msg_reply'] == "STOP") {
674 $icon2_here .= $icons[$row['msg_type']]['STOP']['html'];
675 } elseif ($row['msg_reply'] == "Other") {
676 $icon2_here .= $icons[$row['msg_type']]['Other']['html'];
677 } elseif ($row['msg_reply'] == "CALLED") {
678 $icon2_here .= $icons[$row['msg_type']]['CALLED']['html'];
681 //if pc_apptstatus == '-', update it now to=status
682 if (!empty($other_title)) {
683 $appointment['messages'] = $icon2_here . $icon_extra;
687 // Collect variables and do some processing
688 $docname = $chk_prov[$appointment['uprovider_id']];
689 if (strlen($docname) <= 3) {
692 $ptname = $appointment['lname'] . ', ' . $appointment['fname'] . ' ' . $appointment['mname'];
693 $ptname_short = $appointment['fname'][0] . " " . $appointment['lname'][0];
694 $appt_enc = $appointment['encounter'];
695 $appt_eid = (!empty($appointment['eid'])) ?
$appointment['eid'] : $appointment['pc_eid'];
696 $appt_pid = (!empty($appointment['pid'])) ?
$appointment['pid'] : $appointment['pc_pid'];
697 if ($appt_pid == 0) {
698 continue; // skip when $appt_pid = 0, since this means it is not a patient specific appt slot
700 $status = (!empty($appointment['status']) && (!is_numeric($appointment['status']))) ?
$appointment['status'] : $appointment['pc_apptstatus'];
701 $appt_room = (!empty($appointment['room'])) ?
$appointment['room'] : $appointment['pc_room'];
702 $appt_time = (!empty($appointment['appttime'])) ?
$appointment['appttime'] : $appointment['pc_startTime'];
703 $tracker_id = $appointment['id'];
705 if ($GLOBALS['ptkr_visit_reason']) {
706 $reason_visit = $appointment['pc_hometext'];
708 $newarrive = collect_checkin($tracker_id);
709 $newend = collect_checkout($tracker_id);
710 $colorevents = (collectApptStatusSettings($status));
711 $bgcolor = $colorevents['color'];
712 $statalert = $colorevents['time_alert'];
713 // process the time to allow items with a check out status to be displayed
714 if (is_checkout($status) && (($GLOBALS['checkout_roll_off'] > 0) && strlen($form_apptstatus) != 1)) {
715 $to_time = strtotime($newend);
716 $from_time = strtotime($datetime);
717 $display_check_out = round(abs($from_time - $to_time) / 60, 0);
718 if ($display_check_out >= $GLOBALS['checkout_roll_off']) {
723 echo '<tr data-apptstatus="' . attr($appointment['pc_apptstatus']) . '"
724 data-apptcat="' . attr($appointment['pc_catid']) . '"
725 data-facility="' . attr($appointment['pc_facility']) . '"
726 data-provider="' . attr($appointment['uprovider_id']) . '"
727 data-pid="' . attr($appointment['pc_pid']) . '"
728 data-pname="' . attr($ptname) . '"
730 bgcolor="' . attr($bgcolor) . '" >';
731 if ($GLOBALS['ptkr_show_pid']) {
733 <td
class="detail hidden-xs" align
="center" name
="kiosk_hide">
734 <?php
echo text($appt_pid); ?
>
740 <td
class="detail text-center hidden-xs" name
="kiosk_hide">
742 onclick
="return topatient('<?php echo attr($appt_pid); ?>','<?php echo attr($appt_enc); ?>')">
743 <?php
echo text($ptname); ?
></a
>
745 <td
class="detail text-center visible-xs hidden-sm hidden-md hidden-lg"
746 style
="white-space: normal;" name
="kiosk_hide">
748 onclick
="return topatient('<?php echo attr($appt_pid); ?>','<?php echo attr($appt_enc); ?>')">
749 <?php
echo text($ptname_short); ?
></a
>
752 <td
class="detail text-center" style
="white-space: normal;" name
="kiosk_show">
754 onclick
="return topatient('<?php echo attr($appt_pid); ?>','<?php echo attr($appt_enc); ?>')">
755 <?php
echo text($ptname_short); ?
></a
>
759 <?php
if ($GLOBALS['ptkr_visit_reason']) { ?
>
760 <td
class="detail hidden-xs text-center" name
="kiosk_hide">
761 <?php
echo text($reason_visit) ?
>
764 <?php
if ($GLOBALS['ptkr_show_encounter']) { ?
>
765 <td
class="detail hidden-xs hidden-sm text-center" name
="kiosk_hide">
766 <?php
if ($appt_enc != 0) {
767 echo text($appt_enc);
771 if ($GLOBALS['ptkr_date_range'] == '1') { ?
>
772 <td
class="detail hidden-xs text-center" name
="kiosk_hide">
773 <?php
echo text(oeFormatShortDate($appointment['pc_eventDate']));
777 <td
class="detail" align
="center">
778 <?php
echo oeFormatTime($appt_time) ?
>
780 <td
class="detail text-center">
783 echo oeFormatTime($newarrive);
787 <td
class="detail hidden-xs text-center small">
788 <?php
if (empty($tracker_id)) { //for appt not yet with tracker id and for recurring appt ?>
789 <a onclick
="return calendarpopup(<?php echo attr($appt_eid) . "," . attr($date_squash); // calls popup for add edit calendar event?>)">
791 <a onclick
="return bpopup(<?php echo attr($tracker_id); // calls popup for patient tracker status?>)">
793 if ($appointment['room'] > '') {
794 echo getListItemTitle('patient_flow_board_rooms', $appt_room);
796 echo text(getListItemTitle("apptstat", $status)); // drop down list for appointment status
803 //time in current status
804 $to_time = strtotime(date("Y-m-d H:i:s"));
806 if (strtotime($newend) != '') {
807 $from_time = strtotime($newarrive);
808 $to_time = strtotime($newend);
811 $from_time = strtotime($appointment['start_datetime']);
815 $timecheck = round(abs($to_time - $from_time) / 60, 0);
816 if ($timecheck >= $statalert && ($statalert > '0')) { // Determine if the time in status limit has been reached.
817 echo "<td class='text-center js-blink-infinite small' nowrap> "; // and if so blink
819 echo "<td class='detail text-center' nowrap> "; // and if not do not blink
821 if (($yestime == '1') && ($timecheck >= 1) && (strtotime($newarrive) != '')) {
822 echo text($timecheck . ' ' . ($timecheck >= 2 ?
xl('minutes') : xl('minute')));
823 } else if ($icon_here ||
$icon2_here ||
$icon_CALL) {
824 echo "<span style='font-size:0.7em;' onclick='return calendarpopup(" . attr($appt_eid) . "," . attr($date_squash) . ")'>" . implode($icon_here) . $icon2_here . "</span> " . $icon_CALL;
825 } else if ($logged_in) {
826 $pat = $MedEx->display
->possibleModalities($appointment);
827 echo "<span style='font-size:0.7em;'>" . $pat['SMS'] . $pat['AVM'] . $pat['EMAIL'] . "</span>";
829 //end time in current status
832 <td
class="detail hidden-xs text-center" name
="kiosk_hide">
833 <?php
echo xlt($appointment['pc_title']); ?
>
836 if (count($chk_prov) > 1) { ?
>
837 <td
class="detail text-center hidden-xs">
838 <?php
echo text($docname); ?
>
842 <td
class="detail text-center">
844 // total time in practice
845 if (strtotime($newend) != '') {
846 $from_time = strtotime($newarrive);
847 $to_time = strtotime($newend);
849 $from_time = strtotime($newarrive);
850 $to_time = strtotime(date("Y-m-d H:i:s"));
852 $timecheck2 = round(abs($to_time - $from_time) / 60, 0);
853 if (strtotime($newarrive) != '' && ($timecheck2 >= 1)) {
854 echo text($timecheck2 . ' ' . ($timecheck2 >= 2 ?
xl('minutes') : xl('minute')));
856 // end total time in practice
857 echo text($appointment['pc_time']); ?
>
859 <td
class="detail text-center">
864 if ($GLOBALS['ptkr_show_staff'] == '1') {
866 <td
class="detail hidden-xs hidden-sm text-center" name
="kiosk_hide">
867 <?php
echo text($appointment['user']) ?
>
871 if ($GLOBALS['drug_screen']) {
872 if (strtotime($newarrive) != '') { ?
>
873 <td
class="detail hidden-xs text-center" name
="kiosk_hide">
875 if (text($appointment['random_drug_test']) == '1') {
884 if (strtotime($newarrive) != '' && $appointment['random_drug_test'] == '1') { ?
>
885 <td
class="detail hidden-xs text-center" name
="kiosk_hide">
887 if (strtotime($newend) != '') {
888 // the following block allows the check box for drug screens to be disabled once the status is check out ?>
889 <input type
=checkbox disabled
='disable' class="drug_screen_completed"
890 id
="<?php echo htmlspecialchars($appointment['pt_tracker_id'], ENT_NOQUOTES) ?>" <?php
if ($appointment['drug_screen_completed'] == "1") {
896 <input type
=checkbox
class="drug_screen_completed"
897 id
='<?php echo htmlspecialchars($appointment['pt_tracker_id
'], ENT_NOQUOTES) ?>'
898 name
="drug_screen_completed" <?php
if ($appointment['drug_screen_completed'] == "1") {
919 if (!$_REQUEST['flb_table']) { ?
>
924 </div
><?php
//end container ?>
925 <!-- form used to open a
new top level window when a patient row is clicked
-->
926 <form name
='fnew' method
='post' target
='_blank'
927 action
='../main/main_screen.php?auth=login&site=<?php echo attr($_SESSION['site_id
']); ?>'>
928 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(collectCsrfToken()); ?>" />
929 <input type
='hidden' name
='patientID' value
='0'/>
930 <input type
='hidden' name
='encounterID' value
='0'/>
933 <?php
echo myLocalJS(); ?
>
937 } //end of second !$_REQUEST['flb_table']
939 //$content = ob_get_clean();
947 <script type
="text/javascript">
948 var auto_refresh
= null;
949 //this can be refined to redact HIPAA material using @media print options.
950 top
.restoreSession();
952 window
.parent
.$
("[name='flb']").attr('allowFullscreen', 'true');
954 $
(this
).attr('allowFullscreen', 'true');
957 if ($_REQUEST['kiosk'] == '1') { ?
>
958 $
("[name='kiosk_hide']").hide();
959 $
("[name='kiosk_show']").show();
961 $
("[name='kiosk_hide']").show();
962 $
("[name='kiosk_show']").hide();
964 function print_FLB() {
968 function toggleSelectors() {
969 if ($
("#flb_selectors").css('display') === 'none') {
970 $
.post("<?php echo $GLOBALS['webroot'] . "/interface/patient_tracker
/patient_tracker
.php
"; ?>", {
971 'setting_selectors': 'block',
972 success
: function (data
) {
974 $
("#flb_selectors").slideToggle();
975 $
("#flb_caret").css('color', '#000');
979 $
.post("<?php echo $GLOBALS['webroot'] . "/interface/patient_tracker
/patient_tracker
.php
"; ?>", {
980 'setting_selectors': 'none',
981 success
: function (data
) {
982 $
("#flb_selectors").slideToggle();
983 $
("#flb_caret").css('color', 'red');
987 $
("#print_caret").toggleClass('fa-caret-up').toggleClass('fa-caret-down');
991 * This function refreshes the whole flb_table according to our to/from dates.
993 function refreshMe(fromTimer
) {
995 if(typeof fromTimer
=== 'undefined' ||
!fromTimer
) {
996 //Show loader in the first loading or manual loading not by timer
997 $
("#flb_table").html('');
1001 var startRequestTime
= Date
.now();
1002 top
.restoreSession();
1003 var posting
= $
.post('../patient_tracker/patient_tracker.php', {
1005 form_from_date
: $
("#form_from_date").val(),
1006 form_to_date
: $
("#form_to_date").val(),
1007 form_facility
: $
("#form_facility").val(),
1008 form_provider
: $
("#form_provider").val(),
1009 form_apptstatus
: $
("#form_apptstatus").val(),
1010 form_patient_name
: $
("#form_patient_name").val(),
1011 form_patient_id
: $
("#form_patient_id").val(),
1012 form_apptcat
: $
("#form_apptcat").val(),
1013 kiosk
: $
("#kiosk").val()
1016 //minimum 400 ms of loader (In the first loading or manual loading not by timer)
1017 if((typeof fromTimer
=== 'undefined' ||
!fromTimer
) && Date
.now() - startRequestTime
< 400 ){
1018 setTimeout(drawTable
, 500, data
);
1025 function drawTable(data
) {
1027 $
('#loader').hide();
1028 $
("#flb_table").html(data
);
1029 if ($
("#kiosk").val() === '') {
1030 $
("[name='kiosk_hide']").show();
1031 $
("[name='kiosk_show']").hide();
1033 $
("[name='kiosk_hide']").hide();
1034 $
("[name='kiosk_show']").show();
1043 function refreshme() {
1044 // Just need this to support refreshme call from the popup used for recurrent appt
1049 * This function hides all then shows only the flb_table rows that match our selection, client side.
1050 * It is called on initial load, on refresh and 'onchange/onkeyup' of a flow board parameter.
1052 function refineMe() {
1053 var apptcatV
= $
("#form_apptcat").val();
1054 var apptstatV
= $
("#form_apptstatus").val();
1055 var facV
= $
("#form_facility").val();
1056 var provV
= $
("#form_provider").val();
1057 var pidV
= String($
("#form_patient_id").val());
1058 var pidRE
= new RegExp(pidV
, 'g');
1059 var pnameV
= $
("#form_patient_name").val();
1060 var pnameRE
= new RegExp(pnameV
, 'ig');
1062 //and hide what we don't want to show
1063 $
('#flb_table tbody tr').hide().filter(function () {
1064 var d
= $
(this
).data();
1065 meets_cat
= (apptcatV
=== '') ||
(apptcatV
== d
.apptcat
);
1066 meets_stat
= (apptstatV
=== '') ||
(apptstatV
== d
.apptstatus
);
1067 meets_fac
= (facV
=== '') ||
(facV
== d
.facility
);
1068 meets_prov
= (provV
=== '') ||
(provV
== d
.provider
);
1069 meets_pid
= (pidV
=== '');
1070 if ((pidV
> '') && pidRE
.test(d
.pid
)) {
1073 meets_pname
= (pnameV
=== '');
1074 if ((pnameV
> '') && pnameRE
.test(d
.pname
)) {
1077 return meets_pname
&& meets_pid
&& meets_cat
&& meets_stat
&& meets_fac
&& meets_prov
;
1081 // popup for patient tracker status
1082 function bpopup(tkid
) {
1083 top
.restoreSession();
1084 dlgopen('../patient_tracker/patient_tracker_status.php?tracker_id=' + tkid
, '_blank', 500, 250);
1088 // popup for calendar add edit
1089 function calendarpopup(eid
, date_squash
) {
1090 top
.restoreSession();
1091 dlgopen('../main/calendar/add_edit_event.php?eid=' + eid +
'&date=' + date_squash
, '_blank', 775, 500);
1095 // used to display the patient demographic and encounter screens
1096 function topatient(newpid
, enc
) {
1097 if ($
('#setting_new_window').val() === 'checked') {
1098 openNewTopWindow(newpid
, enc
);
1101 top
.restoreSession();
1103 top
.RTop
.location
= "<?php echo $GLOBALS['webroot']; ?>/interface/patient_file/summary/demographics.php?set_pid=" + newpid +
"&set_encounterid=" + enc
;
1106 top
.RTop
.location
= "<?php echo $GLOBALS['webroot']; ?>/interface/patient_file/summary/demographics.php?set_pid=" + newpid
;
1111 function doCALLback(eventdate
, eid
, pccattype
) {
1112 $
("#progCALLback_" + eid
).parent().removeClass('js-blink-infinite').css('animation-name', 'none');
1113 $
("#progCALLback_" + eid
).removeClass("hidden");
1114 clearInterval(auto_refresh
);
1117 // opens the demographic and encounter screens in a new window
1118 function openNewTopWindow(newpid
, newencounterid
) {
1119 document
.fnew
.patientID
.value
= newpid
;
1120 document
.fnew
.encounterID
.value
= newencounterid
;
1121 top
.restoreSession();
1122 document
.fnew
.submit();
1125 //opens the two-way SMS phone app
1129 function SMS_bot(pid
) {
1130 top
.restoreSession();
1131 var from
= '<?php echo attr($from_date); ?>';
1132 var to
= '<?php echo attr($to_date); ?>';
1133 var oefrom
= '<?php echo attr(oeFormatShortDate($from_date)); ?>';
1134 var oeto
= '<?php echo attr(oeFormatShortDate($to_date)); ?>';
1135 window
.open('../main/messages/messages.php?nomenu=1&go=SMS_bot&pid=' + pid +
'&to=' + to +
'&from=' + from +
'&oeto=' + oeto +
'&oefrom=' + oefrom
, 'SMS_bot', 'width=370,height=600,resizable=0');
1139 function kiosk_FLB() {
1140 $
("#kiosk").val('1');
1141 $
("[name='kiosk_hide']").hide();
1142 $
("[name='kiosk_show']").show();
1143 var i
= document
.getElementById("flb_table");
1145 if (i
.requestFullscreen
) {
1146 i
.requestFullscreen();
1147 } else if (i
.webkitRequestFullscreen
) {
1148 i
.webkitRequestFullscreen();
1149 } else if (i
.mozRequestFullScreen
) {
1150 i
.mozRequestFullScreen();
1151 } else if (i
.msRequestFullscreen
) {
1152 i
.msRequestFullscreen();
1157 $
(document
).ready(function () {
1159 $
("#kiosk").val('');
1160 $
("[name='kiosk_hide']").show();
1161 $
("[name='kiosk_show']").hide();
1163 onresize
= function () {
1164 var state
= 1 >= outerHeight
- innerHeight ?
"fullscreen" : "windowed";
1165 if (window
.state
=== state
) return;
1166 window
.state
= state
;
1167 var event
= document
.createEvent("Event");
1168 event
.initEvent(state
, true, true);
1169 window
.dispatchEvent(event
);
1172 addEventListener('windowed', function (e
) {
1173 $
("#kiosk").val('');
1174 $
("[name='kiosk_hide']").show();
1175 $
("[name='kiosk_show']").hide();
1178 addEventListener('fullscreen', function (e
) {
1179 $
("#kiosk").val('1');
1180 $
("[name='kiosk_hide']").hide();
1181 $
("[name='kiosk_show']").show();
1186 if ($GLOBALS['pat_trkr_timer'] != '0') {
1188 var reftime
= "<?php echo attr($GLOBALS['pat_trkr_timer']); ?>";
1189 var parsetime
= reftime
.split(":");
1190 parsetime
= (parsetime
[0] * 60) +
(parsetime
[1] * 1) * 1000;
1191 if (auto_refresh
) clearInteral(auto_refresh
);
1192 auto_refresh
= setInterval(function () {
1193 refreshMe(true) // this will run after every parsetime seconds
1199 $
('.js-blink-infinite').each(function () {
1200 // set up blinking text
1202 setInterval(function () {
1203 if (elem
.css('visibility') === 'hidden') {
1204 elem
.css('visibility', 'visible');
1206 elem
.css('visibility', 'hidden');
1210 // toggle of the check box status for drug screen completed and ajax call to update the database
1211 $
(".drug_screen_completed").change(function () {
1212 top
.restoreSession();
1214 testcomplete_toggle
= "true";
1216 testcomplete_toggle
= "false";
1218 $
.post("../../library/ajax/drug_screen_completed.php", {
1220 testcomplete
: testcomplete_toggle
1224 // mdsupport - Immediately post changes to setting_new_window
1225 $
('#setting_new_window').click(function () {
1226 $
('#setting_new_window').val(this
.checked ?
'checked' : ' ');
1227 $
.post("<?php echo basename(__FILE__) ?>", {
1228 'setting_new_window': $
('#setting_new_window').val(),
1229 success
: function (data
) {
1235 $
('#filter_submit').click(function (e
) {
1241 $
('[data-toggle="tooltip"]').tooltip();
1243 $
('.datepicker').datetimepicker({
1244 <?php
$datetimepicker_timepicker = false; ?
>
1245 <?php
$datetimepicker_showseconds = false; ?
>
1246 <?php
$datetimepicker_formatInput = true; ?
>
1247 <?php
require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?
>
1248 <?php
// can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
1253 function initTableButtons() {
1254 $
('#refreshme').click(function () {
1259 $
('#setting_cog').click(function () {
1260 $
(this
).css("display", "none");
1261 $
('#settings').css("display", "inline");
1264 $
('#settings').css("display", "none");