fix: fix none mechanism in issues gui (#6860)
[openemr.git] / interface / patient_file / summary / stats_full.php
blobbf83fe04afff5aad87e60374ecb7e37ef32c5a8a
1 <?php
3 /**
4 * stats_full.php
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2005-2017 Rod Roark <rod@sunsetsystems.com>
11 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
12 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 require_once('../../globals.php');
16 require_once($GLOBALS['srcdir'] . '/lists.inc.php');
17 require_once($GLOBALS['fileroot'] . '/custom/code_types.inc.php');
18 require_once($GLOBALS['srcdir'] . '/options.inc.php');
20 use OpenEMR\Common\Acl\AclMain;
21 use OpenEMR\Common\Csrf\CsrfUtils;
22 use OpenEMR\Common\Twig\TwigContainer;
23 use OpenEMR\Core\Header;
24 use OpenEMR\Menu\PatientMenuRole;
25 use OpenEMR\OeUI\OemrUI;
26 use OpenEMR\Services\ListService;
28 // Check if user has permission for any issue type.
29 $auth = false;
30 foreach ($ISSUE_TYPES as $type => $dummy) {
31 if (AclMain::aclCheckIssue($type)) {
32 $auth = true;
33 break;
37 if ($auth) {
38 $tmp = getPatientData($pid, "squad");
39 if ($tmp['squad'] && ! AclMain::aclCheckCore('squads', $tmp['squad'])) {
40 die(xlt('Not authorized'));
42 } else {
43 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Patient Issues")]);
44 exit;
47 // Collect parameter(s)
48 $category = empty($_REQUEST['category']) ? '' : $_REQUEST['category'];
50 // Get patient's preferred language for the patient education URL.
51 $tmp = getPatientData($pid, 'language');
52 $language = $tmp['language'];
54 <html>
55 <head>
56 <?php Header::setupHeader('popper'); ?>
57 <title><?php echo xlt('Patient Issues'); ?></title>
58 <script>
60 // callback from add_edit_issue.php:
61 function refreshIssue(issue, title) {
62 top.restoreSession();
63 window.location=window.location;
66 function dopclick(id, category) {
67 top.restoreSession();
68 category = (category == 0) ? '' : category;
69 let dlg_url = 'add_edit_issue.php?issue=' + encodeURIComponent(id) + '&thistype=' + encodeURIComponent(category);
70 dlgopen(dlg_url, '_blank', 1280, 900, '', <?php echo xlj("Add/Edit Issue"); ?>);
73 // Process click on number of encounters.
74 function doeclick(id) {
75 top.restoreSession();
76 dlgopen('../problem_encounter.php?issue=' + encodeURIComponent(id), '_blank', 700, 400);
79 function getSelectionCheckBoxes(issueType) {
80 let issue = (issueType instanceof HTMLElement) ? issueType : document.getElementById(issueType)
81 return Array.from(issue.getElementsByClassName("selection-check"));
84 function rowSelectionChanged(issue) {
85 var deleteBtn = document.getElementById(issue + "-delete");
86 if (deleteBtn) {
87 deleteBtn.disabled = !getSelectionCheckBoxes(issue).some(e => e.checked);
91 function headerSelectionChanged(groupBox, issueType) {
92 let issueElm = document.getElementById(issueType);
93 for (const c of getSelectionCheckBoxes(issueElm)) {
94 c.checked = groupBox.checked;
96 rowSelectionChanged(issueType);
99 function deleteSelectedIssues(tableName) {
100 var selBoxes = getSelectionCheckBoxes(tableName);
101 var ids = ""
102 var count = 0;
103 for (var i = 0; i < selBoxes.length; i++) {
104 if (selBoxes[i].checked) {
105 if (count > 0) {
106 ids += ","
108 ids += selBoxes[i].id.split("_")[1]
109 count++
113 dlgopen('../deleter.php?issue=' + ids + '&csrf_token_form=' + <?php echo js_url(CsrfUtils::collectCsrfToken()); ?>, '_blank', 500, 450);
116 // Called by the deleter.php window on a successful delete.
117 function imdeleted() {
118 refreshIssue('', '')
121 // Process click on diagnosis for patient education popup.
122 function educlick(codetype, codevalue) {
123 top.restoreSession();
124 dlgopen('../education.php?type=' + encodeURIComponent(codetype) +
125 '&code=' + encodeURIComponent(codevalue) +
126 '&language=' + <?php echo js_url($language); ?>,
127 '_blank', 1024, 750,true); // Force a new window instead of iframe to address cross site scripting potential
130 // Add Encounter button is clicked.
131 function newEncounter() {
132 var f = document.forms[0];
133 top.restoreSession();
134 location.href='../../forms/newpatient/new.php?autoloaded=1&calenc=';
137 </script>
138 <script>
139 <?php
140 require_once("$include_root/patient_file/erx_patient_portal_js.php"); // jQuery for popups for eRx and patient portal
142 </script>
143 <?php
144 $arrOeUiSettings = array(
145 'heading_title' => xl('Medical Issues'),
146 'include_patient_name' => true,
147 'expandable' => true,
148 'expandable_files' => array("stats_full_patient_xpd", "external_data_patient_xpd", "patient_ledger_patient_xpd"),//all file names need suffix _xpd
149 'action' => "",//conceal, reveal, search, reset, link or back
150 'action_title' => "",
151 'action_href' => "",//only for actions - reset, link or back
152 'show_help_icon' => true,
153 'help_file_name' => "issues_dashboard_help.php"
155 $oemr_ui = new OemrUI($arrOeUiSettings);
158 <style>
159 .selection-check {
160 top: 0;
161 left: 0;
162 height: 16px;
163 width: 16px;
165 </style>
166 </head>
168 <body class="patient-medical-issues">
169 <div id="container_div" class="<?php echo $oemr_ui->oeContainer();?>">
170 <div class="row">
171 <div class="col-sm-12">
172 <?php require_once("$include_root/patient_file/summary/dashboard_header.php") ?>
173 </div>
174 </div>
175 <?php
176 $list_id = "issues"; // to indicate nav item is active, count and give correct id
177 // Collect the patient menu then build it
178 $menuPatient = new PatientMenuRole();
179 $menuPatient->displayHorizNavBarMenu();
182 <div id='patient_stats'>
183 <form method='post' action='stats_full.php' onsubmit='return top.restoreSession()'>
184 <?php foreach ($ISSUE_TYPES as $t => $focustitles) : ?>
185 <?php
186 if (!AclMain::aclCheckIssue($t)) {
187 continue;
190 if ($category && ($t !== $category)) {
191 continue;
194 $btnDelete = AclMain::aclCheckCore('admin', 'super');
195 $canSelect = $btnDelete;
196 $btnAdd = false;
197 if (AclMain::aclCheckIssue($t, '', ['write', 'addonly'])) {
198 if (in_array($t, ['allergy', 'medications']) && $GLOBALS['erx_enable']) {
199 $btnAdd = [
200 'href' => '../../eRx.php?page=medentry',
201 'onclick' => 'top.restoreSession()',
203 } else {
204 $btnAdd = [
205 'href' => '#',
206 'onclick' => 'dopclick(0, ' . attr_js($t) . ')'
211 $condition = ($GLOBALS['erx_enable'] && $GLOBALS['erx_medication_display'] && $t == 'medication') ? "AND erx_uploaded != '1'" : '';
212 $pres = sqlStatement("SELECT * FROM lists WHERE pid = ? AND type = ? $condition ORDER BY begdate", [$pid, $t]);
213 $noIssues = false;
214 $nothingRecorded = false;
216 // if no issues (will place a 'None' text vs. toggle algorithm here)
217 if (sqlNumRows($pres) < 1) {
218 if (getListTouch($pid, $t)) {
219 // Data entry has happened to this type, so can display an explicit None.
220 $noIssues = true;
221 } else {
222 // Data entry has not happened to this type, so can show the none selection option.
223 $nothingRecorded = true;
228 <div class="bg-light w-100 p-3 d-flex sticky-top justify-content-between align-items-center">
229 <div class="d-flex align-items-center">
230 <?php if (!($noIssues || $nothingRecorded)) : ?>
231 <input type="checkbox" class="selection-check mr-1" onclick="headerSelectionChanged(this, <?php echo attr_js($t);?>);"/>
232 <button type="button" class="btn btn-text px-2" data-issue-type="<?php echo attr($t); ?>" data-action="toggle" data-expanded="false" aria-label="<?php echo xla("Expand or collapse all items in section"); ?>"><span class="fa fa-fw fa-expand" aria-hidden="true"></span></button>
233 <?php endif; ?>
234 <h4 class="d-inline-block p-0 m-0"><?php echo text($focustitles[0]); ?></h4>
235 </div>
237 <div class="btn-group" role="group">
239 <?php if ($btnAdd) : ?>
240 <a href="<?php echo attr($btnAdd['href']); ?>" class="btn btn-sm btn-text" onclick='<?php echo $btnAdd['onclick']; ?>'><span class="fa fa-fw fa-plus"></span>&nbsp;<?php echo xlt('Add'); ?></a>
241 <?php endif; ?>
243 <?php if ($btnDelete) : ?>
244 <button type="button" id="<?php echo attr($t); ?>-delete" class="btn btn-sm btn-text" disabled onclick="deleteSelectedIssues(<?php echo attr_js($t); ?>)"><span class="fa fa-fw fa-trash-can"></span>&nbsp;<?php echo xlt('Delete'); ?></a>
245 <?php endif; ?>
246 </div>
247 </div>
248 <div class="list-group list-group-flush" id="<?php echo attr($t); ?>">
249 <?php if ($noIssues && !$nothingRecorded) : ?>
250 <div class="list-group-item"><?php echo xlt("None{{Issue}}"); ?></div>
251 <?php elseif (!$noIssues && $nothingRecorded) : ?>
252 <div class="list-group-item">
253 <div class="form-check">
254 <input class="form-check-input noneCheck" value="none" <?php echo (!AclMain::aclCheckIssue($t, '', 'write')) ? " disabled" : ""; ?> type="checkbox" name="<?php echo attr($t); ?>" id="<?php echo attr($t); ?>">
255 <label class="form-check-label" for="<?php echo attr($t); ?>"><?php echo xlt("None{{Issue}}"); ?></label>
256 </div>
257 </div>
258 <?php endif; ?>
260 <?php
261 // display issues
262 while ($row = sqlFetchArray($pres)) :
263 $rowid = $row['id'];
265 $disptitle = trim($row['title']) ? $row['title'] : "[Missing Title]";
267 $ierow = sqlQuery("SELECT count(*) AS count FROM issue_encounter WHERE list_id = ?", array($rowid));
269 // encount is used to toggle the color of the table-row output below
270 ++$encount;
271 $bgclass = (($encount & 1) ? "bg1" : "bg2");
273 $colorstyle = !empty($row['enddate']) ? "text-muted" : "";
275 // look up the diag codes
276 $codetext = "";
277 if ($row['diagnosis'] != "") {
278 $diags = explode(";", $row['diagnosis']);
279 foreach ($diags as $diag) {
280 $codedesc = lookup_code_descriptions($diag);
281 list($codetype, $code) = explode(':', $diag);
282 if ($codetext) {
283 $codetext .= "<br>";
286 $codetext .= "<a href='javascript:educlick(" . attr_js($codetype) . "," . attr_js($code) . ")' class='" . $colorstyle . "'>" .
287 text($diag . " (" . $codedesc . ")") . "</a>";
291 // calculate the status
292 $resolved = false;
293 if ($row['outcome'] == "1" && $row['enddate'] != null) {
294 // Resolved
295 $resolved = true;
296 $statusCompute = generate_display_field(array('data_type' => '1','list_id' => 'outcome'), $row['outcome']);
297 } elseif ($row['enddate'] == null) {
298 $statusCompute = xlt("Active");
299 } else {
300 // MU3 criteria, show medical problem's with end dates as a status of Completed.
301 $statusCompute = ($t == 'medical_problem') ? xlt("Completed") : xlt("Inactive");
302 $resolved = ($t == "medical_problems") ? true : false;
305 $click_class = 'statrow';
306 if ($row['erx_source'] == 1 && $t == 'allergy') {
307 $click_class = '';
308 } elseif ($row['erx_uploaded'] == 1 && $t == 'medication') {
309 $click_class = '';
312 $shortBegDate = trim(oeFormatShortDate($row['begdate']));
313 $shortEndDate = trim(oeFormatShortDate($row['enddate']));
314 $fullBegDate = trim(oeFormatDateTime($row['begdate']));
315 $fullEndDate = trim(oeFormatDateTime($row['enddate']));
316 $shortModDate = trim(oeFormatShortDate($row['modifydate']));
317 $fullModDate = trim(oeFormatDateTime($row['modifydate']));
319 $outcome = ($row['outcome']) ? generate_display_field(['data_type' => 1, 'list_id' => 'outcome'], $row['outcome']) : false;
321 <div class="list-group-item p-1">
322 <div class="summary m-0 p-0 d-flex w-100 justify-content-end align-content-center">
323 <?php if ($canSelect) : ?>
324 <input type="checkbox" class="selection-check mt-1 mr-2" data-issue="<?php echo attr($t); ?>" name="sel_<?php echo attr($rowid); ?>" id="sel_<?php echo attr($rowid); ?>">
325 <?php endif; ?>
326 <div class="flex-fill pl-2">
327 <div class="btn-group" role="group">
328 <button type="button" class="btn btn-outline-text btn-sm collapsed" data-toggle="collapse" data-target="#details_<?php echo attr($row['id']); ?>" aria-expanded="false" aria-controls="details_<?php echo attr($row['id']); ?>"><span aria-hidden="true" class="fa fa-fw fa-chevron-right"></span></button>
329 <button type="button" class="btn btn-outline-text btn-sm editenc" data-issue-id="<?php echo attr($row['id']); ?>"><span aria-hidden="true" class="fa fa-fw fa-link"></span></button>
330 </div>
331 <a href="#" data-issue-id="<?php echo attr($row['id']); ?>" class="font-weight-bold issue_title" data-toggle="tooltip" data-placement="right" title="<?php echo text($diag . ": " . $codedesc); ?>">
332 <?php echo text($disptitle); ?>
333 </a>&nbsp;(<?php echo $statusCompute; ?><?php echo (!$resolved && $outcome) ? ", $outcome" : ""; ?>)
334 <?php
335 if ($focustitles[0] == "Allergies") :
336 echo generate_display_field(array('data_type' => '1','list_id' => 'reaction'), $row['reaction']);
337 endif;
339 </div>
340 <?php if ($focustitles[0] == "Allergies") :
341 $l = new ListService();
342 $sev = $l->getListOption('severity_ccda', $row['severity_al']);
343 $hgl = (in_array($row['severity_al'], ['severe', 'life_threatening_severity', 'fatal'])) ? 'bg-warning font-weight-bold px-1' : '';
345 <span class="mr-3 <?php echo attr($hgl); ?>">
346 <?php echo text($sev['title']); ?>
347 </span>
348 <?php endif; ?>
349 <div class="text-right">
350 <span class="font-weight-bold d-inline"><?php echo xlt("Occurrence"); ?></span>
351 <span><?php echo generate_display_field(['data_type' => '1', 'list_id' => 'occurrence'], $row['occurrence']); ?></span>
352 </div>
353 </div>
354 <div id="details_<?php echo attr($row['id']); ?>" class="collapse">
355 <div class="d-flex flex-column w-100 my-3">
356 <div class="d-flex w-100">
357 <div class="pr-3">
358 <div class="font-weight-bold"><?php echo xlt("Last Modified"); ?></div>
359 <div class="pl-1" title="<?php echo attr($fullModDate); ?>"><?php echo text($shortModDate); ?></div>
360 </div>
361 <?php if ($row['begdate']) : ?>
362 <div class="pr-3">
363 <div class="font-weight-bold "><?php echo xlt("Start Date"); ?></div>
364 <div class="" title="<?php echo text($fullBegDate); ?>"><?php echo text($shortBegDate); ?></div>
365 </div>
366 <?php endif; ?>
367 <?php if ($row['enddate']) : ?>
368 <div class="pr-3">
369 <div class="font-weight-bold "><?php echo xlt("End Date"); ?></div>
370 <div title="<?php echo attr($fullEndDate); ?>"><?php echo text($shortEndDate); ?></div>
371 </div>
372 <?php endif; ?>
373 <?php if ($t == "allergy" || $t == "medical_problem") : ?>
374 <div class="pr-3">
375 <div class="font-weight-bold"><?php echo xlt("Verification"); ?></div>
376 <div>
377 <?php
378 $codeListName = (!empty($thistype) && ($thistype == 'medical_problem')) ? 'condition-verification' : 'allergyintolerance-verification';
379 echo generate_display_field(array('data_type' => '1','list_id' => $codeListName), $row['verification']);
381 </div>
382 </div>
383 <?php endif; ?>
384 <?php if ($row['referredby']) : ?>
385 <div class="pr-3">
386 <div class="font-weight-bold"><?php echo xlt("Referred By"); ?></div>
387 <div><?php echo text($row['referredby']); ?></div>
388 </div>
389 <?php endif; ?>
390 <?php if ($row['comments']) : ?>
391 <div class="flex-fill">
392 <div class="font-weight-bold"><?php echo xlt("Comments"); ?></div>
393 <div><?php echo text($row['comments']); ?></div>
394 </div>
395 <?php endif; ?>
396 </div>
397 <div class="d-flex w-100 mt-2">
398 <?php echo $codetext; ?>
399 </div>
400 </div>
401 </div>
402 </div>
403 <?php endwhile; ?>
404 </div>
405 <?php endforeach; ?>
406 </form>
407 </div> <!-- end patient_stats -->
408 </div><!--end of container div -->
409 <?php $oemr_ui->oeBelowContainerDiv();?>
410 </body>
411 <script>
412 $(function () {
413 $("[data-toggle='collapse']").click(function() {
414 $(this).children("span").toggleClass(["fa-chevron-right", "fa-chevron-down"]);
416 $(".selection-check").on('change', function(e) {
417 rowSelectionChanged(this.getAttribute('data-issue'));
419 $('[data-action="toggle"]').on('click', function(e) {
420 let type = this.getAttribute('data-issue-type');
421 let isExp = this.getAttribute('data-expanded');
422 let selector = (isExp === "false") ? "[data-toggle='collapse'].collapsed" : "[data-toggle='collapse']";
423 console.debug(selector);
424 $("#" + type + " " + selector).trigger('click');
425 $(this).children(".fa").toggleClass(["fa-compress", 'fa-expand']);
426 this.setAttribute('data-expanded', (isExp === "false" ? "true" : "false"));
428 $(".issue_title").click(function() { dopclick($(this).data('issue-id'),0); });
429 $(".editenc").click(function(event) { doeclick($(this).data('issue-id'),0); });
430 $("#newencounter").click(function() { newEncounter(); });
431 $("#history").click(function() { GotoHistory(); });
432 $("#back").click(function() { GoBack(); });
434 $(".noneCheck").click(function() {
435 top.restoreSession();
436 $.post( "../../../library/ajax/lists_touch.php",
438 type: this.name,
439 patient_id: <?php echo js_escape($pid); ?>,
440 csrf_token_form: <?php echo js_escape(CsrfUtils::collectCsrfToken()); ?>
443 $(this).hide();
447 var GotoHistory = function() {
448 top.restoreSession();
449 location.href='../history/history_full.php';
452 var GoBack = function () {
453 top.restoreSession();
454 location.href='demographics.php';
456 </script>
457 </html>