소스 검색

Added Survey

Samson Mutunga 1 년 전
부모
커밋
974cdcc9d3

+ 8 - 0
app/Helpers/helpers.php

@@ -1168,4 +1168,12 @@ if(!function_exists('getDefaultCompanyClientUidSession')) {
     function getDefaultCompanyClientUidSession($patientID) {
         return session()->get('DEFAULT_COMPANY_CLIENT_UID_'.$patientID);
     }
+}
+
+if(!function_exists('formatAsTitle')) {
+    function formatAsTitle($inputString) {
+        $cleanString = preg_replace('/[^a-zA-Z0-9\s]/', '', $inputString);
+        $titleCaseString = ucwords(strtolower($cleanString));        
+        return $titleCaseString;
+    }
 }

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

@@ -34,6 +34,7 @@ use Illuminate\Support\Facades\Http;
 use PDF;
 use Illuminate\Support\Facades\Schema;
 use App\Models\AdminPatient;
+use App\Models\Survey;
 use App\Models\SupplyOrderView;
 use Illuminate\Pagination\LengthAwarePaginator;
 
@@ -830,4 +831,56 @@ class AdminController extends Controller
         return view('app.admin.patients-notes-points-filter', compact('records', 'filters'));
     }
 
+    public function surveys(Request $request)
+    {
+        $entityTypes = Survey::ALLOWED_ENTITIES;
+        $surveyFormsPath = resource_path(Survey::FORM_PATH);
+        $filesInFolder = File::allFiles($surveyFormsPath);
+        $forms = [];
+
+
+        foreach ($filesInFolder as $path) {
+            $file = pathinfo($path);
+            $fileName = $file['filename'];
+            $internalName = explode('.', $fileName)[0];
+            $forms[] = $internalName;
+        }
+        
+        $records = Survey::paginate(5);
+        return view('app.admin.surveys.list', compact('forms', 'records', 'entityTypes'));
+    }
+
+    public function getEntityRecords(Request $request)
+    {
+        $term = $request->get('term');
+        $type = $request->get('type');
+        if(!in_array($type, Survey::ALLOWED_ENTITIES)){
+            return $this->fail('Invalid entity type');
+        }
+        $records = [];
+        if($type === 'client'){
+            $clients = Client::query();
+            $clients = $clients->where('is_active', true);
+
+            $clients = $clients->where(function ($q) use ($term) {
+                $q->orWhereRaw('LOWER(name_first::text) LIKE ?', ['%' . $term . '%'])
+                    ->orWhereRaw('LOWER(name_last::text) LIKE ?', ['%' . $term . '%'])
+                    ->orWhereRaw('LOWER(email_address::text) LIKE ?', ['%' . $term . '%'])
+                    ->orWhereRaw('cell_number LIKE ?', ['%' . $term . '%']);
+            });
+            $clients = $clients->orderBy('name_first', 'ASC')->limit(10)->get();
+            $clientsData = $clients->map(function($client) {
+                return [
+                    "uid" => $client->uid,
+                    "id" => $client->id,
+                    "text" => $client->displayName(),
+                ];
+            });
+            return json_encode([
+                "results" => $clientsData
+            ]);
+        }
+
+        return $this->pass($records);
+    }
 }

+ 37 - 0
app/Http/Controllers/GuestController.php

@@ -10,6 +10,7 @@ use App\Models\Handout;
 use App\Models\HandoutClient;
 use App\Models\Pro;
 use App\Models\Section;
+use App\Models\Survey;
 use App\Models\SectionTemplate;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\File;
@@ -103,4 +104,40 @@ class GuestController extends Controller
         return $response;
     }
 
+    public function viewSurveyForm(Request $request, $accessKey){
+        $survey = Survey::where('access_key', $accessKey)->where('is_accessible_to_target', true)->where('is_active', true)->first();
+        if(!$survey) abort(404);
+
+        $surveyFormPath = resource_path(Survey::FORM_PATH . '/' . $survey->internal_name . '.blade.php');
+        if(!file_exists($surveyFormPath)) abort(404);
+
+        $entity = null;
+        if($survey->entity_type === 'Client'){
+            $entity = Client::where('uid', $survey->entity_uid)->first();
+        }
+
+        if(!$entity) abort(404);
+
+        return view('app.admin.surveys.forms.'.$survey->internal_name, compact('entity', 'survey'));
+    }
+
+    public function viewSurveyFormSubmit(Request $request, $accessKey){
+        $survey = Survey::where('access_key', $accessKey)->where('is_accessible_to_target', true)->where('is_active', true)->first();
+        if(!$survey) abort(404);
+
+        $data = $request->all();
+        unset($data['_token']);
+
+        $url = '/survey/submitData';
+        $response = $this->calljava($request, $url, [
+            'uid' => $survey->uid,
+            'surveyDataJson' => json_encode($data)
+        ]);
+
+        if($response['success']){
+            return redirect()->back()->with('success', 'Information saved!');
+        }
+        return redirect()->back()->with('error', $response['message']);
+        
+    }
 }

+ 28 - 0
app/Models/Survey.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Models;
+
+class Survey extends Model
+{
+    protected $table = 'survey';
+
+    const FORM_PATH = "views/app/admin/surveys/forms";
+    const ALLOWED_ENTITIES = [
+        'Client',
+    ];
+
+    public function getFieldValue($field){
+        $data = json_decode($this->survey_data);
+        return @$data->{$field};
+    }
+
+    public function getEntity(){
+        $entity = null;
+        if($this->entity_type === 'Client'){
+            $entity = Client::where('uid', $this->entity_uid)->first();
+        }
+
+        return $entity;
+    }
+
+}

+ 44 - 0
resources/views/app/admin/surveys/forms/sleep.blade.php

@@ -0,0 +1,44 @@
+@extends ('app.admin.surveys.partials.form-layout')
+
+@section('content')
+<div class="card">
+    <div class="card-header">
+        Hi {{ $entity->displayName() }}
+    </div>
+    <div class="card-body">
+        <form action="{{ route('view-survey-form-submit', $survey->access_key) }}" method="POST">
+            @csrf
+            <div class="row">
+                <div class="col-md-4">
+                    <div class="form-group">
+                        <label>First Name</label>
+                        <input type="text" class="form-control" name="nameFirst" value="{{ $survey->getFieldValue('nameFirst') }}" />
+                    </div>
+                </div>
+                <div class="col-md-4">
+                    <div class="form-group">
+                        <label>Middle Name</label>
+                        <input type="text" class="form-control" name="nameMiddle" value="{{ $survey->getFieldValue('nameMiddle') }}" />
+                    </div>
+                </div>
+                <div class="col-md-4">
+                    <div class="form-group">
+                        <label>Last Name</label>
+                        <input type="text" class="form-control" name="nameFirst" value="{{ $survey->getFieldValue('nameFirst') }}" />
+                    </div>
+                </div>
+                <div class="col-md-12">
+                    <div class="form-group">
+                        <label>Explain your sleep issue</label>
+                        <textarea class="form-control" name="description">{{ $survey->getFieldValue('description') }}</textarea>
+                    </div>
+                </div>
+                <div class="col-md-12">
+                    <button class="btn btn-sm btn-primary">Submit</button>
+                </div>
+            </div>
+
+        </form>
+    </div>
+</div>
+@endsection

+ 83 - 0
resources/views/app/admin/surveys/list.blade.php

@@ -0,0 +1,83 @@
+@extends ('layouts/template')
+
+@section('content')
+<link href="/select2/select2.min.css" rel="stylesheet" />
+<script src="/select2/select2.min.js"></script>
+
+<div class="p-3 mcp-theme-1" id="patients-list">
+	<div class="card">
+		<div class="card-header px-3 py-2">
+            <div class="d-flex justify-content-between">
+                <div>
+                    <strong class="mr-4">
+                        <i class="fas fa-list"></i>
+                        Surveys
+                    </strong>
+                </div>
+                <div>
+                    @include("app.admin.surveys.partials.create")
+                </div>
+            </div>
+			
+		</div>
+		{{-- <div class="p-3">
+			filter blade
+		</div> --}}
+		<table class="table table-striped p-0 m-0 table-sm border-top border-bottom ">
+			<thead class="bg-light">
+				<tr>
+					<th class="border-0">Date</th>
+					<th class="border-0">Internal Name</th>
+					<th class="border-0">Title</th>
+					<th class="border-0">Data</th>
+					<th class="border-0">Entity Type</th>
+					<th class="border-0">Name</th>
+					<th class="border-0">Is Accessible to Target</th>
+					<th class="border-0">Access Link</th>
+				</tr>
+			</thead>
+			<tbody>
+				@foreach($records as $record)
+				<tr>
+					<td>{{ friendly_date($record->created_at) }}</td>
+					<td>{{ $record->internal_name }}</td>
+					<td>{{ $record->title }}</td>
+					<td><?= parseRender(json_decode($record->survey_data ?? '{}')) ?></td>
+					<td>{{ $record->entity_type }}</td>
+					<td>
+                        @if($record->entity_type === 'Client')
+                            {{ $record->getEntity()->displayName() }}
+                        @else
+                            ---
+                        @endif
+                    </td>
+					<td>{{ $record->is_accessible_to_target ? 'YES' : 'NO' }}</td>
+					<td>
+                        @if($record->is_accessible_to_target)
+                            <a href="{{ route('view-survey-form', $record->access_key) }}" target="_blank" class="mr-2" native>Open Link</a>
+                            @include("app.admin.surveys.partials.revoke-access-to-target")
+                        @else
+                            @include("app.admin.surveys.partials.grant-access-to-target")
+                        @endif
+                    </td>
+					
+				</tr>
+				@endforeach
+
+				@if(count($records) === 0)
+				<tr>
+					<td colspan="8">No records found!</td>
+				</tr>
+				@endif
+			</tbody>
+
+		</table>
+	</div>
+	<div class="p-3">
+		{{$records->withQueryString()->links()}}
+	</div>
+
+</div>
+</div>
+</div>
+@endsection

+ 106 - 0
resources/views/app/admin/surveys/partials/create.blade.php

@@ -0,0 +1,106 @@
+<div moe>
+    <a href="" start show class="">+ Create </a>
+
+    <form url="/api/survey/create" class="mcp-theme-1" right>
+        <div id="createSurveyForm" v-cloak>
+            <div class="form-group">
+                <label>Title</label>
+                <input type="text" name="title" class="form-control" />
+            </div>
+            <div class="form-group">
+                <label>Internal Name</label>
+                <select name="internalName" class="form-control">
+                    <option value=""></option>
+                    @foreach ($forms as $form)
+                        <option value="{{ $form }}">{{ formatAsTitle($form) }}</option>
+                    @endforeach
+                </select>
+            </div>
+            <div class="form-group">
+                <label>Entity Type</label>
+                <select name="entityType" class="form-control" v-model="form.entityType" @change="onEntityTypeChange">
+                    <option value=""></option>
+                    @foreach ($entityTypes as $entityType)
+                        <option value="{{ $entityType }}">{{ formatAsTitle($entityType) }}</option>
+                    @endforeach
+                </select>
+            </div>
+            <div v-if="form.entityType" class="form-group">
+                <label>Entity</label>
+                <select name="entityUid" class="form-control" v-model="form.entityUid">
+                    <option value=""></option>
+                </select>
+            </div>
+        </div>
+        <div class="form-group text-nowrap mb-0">
+            <button class="btn btn-sm btn-primary" submit>Submit</button>
+            <button class="btn btn-sm btn-default border" close>Close</button>
+        </div>
+    </form>
+
+    <script>
+        (function() {
+            function init() {
+                new Vue({
+                    el: '#createSurveyForm',
+                    delimiters: ['@{{ ', ' }}'],
+                    data: {
+                        form: {
+                            entityType: null
+                        },
+                        entityRecords: []
+                    },
+                    methods: {
+                        onEntityTypeChange: function() {
+                            var self = this;
+                            if (!self.form.entityType.length) return;
+                            self.$nextTick(function(){
+                                self.initAutoSuggest();
+                            });
+                        },
+                        initAutoSuggest: function() {
+                            var self = this;
+                            var select2 = $("select[name=entityUid]").select2({
+                                placeholder: "Search " + self.form.entityType,
+                                minimumInputLength: 2,
+                                ajax: {
+                                    url: '{{ route("admin.get-entity-records") }}',
+                                    dataType: 'json',
+                                    type: "GET",
+                                    quietMillis: 50,
+                                    data: function(params) {
+                                        return {
+                                            term: params.term,
+                                            json: true,
+                                            type: self.form.entityType,
+                                        };
+                                    },
+                                    processResults: function(data) {
+                                        data = data.results || [];
+                                        return {
+                                            results: $.map(data, function(item) {
+                                                return {
+                                                    text: item.text,
+                                                    id: item.uid
+                                                }
+                                            })
+                                        };
+                                    }
+                                }
+                            });
+
+                        },
+                        init: function() {
+
+                        },
+                    },
+                    mounted: function() {
+                        this.init();
+                    },
+                });
+
+
+            }
+            addMCInitializer('createSurveyForm', init, '#createSurveyForm');
+        })();
+    </script>

+ 84 - 0
resources/views/app/admin/surveys/partials/form-layout.blade.php

@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="csrf-token" content="{{ csrf_token() }}">
+
+    <title>{{ config('app.name') }}</title>
+
+    <!-- Fonts -->
+    <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
+
+    {{-- mc initializers --}}
+    <script src="/js/mc-init.js?v={{config('app.asset_version')}}"></script>
+
+    {{-- vue --}}
+    <script src="/js/vue.js"></script>
+
+
+    <!-- <link href="{{ asset('bootstrap-4.5.0/css/bootstrap.css') }}" rel="stylesheet"> -->
+    <link rel="stylesheet" href="/fontawesome-free-5.13.1-web/css/all.min.css">
+    <link href="{{ asset('/css/app.css') }}?v={{config('app.asset_version')}}" rel="stylesheet">
+    <link href="{{ asset('/css/style.css') }}?v={{config('app.asset_version')}}" rel="stylesheet">
+    <link href="{{ asset('/css/yemi.css') }}?v={{config('app.asset_version')}}" rel="stylesheet">
+    <link rel="stylesheet" href="{{ asset('/css/toastr.min.css') }}">
+    <link href="{{asset('/css/z.css')}}?v={{config('app.asset_version')}}" rel=stylesheet>
+    <!-- Styles -->
+
+    <script src="{{ asset('js/app.js') }}?v={{config('app.asset_version')}}" type="application/javascript"></script>
+    <script src="/js/jquery-3.5.1.min.js"></script>
+    <script src="/js/jquery.form.min.js"></script>
+    <script src="{{ asset('js/toastr.min.js') }}" type="application/javascript"></script>
+    <script src="/js/yemi.js?v={{config('app.asset_version')}}" type="application/javascript"></script>
+
+
+
+    <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+
+
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.0/sockjs.min.js"
+            integrity="sha512-5yJ548VSnLflcRxWNqVWYeQZnby8D8fJTmYRLyvs445j1XmzR8cnWi85lcHx3CUEeAX+GrK3TqTfzOO6LKDpdw=="
+            crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"
+            integrity="sha512-iKDtgDyTHjAitUDdLljGhenhPwrbBfqTKWO1mkhSFH3A7blITC9MhYon6SjnMhp4o0rADGw9yAC6EW4t5a4K3g=="
+            crossorigin="anonymous"></script>
+
+
+
+    <script type="text/javascript">
+        $(function() {
+            $.ajaxSetup({
+                headers: {
+                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
+                }
+            });
+        });
+    </script>
+
+    @yield('head')
+</head>
+
+<body>
+
+    <main role="main" class="stag-content px-0">
+        <div class="container">
+            <div class="row">
+                <div class="col-12">
+                    @if(session('success'))
+                        <div class="alert alert-success rounded-0">{{ session('success') }}</div>
+                    @endif
+                    @if(session('error'))
+                        <div class="alert alert-danger rounded-0">{{ session('error') }}</div>
+                    @endif
+                    @yield('content')
+                </div>
+            </div>
+        </div>
+    </main>
+
+
+</body>
+
+</html>

+ 11 - 0
resources/views/app/admin/surveys/partials/grant-access-to-target.blade.php

@@ -0,0 +1,11 @@
+<div moe>
+    <a href="" start show class="">Grant Access</a>
+
+    <form url="/api/survey/grantAccessToTarget" class="mcp-theme-1" right>
+        <input type="hidden" name="uid" value="{{ $record->uid }}" />
+        <label>Are you sure?</label>
+        <div class="form-group text-nowrap mb-0">
+            <button class="btn btn-sm btn-primary" submit>Grant Access</button>
+            <button class="btn btn-sm btn-default border" close>Close</button>
+        </div>
+    </form>

+ 11 - 0
resources/views/app/admin/surveys/partials/revoke-access-to-target.blade.php

@@ -0,0 +1,11 @@
+<div moe>
+    <a href="" start show class="text-danger">Revoke Access</a>
+
+    <form url="/api/survey/revokeAccessToTarget" class="mcp-theme-1" right>
+        <input type="hidden" name="uid" value="{{ $record->uid }}" />
+        <label>Are you sure?</label>
+        <div class="form-group text-nowrap mb-0">
+            <button class="btn btn-sm btn-danger" submit>Revoke Access</button>
+            <button class="btn btn-sm btn-default border" close>Close</button>
+        </div>
+    </form>

+ 1 - 0
resources/views/layouts/template.blade.php

@@ -275,6 +275,7 @@
                             <a class="dropdown-item" href="{{ route('management-stats') }}">Management Stats</a>
                             <a class="dropdown-item" href="{{ route('messages') }}">Messages</a>
                             <a class="dropdown-item" href="{{ route('admin.patients-notes-points-filter') }}">Patients Notes Points Filter</a>
+                            <a class="dropdown-item" href="{{ route('admin.surveys') }}">Surveys</a>
                         </div>
                     </li>
                     <li class="nav-item dropdown">

+ 4 - 1
routes/web.php

@@ -28,7 +28,8 @@ use App\Http\Controllers\RdController;
  * [Cell Number] [Password] field -> proLogInWithPassword -> /pro/dashboard
  * -> they are authenticated in... see the home dashboard... logout button to -> /login
  */
-
+Route::get('survey/{accessKey}', 'GuestController@viewSurveyForm')->name('view-survey-form');
+Route::post('survey/{accessKey}/submit', 'GuestController@viewSurveyFormSubmit')->name('view-survey-form-submit');
 Route::get('login', 'LoginController@showLoginForm')->name('login');
 Route::post('login', 'LoginController@login');
 Route::get('logout', 'LoginController@logout');
@@ -279,6 +280,8 @@ Route::middleware('pro.auth')->group(function () {
         Route::get('patients-missing-defult-settings', 'AdminController@patientsMissingDefasultSettings')->name('patientsMissingDefasultSettings');
         Route::get('points', 'AdminController@points')->name('points');
         Route::get('patients-notes-points-filter', 'AdminController@patientsNotesPointsFilter')->name('patients-notes-points-filter');
+        Route::get('surveys', 'AdminController@surveys')->name('surveys');
+        Route::get('surveys/get-entity-records', 'AdminController@getEntityRecords')->name('get-entity-records');
     });
     Route::middleware('pro.auth.admin')->group(function () {
         Route::get('mgmt-stats', [ManagementStatsController::class, 'index'])->name('management-stats');