Bladeren bron

Merge branch 'dev' into dev-vj

Vijayakrishnan 3 jaren geleden
bovenliggende
commit
576db04168

+ 34 - 0
app/Http/Controllers/AdminController.php

@@ -108,6 +108,40 @@ class AdminController extends Controller
         $this->filterMultiQuery($request, $patients, 'most_recent_weight_at', 'last_weighed_in_category', 'last_weighed_in_value_1', 'last_weighed_in_value_2');
         $this->filterMultiQuery($request, $patients, 'most_recent_bp_at', 'last_bp_category', 'last_bp_value_1', 'last_bp_value_2');
 
+        if($request->input('number_of_measurements')){
+            $keyName = $request->input('number_of_measurements');
+            $measurementCountQuery = '(SELECT COUNT(*) FROM measurement WHERE measurement.client_id = client.id AND is_active IS TRUE AND is_cellular IS TRUE AND is_cellular_zero IS NOT TRUE)';
+            switch($keyName) {
+                case 'EXACTLY':
+                    if($request->input('number_of_measurements_value_1')) {
+                        $patients->whereRaw($measurementCountQuery . '='.$request->input('number_of_measurements_value_1'));
+                    }
+                    break;
+                case 'LESS_THAN':
+                    if($request->input('number_of_measurements_value_1')) {
+                        $patients->whereRaw($measurementCountQuery . '<='.$request->input('number_of_measurements_value_1'));
+                    }
+                    break;
+                case 'GREATER_THAN':
+                    if($request->input('number_of_measurements_value_1')) {
+                        $patients->whereRaw($measurementCountQuery . '>='.$request->input('number_of_measurements_value_1'));
+                    }
+                    break;
+                case 'BETWEEN':
+                    if($request->input('number_of_measurements_value_1') && $request->input('number_of_measurements_value_2')) { 
+                        $patients->whereRaw($measurementCountQuery.'>='.$request->input('number_of_measurements_value_1') .' AND '. $measurementCountQuery . '<='.$request->input('number_of_measurements_value_2'));
+                    }
+                    break;
+                case 'NOT_BETWEEN':
+                    if($request->input('number_of_measurements_value_1') && $request->input('number_of_measurements_value_2')) {
+                        $patients->where(function ($q) use ($request, $measurementCountQuery) {
+                                $q->whereRaw($measurementCountQuery . '<'.$request->input('number_of_measurements_value_1') .' OR '. $measurementCountQuery . '>'.$request->input('number_of_measurements_value_2'));                               
+                        });
+                    }
+                    break;
+            }
+        }
+
         switch($request->input('status')) {
             case 'ACTIVE':
                 $patients->where('is_active', true)->where('has_mcp_done_onboarding_visit', true);

+ 10 - 0
app/Models/Client.php

@@ -208,6 +208,16 @@ class Client extends Model
             ->orderByRaw('ts DESC NULLS LAST');
     }
 
+    public function cellularMeasurements()
+    {
+        return $this->hasMany(Measurement::class, 'client_id', 'id')
+            /*->distinct('label')*/
+            ->where('is_active', true)
+            ->where('is_cellular', true)
+            ->where('is_cellular_zero', false)
+            ->orderByRaw('ts DESC NULLS LAST');
+    }
+
     public function recentMeasurements()
     {
         return $this->hasMany(Measurement::class, 'client_id', 'id')

+ 2 - 1
config/app.php

@@ -262,7 +262,8 @@ return [
         'objective_free_text',
         'plan_free_text',
         'assessment_free_text',
-        'disclaimers'
+        'disclaimers',
+        'masks_and_respirators'
     ],
 
     'note_rhs_segments' => [

+ 3 - 0
resources/views/app/admin/patients-table-extended.blade.php

@@ -27,6 +27,8 @@
             <th class="border-0">Weight</th>
             <th class="border-0">Weight Timestamp</th>
 
+            <th class="border-0"># Cellular Measurements</th>
+
             {{-- <th>Scale <i class="fa fa-battery"></i></th>--}}
             {{-- <th class="border-0">RPM</th>--}}
             {{-- <th class="border-0">CCM</th>--}}
@@ -304,6 +306,7 @@
                     <?php $m = $patient->lastMeasurementOfType('BP'); ?>
                     {{$m && $m->value ? $m->value : '-'}}
                 </td>
+                <td>{{count($patient->cellularMeasurements)}}</td>
                 <td>{{$patient->getMcpAssignedOn()}}</td>
                 @if($pro->pro_type == 'ADMIN')
                     <td>{{@$patient->mcp ? $patient->mcp->displayName() : '--'}}</td>

+ 26 - 0
resources/views/app/admin/patients_filters.blade.php

@@ -207,6 +207,29 @@
 	</div>
 	@endif
 
+	<!-- Number of measurements	 -->
+	<div class="sm-section">
+		<div class="">
+			<label># Measurements:</label>
+			<select name="number_of_measurements" class="form-control input-sm" v-model="filters.number_of_measurements">
+				<option value="">All</option>
+				<option value="EXACTLY">Exactly</option>
+				<option value="LESS_THAN">Less Than</option>
+				<option value="GREATER_THAN">Greater Than</option>
+				<option value="BETWEEN">Between</option>
+				<option value="NOT_BETWEEN">Not Between</option>
+			</select>
+			<div v-show="filters.number_of_measurements" class="mt-2">
+				<div>
+					<input  name="number_of_measurements_value_1" v-model="filters.number_of_measurements_value_1" type="number" class="form-control input-sm" :placeholder="(filters.number_of_measurements === 'BETWEEN' || filters.number_of_measurements === 'NOT_BETWEEN') ? 'From' : 'Number of measurements'" />
+				</div>
+				<div v-show="filters.number_of_measurements === 'BETWEEN' || filters.number_of_measurements === 'NOT_BETWEEN'" class="mt-2">
+					<input name="number_of_measurements_value_2" v-model="filters.number_of_measurements_value_2" type="number" class="form-control input-sm" placeholder="To" />
+				</div>
+			</div>
+		</div>
+	</div>
+
 	@if($performer->pro->pro_type == 'ADMIN')
 	<div class="sm-section">
 		<div class="">
@@ -302,6 +325,9 @@ $allFilterKeys = [
 	'initiative',
 	'insurance',
 	'include_test_records',
+	'number_of_measurements',
+	'number_of_measurements_value_1',
+	'number_of_measurements_value_2'
 ];
 for ($i=0; $i < count($allFilterKeys); $i++) {
 	if (!isset($loadedFilters[$allFilterKeys[$i]]) || !$loadedFilters[$allFilterKeys[$i]]) {

+ 157 - 0
resources/views/app/patient/segment-templates/masks_and_respirators/edit.blade.php

@@ -0,0 +1,157 @@
+<?php
+
+use App\Models\Point;
+
+$segmentSections = [
+	[
+		'heading' => 'Key Messages',
+		'points' => [
+			[
+				'key' => 'any_mask_better_than_no_mask',
+				'text' => 'Masking is a critical public health tool for preventing spread of COVID-19, and it is important to remember that any mask is better than no mask.',
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'masks_effective_at_reducing_virus',
+				'text' => 'Masks and respirators are effective at reducing transmission of SARS-CoV-2, the virus that causes COVID-19, when worn consistently and correctly.',
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'wear_the_best_mask_you_can',
+				'text' => "The key is: what will you wear that's most protective, but also wear consistently.",
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'more_protective_may_be_uncomfortable',
+				'text' => 'Some masks and respirators offer higher levels of protection than others, and some may be harder to tolerate or wear consistently than others.',
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'importance_with_risk_and_age',
+				'text' => 'This becomes more important if you are over 65 or have any medical conditions like HBP or DM that increase risk of COVID severity.',
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'what_are_you_currently_wearing',
+				'text' => 'What are you currently wearing / how often / how often replaced?',
+				'type' => 'textarea'
+			],
+			[
+				'key' => 'what_is_the_best_mask_you_will_wear_consistently',
+				'text' => 'What is the most most protective mask that you will wear consistently?',
+				'type' => 'text'
+			]
+		]
+	],
+	[
+		'heading' => 'Follow-Up',
+		'points' => [
+			[
+				'key' => 'n95_recommended',
+				'text' => 'N95 recommended.',
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'ensure_tight_fit',
+				'text' => 'Check for gaps by cupping your hands around the outside edges of the mask.',
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'check_airflow',
+				'text' => 'Make sure no air is flowing from the area near your eyes or from the sides of the mask.',
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'warm_air_check',
+				'text' => 'If the mask has a good fit, you will feel warm air come through the front of the mask and may be able to see the mask material move in and out with each breath.',
+				'type' => 'checkbox'
+			],
+			[
+				'key' => 'send_n95',
+				'text' => 'Send N95 samples if appropriate.',
+				'type' => 'readonly'
+			]
+		]
+	]
+];
+
+$category = 'MASKS_AND_RESPIRATORS';
+$endPoint = 'upsertNoteSingleton';
+
+$point = Point::where('added_in_segment_id', $segment->id)->where('category', $category)->orderBy('id', 'DESC')->first();
+
+$contentData = [];
+
+foreach($segmentSections as $segmentSection){
+	foreach($segmentSection['points'] as $sectionPoint){
+		if($sectionPoint['type'] == 'text'){
+			$contentData[$sectionPoint['key']] = '';
+		}elseif($sectionPoint['type'] == 'textarea'){
+			$contentData[$sectionPoint['key']] = '';
+		}elseif($sectionPoint['type'] == 'checkbox'){
+			$contentData[$sectionPoint['key']] = null;
+		}else{
+			$contentData[$sectionPoint['key']] = '';
+		}
+	}
+}
+
+
+if (!!@$point->data) {
+    $contentData = json_decode($point->data, true);
+}
+
+?>
+<div visit-moe close-on-save close-on-cancel class="d-block p-3">
+	<form show url="/api/visitPoint/<?= $endPoint ?>" class="mcp-theme-1">
+		<input type="hidden" name="uid" value="<?= @$point->uid ?>">
+		<input type="hidden" name="noteUid" value="<?= @$note->uid ?>">
+		<input type="hidden" name="segmentUid" value="<?= @$segment->uid ?>">
+		<input type="hidden" name="category" value="<?= $category ?>">
+		<input type="hidden" name="data" value="{{json_encode($contentData)}}">
+
+		@foreach($segmentSections as $section)
+		<div class="mb-2">
+			<h6><b><u>{{ $section['heading'] }}</u></b></h6>
+			@foreach($section['points'] as $point)
+			@if($point['type'] == 'text')
+			<div class="mb-2">
+				<label>{{ $point['text'] }}</label>
+				<input name="{{ $point['key'] }}" data-name="{{ $point['key'] }}" class="form-control" value="{{ @$contentData[$point['key']] }}" />
+			</div>
+			@elseif($point['type'] == 'textarea')
+			<div class="mb-2">
+				<label>{{ $point['text'] }}</label>
+				<textarea name="{{ $point['key'] }}" data-name="{{ $point['key'] }}" rows="2" class="form-control"><?= nl2br(@$contentData[$point['key']]) ?></textarea>
+			</div>
+			@elseif($point['type'] == 'checkbox')
+			<div class="">
+				<label class="d-flex align-items-baseline mb-2">
+					<div class="mr-2 align-self-stretch" style="padding-top: 2px;">
+						<input type="checkbox" name="{{ $point['key'] }}" data-name="{{ $point['key'] }}" {{@($contentData[$point['key']] ? 'checked' : '')}}>
+					</div>
+					<span>{{ $point['text'] }}</span>
+				</label>
+			</div>
+			@else
+			<div class="mb-2">
+				<label><b>*</b> {{ $point['text'] }}</label>
+			</div>
+			@endif
+			@endforeach
+		</div>
+		<hr class="my-3">
+		@endforeach
+
+		<div class="pt-2">
+			<button submit class="btn btn-sm btn-primary mr-2"><i class="fa fa-save"></i></button>
+			<div class="d-inline-flex align-self-stretch align-items-center">
+				<span class="autosave-indicator saving text-sm text-secondary">Saving changes &hellip;</span>
+				<span class="autosave-indicator saved text-sm text-secondary">
+					<i class="fa fa-check"></i>
+					Saved
+				</span>
+			</div>
+		</div>
+	</form>
+</div>

+ 141 - 0
resources/views/app/patient/segment-templates/masks_and_respirators/summary.blade.php

@@ -0,0 +1,141 @@
+<?php
+
+use App\Models\Point;
+
+$segmentSections = [
+    [
+        'heading' => 'Key Messages',
+        'points' => [
+            [
+                'key' => 'any_mask_better_than_no_mask',
+                'text' => 'Masking is a critical public health tool for preventing spread of COVID-19, and it is important to remember that any mask is better than no mask.',
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'masks_effective_at_reducing_virus',
+                'text' => 'Masks and respirators are effective at reducing transmission of SARS-CoV-2, the virus that causes COVID-19, when worn consistently and correctly.',
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'wear_the_best_mask_you_can',
+                'text' => "The key is: what will you wear that's most protective, but also wear consistently.",
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'more_protective_may_be_uncomfortable',
+                'text' => 'Some masks and respirators offer higher levels of protection than others, and some may be harder to tolerate or wear consistently than others.',
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'importance_with_risk_and_age',
+                'text' => 'This becomes more important if you are over 65 or have any medical conditions like HBP or DM that increase risk of COVID severity.',
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'what_are_you_currently_wearing',
+                'text' => 'What are you currently wearing / how often / how often replaced?',
+                'type' => 'textarea'
+            ],
+            [
+                'key' => 'what_is_the_best_mask_you_will_wear_consistently',
+                'text' => 'What is the most most protective mask that you will wear consistently?',
+                'type' => 'text'
+            ]
+        ]
+    ],
+    [
+        'heading' => 'Follow-Up',
+        'points' => [
+            [
+                'key' => 'n95_recommended',
+                'text' => 'N95 recommended.',
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'ensure_tight_fit',
+                'text' => 'Check for gaps by cupping your hands around the outside edges of the mask.',
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'check_airflow',
+                'text' => 'Make sure no air is flowing from the area near your eyes or from the sides of the mask.',
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'warm_air_check',
+                'text' => 'If the mask has a good fit, you will feel warm air come through the front of the mask and may be able to see the mask material move in and out with each breath.',
+                'type' => 'checkbox'
+            ],
+            [
+                'key' => 'send_n95',
+                'text' => 'Send N95 samples if appropriate.',
+                'type' => 'readonly'
+            ]
+        ]
+    ]
+];
+
+$category = 'MASKS_AND_RESPIRATORS';
+$endPoint = 'upsertNoteSingleton';
+
+$point = Point::where('added_in_segment_id', $segment->id)->where('category', $category)->orderBy('id', 'DESC')->first();
+
+
+$contentData = [];
+
+foreach ($segmentSections as $segmentSection) {
+    foreach ($segmentSection['points'] as $sectionPoint) {
+        if ($sectionPoint['type'] == 'text') {
+            $contentData[$sectionPoint['key']] = '';
+        } elseif ($sectionPoint['type'] == 'textarea') {
+            $contentData[$sectionPoint['key']] = '';
+        } elseif ($sectionPoint['type'] == 'checkbox') {
+            $contentData[$sectionPoint['key']] = null;
+        } else {
+            $contentData[$sectionPoint['key']] = '';
+        }
+    }
+}
+
+
+if (!!@$point->data) {
+    $contentData = json_decode($point->data, true);
+}
+?>
+
+
+<div class="events-none form-read-mode">
+    @foreach($segmentSections as $section)
+    <div class="mb-2">
+        <h6><b>{{ $section['heading'] }}</b></h6>
+        <ul>
+            @foreach($section['points'] as $point)
+            @if($point['type'] == 'text')
+            @if(@$contentData[$point['key']])
+            <li>{{ $point['text'] }}</li>
+            @endif
+
+            @elseif($point['type'] == 'textarea')
+            @if(@$contentData[$point['key']])
+            <li>
+                <label>{{ $point['text'] }}:</label>
+                <span><?= nl2br($contentData[$point['key']]) ?></span>
+            </li>
+            @endif
+            @elseif($point['type'] == 'checkbox')
+            @if(@$contentData[$point['key']])
+            <li>{{ $point['text'] }}</li>
+            @endif
+            @else
+            <div class="mb-2">
+                <li>{{ $point['text'] }}</li>
+            </div>
+            @endif
+            @endforeach
+        </ul>
+    </div>
+    <hr class="my-3">
+    @endforeach
+
+
+</div>