patients.blade.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. @extends ('layouts/template')
  2. @section('content')
  3. <?php
  4. $showProgramsColumn = false;
  5. foreach($patients as $patient) {
  6. if(count($patient->clientPrograms)) {
  7. if($pro->pro_type === 'ADMIN') {
  8. $showProgramsColumn = true;
  9. break;
  10. }
  11. else {
  12. foreach($patient->clientPrograms as $clientProgram) {
  13. if(in_array($pro->id, [$clientProgram->mcp_pro_id, $clientProgram->manager_pro_id])) {
  14. $showProgramsColumn = true;
  15. break;
  16. }
  17. }
  18. if($showProgramsColumn) break;
  19. }
  20. }
  21. }
  22. ?>
  23. <div class="p-3 mcp-theme-1" id="patients-list">
  24. <div class="card">
  25. <div class="card-header px-3 py-2 d-flex align-items-center">
  26. <strong class="mr-4">
  27. <i class="fas fa-user"></i>
  28. Patients
  29. </strong>
  30. <div class="ml-auto d-flex align-items-center search-form">
  31. <form action="" method="get" class="mr-2" id="patients-search">
  32. <input type="text" name="q" value="{{request()->input('q')}}" class="form-control form-control-sm"
  33. placeholder="Name / Email / Tags">
  34. </form>
  35. <select class="ml-auto max-width-300px form-control form-control-sm"
  36. id="patients-filter">
  37. <option value="" {{ $filter === '' ? 'selected' : '' }}>All patients</option>
  38. <option value="not-yet-seen" {{ $filter === 'not-yet-seen' ? 'selected' : '' }}>Patients I have not seen yet</option>
  39. <option value="having-birthday-today" {{ $filter === 'having-birthday-today' ? 'selected' : '' }}>Patients having birthday today</option>
  40. </select>
  41. </div>
  42. </div>
  43. <div class="card-body p-0">
  44. <table class="table table-sm table-bordered p-0 m-0">
  45. <thead class="bg-light">
  46. <tr>
  47. @if($pro->pro_type === 'ADMIN')
  48. <th class="border-0"></th>
  49. @endif
  50. <th class="px-3 border-0">Chart #</th>
  51. <th class="border-0">Patient</th>
  52. @if($pro->isDefaultNA() || $pro->pro_type === 'ADMIN')
  53. <th class="border-0">Source</th>
  54. @endif
  55. <th class="border-0 px-1">OB</th>
  56. <th class="border-0">Signed<br>Notes</th>
  57. <th class="border-0">CM<br>Setup</th>
  58. <th class="border-0">Created At</th>
  59. <th class="border-0">Address</th>
  60. @if($showProgramsColumn)
  61. <th class="border-0">Program(s)</th>@endif
  62. <th class="border-0">MCN</th>
  63. <th class="border-0">PCP</th>
  64. <th class="border-0"><span class="text-nowrap">Recent Notes</span><br>(overall)</th>
  65. <th class="border-0"><span class="text-nowrap">Recent Notes</span><br>(me)</th>
  66. <th class="border-0">Appointments</th>
  67. <th class="border-0">Account</th>
  68. <th class="border-0">Tags</th>
  69. </tr>
  70. </thead>
  71. <tbody>
  72. @foreach($patients as $patient)
  73. <tr>
  74. @if($pro->pro_type === 'ADMIN')
  75. <td>{{$loop->index + 1}}</td>
  76. @endif
  77. <td class="px-3">
  78. <a href="{{route('patients.view.dashboard', $patient)}}">
  79. {{$patient->chart_number}}
  80. </a>
  81. </td>
  82. <td>
  83. {{$patient->displayName()}}
  84. <div>{{ friendly_date_time($patient->dob, false) }}{{ $patient->sex === 'M' ? ', Male' : ($patient->sex === ', F' ? 'Female' : '') }}</div>
  85. </td>
  86. @if($pro->isDefaultNA() || $pro->pro_type === 'ADMIN')
  87. <td>
  88. @if($patient->has_system_source)
  89. @if($patient->system_source_category === 'PRO_TEAM' && $patient->systemSourceProTeam)
  90. <div class="text-nowrap">Via team profile</div>
  91. <a native target="_blank" href="{{config('app.stagfe6_url')}}/{{$patient->systemSourceProTeam->slug}}">{{$patient->systemSourceProTeam->slug}}</a>
  92. @elseif($patient->system_source_category === 'PRO' && $patient->systemSourcePro)
  93. <div class="text-nowrap">Via pro profile</div>
  94. <a native target="_blank" href="{{config('app.stagfe6_url')}}/{{$patient->systemSourcePro->slug}}">{{$patient->systemSourcePro->slug}}</a>
  95. @endif
  96. @endif
  97. </td>
  98. @endif
  99. <td class="px-1">
  100. @if($patient->has_mcp_done_onboarding_visit !== 'YES')
  101. <span title="MCP Onboarding Visit Pending"><i class="fa fa-exclamation-triangle"></i></span>
  102. @else
  103. <i class="fa fa-check text-secondary on-hover-opaque"></i>
  104. @endif
  105. </td>
  106. <td>
  107. <?php $numSignedNotes = $patient->numSignedNotes(); ?>
  108. <span class="{{$numSignedNotes && $patient->has_mcp_done_onboarding_visit !== 'YES' ? 'font-weight-bold text-warning-mellow' : 'text-secondary'}}">
  109. {{$numSignedNotes ? $numSignedNotes :'-'}}
  110. </span>
  111. </td>
  112. <td>
  113. @if($patient->has_cm_setup_been_performed && $patient->cmSetupNote)
  114. <i class="fa fa-check text-secondary on-hover-opaque"></i>
  115. <br>
  116. <a href="{{route('patients.view.notes.view.dashboard', ['patient' => $patient, 'note' => $patient->cmSetupNote])}}">Note</a>
  117. @else
  118. -
  119. @endif
  120. </td>
  121. <td>
  122. {{ friendly_date_time_short_with_tz($patient->created_at, true, 'EASTERN') }}
  123. <hr>
  124. @if($pro->pro_type === 'ADMIN')
  125. {{ $patient->initiative }}
  126. @endif
  127. </td>
  128. <td>
  129. <?php
  130. $addressParts = [];
  131. if (!!$patient->mailing_address_line1) $addressParts[] = $patient->mailing_address_line1;
  132. if (!!$patient->mailing_address_line2) $addressParts[] = $patient->mailing_address_line2;
  133. $addressParts = implode(", ", $addressParts) . "<br/>";
  134. $addressPart2 = [];
  135. if (!!$patient->mailing_address_city) $addressPart2[] = $patient->mailing_address_city;
  136. if (!!$patient->mailing_address_state) $addressPart2[] = $patient->mailing_address_state;
  137. $addressParts .= implode(", ", $addressPart2);
  138. echo $addressParts;
  139. ?>
  140. </td>
  141. @if($showProgramsColumn)
  142. <td>
  143. <?php $programNumber = 0; ?>
  144. @foreach($patient->clientPrograms as $clientProgram)
  145. <?php
  146. if($pro->pro_type === 'ADMIN' ||
  147. in_array($pro->id, [$clientProgram->mcp_pro_id, $clientProgram->manager_pro_id])
  148. ) {
  149. // $program = $clientProgram->program;
  150. $programNumber++;
  151. ?>
  152. <div class="mb-1 text-nowrap">
  153. {{ $programNumber }}. {{ $clientProgram->title }}
  154. @if($clientProgram->has_mcp_done_onboarding_visit !== 'YES')
  155. <span title="Onboarding Pending" class="ml-1"><i class="fa fa-exclamation-triangle"></i></span>
  156. @else
  157. <span title="Onboarding Complete" class="ml-1 text-secondary"><i class="fa fa-check"></i></span>
  158. @endif
  159. </div>
  160. <?php } ?>
  161. @endforeach
  162. </td>
  163. @endif
  164. <td>
  165. @include('app.patient.coverage_column_renderer', ['patient'=>$patient])
  166. </td>
  167. <td>
  168. {{ $patient->mcp ? $patient->mcp->displayName() : '-' }}
  169. </td>
  170. <td class="p-0">
  171. <?php $allNotes = $patient->recentNotes(); ?>
  172. <table class="table table-sm table-condensed table-bordered m-0 width-200px">
  173. <tbody>
  174. @foreach($allNotes as $note)
  175. <tr>
  176. <td>
  177. <a href="{{route('patients.view.notes.view.dashboard', ['patient' => $patient, 'note' => $note])}}"><b class="text-nowrap">{{friendlier_date($note->effective_dateest)}}</b></a>
  178. <br>
  179. <span class="text-nowrap">{{$note->hcpPro->displayName()}}</span>
  180. </td>
  181. <td>{{$note->new_or_fu_or_na}}</td>
  182. </tr>
  183. @endforeach
  184. </tbody>
  185. </table>
  186. </td>
  187. <td class="py-0 pl-2">
  188. <?php $myNotes = $patient->recentNotes($pro); ?>
  189. <table class="table table-sm table-condensed table-bordered m-0 width-200px">
  190. <tbody>
  191. @foreach($myNotes as $note)
  192. <tr>
  193. <td>
  194. <a href="{{route('patients.view.notes.view.dashboard', ['patient' => $patient, 'note' => $note])}}"><b class="text-nowrap">{{friendlier_date($note->effective_dateest)}}</b></a>
  195. </td>
  196. <td>{{$note->new_or_fu_or_na}}</td>
  197. </tr>
  198. @endforeach
  199. </tbody>
  200. </table>
  201. </td>
  202. <td>
  203. <table class="table table-sm border-0 my-0">
  204. <tbody>
  205. <?php $numAppts = 0; ?>
  206. @foreach($patient->upcomingAppointments as $appointment)
  207. @if($appointment->status !== 'CANCELLED' && $appointment->status !== 'ABANDONED')
  208. <tr>
  209. <td class="text-black p-0 border-0">
  210. <div class="pb-0">
  211. {{ friendly_date_time($appointment->start_time, false) }}, {{ friendly_time($appointment->raw_start_time) }}
  212. <span class="d-inline-block text-secondary text-sm">({{ $appointment->timezone }})</span>
  213. <br>
  214. <b class="mr-1">{{$appointment->pro->displayName()}}</b>
  215. <span class="text-secondary text-sm">({{ $appointment->status }})</span>
  216. </div>
  217. </td>
  218. </tr>
  219. <?php $numAppts++; ?>
  220. @endif
  221. @endforeach
  222. @if(!$numAppts)
  223. <tr>
  224. <td class="text-secondary p-0 border-0">
  225. No upcoming appointments
  226. </td>
  227. </tr>
  228. @endif
  229. </tbody>
  230. </table>
  231. </td>
  232. <td>
  233. @if($patient->linkedAccounts && count($patient->linkedAccounts))
  234. <span class="font-weight-bold text-info"><i class="fa fa-check"></i></span>
  235. @else
  236. <span class="text-secondary">-</span>
  237. @endif
  238. </td>
  239. <td>
  240. @if($patient->tags)
  241. <?php
  242. $tags = explode("|", $patient->tags);
  243. $tags = array_filter($tags, function($_x) {
  244. return !empty($_x);
  245. });
  246. $tags = implode(", ", $tags);
  247. ?>
  248. {{ $tags }}
  249. @endif
  250. </td>
  251. </tr>
  252. @endforeach
  253. </tbody>
  254. </table>
  255. <div class="ml-2 mt-2">
  256. {{$patients->links()}}
  257. </div>
  258. </div>
  259. </div>
  260. </div>
  261. <script>
  262. (function() {
  263. function init() {
  264. function submit() {
  265. let url = '/patients' +
  266. ($('#patients-filter').val() ? '/' + $('#patients-filter').val() : '') +
  267. ($('#patients-search input').val() ? '?q=' + encodeURIComponent($('#patients-search input').val()) : '');
  268. fastLoad(url);
  269. return false;
  270. }
  271. $('#patients-search').off('submit').on('submit', submit);
  272. $('#patients-filter').off('change').on('change', submit);
  273. @if($pro->id === 1 || $pro->id === 16)
  274. patientAcquisitionChart();
  275. @endif
  276. }
  277. @if($pro->pro_type === 'ADMIN')
  278. <?php
  279. $dates = [];
  280. $acquisitions = [];
  281. for ($i = count($patientAcquisitionData) - 1; $i >= 0; $i--) {
  282. $dates[] = $patientAcquisitionData[$i]->date;
  283. $acquisitions[] = $patientAcquisitionData[$i]->count;
  284. }
  285. ?>
  286. function patientAcquisitionChart() {
  287. var chart = c3.generate({
  288. bindto: '#patientAcquisitionChart',
  289. data: {
  290. x: 'x',
  291. // xFormat: '%Y%m%d', // 'xFormat' can be used as custom format of 'x'
  292. columns: [
  293. ['x', <?= implode(", ", array_map(function($_x) { return "'" . $_x . "'"; }, $dates)) ?>],
  294. ['New Patients', <?= implode(", ", array_map(function($_x) { return "'" . $_x . "'"; }, $acquisitions)) ?>],
  295. ]
  296. },
  297. axis: {
  298. x: {
  299. type: 'timeseries',
  300. tick: {
  301. format: '%Y-%m-%d',
  302. multiline: true,
  303. fit: true,
  304. rotate: -45
  305. },
  306. },
  307. }
  308. });
  309. }
  310. @endif
  311. addMCInitializer('patients-list', init, '#patients-list');
  312. }).call(window);
  313. </script>
  314. @endsection