wip - assignment
This commit is contained in:
parent
6e33729c67
commit
f9491b306f
@ -25,7 +25,8 @@ public static function assignables()
|
|||||||
FROM
|
FROM
|
||||||
studies
|
studies
|
||||||
WHERE
|
WHERE
|
||||||
received_at::DATE >= NOW() - INTERVAL '3 DAY'
|
--received_at::DATE >= NOW() - INTERVAL '3 DAY'
|
||||||
|
assigned_at::DATE >= NOW() - INTERVAL '3 DAY'
|
||||||
AND report_status < 3
|
AND report_status < 3
|
||||||
AND reported_at IS NULL
|
AND reported_at IS NULL
|
||||||
GROUP BY
|
GROUP BY
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use App\DAL\Studies\WorklistFactory;
|
use App\DAL\Studies\WorklistFactory;
|
||||||
use App\Models\Study;
|
use App\Models\Study;
|
||||||
|
use Blade;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
use Illuminate\Database\Eloquent\Builder as QueryBuilder;
|
use Illuminate\Database\Eloquent\Builder as QueryBuilder;
|
||||||
@ -27,21 +28,34 @@ public function dataTable(QueryBuilder $query): EloquentDataTable
|
|||||||
{
|
{
|
||||||
return (new EloquentDataTable($query))
|
return (new EloquentDataTable($query))
|
||||||
->addColumn('action', 'worklist.action')
|
->addColumn('action', 'worklist.action')
|
||||||
->editColumn('patient_name', fn (Study $study) => $study->sanitizedPatientName())
|
->editColumn('patient_name', fn(Study $study) => $study->sanitizedPatientName())
|
||||||
->editColumn('study_description', fn (Study $study) => $study->sanitizedStudyDescription())
|
->editColumn('study_description', fn(Study $study) => $study->sanitizedStudyDescription())
|
||||||
->editColumn('reader', function (Study $study) {
|
->editColumn('reader', function (Study $study) {
|
||||||
if ($study->readingPhysician == null) {
|
if ($study->readingPhysician == null) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '<img class="rounded-circle me-2" height="24px" width="24px" src="' . $study->readingPhysician->avatar() . '"></img>' . $study->readingPhysician->display_name;
|
return Blade::render('staff.worklist.partials._radiologist-listing',
|
||||||
|
[
|
||||||
|
'avatar_url' => $study->readingPhysician->avatar(),
|
||||||
|
'name' => $study->readingPhysician->display_name,
|
||||||
|
'time' => $study->read_at->diffForHumans(),
|
||||||
|
]
|
||||||
|
);
|
||||||
})
|
})
|
||||||
->editColumn('assigned_to', function (Study $study) {
|
->editColumn('assigned_to', function (Study $study) {
|
||||||
|
|
||||||
if ($study->assignedPhysician == null) {
|
if ($study->assignedPhysician == null) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '<img class="rounded-circle me-2" height="24px" width="24px" src="' . $study->assignedPhysician->avatar() . '"></img>' . $study->assignedPhysician->display_name;
|
return Blade::render('staff.worklist.partials._radiologist-listing',
|
||||||
|
[
|
||||||
|
'avatar_url' => $study->assignedPhysician->avatar(),
|
||||||
|
'name' => $study->assignedPhysician->display_name,
|
||||||
|
'time' => $study->assigned_at->diffForHumans(),
|
||||||
|
]
|
||||||
|
);
|
||||||
})
|
})
|
||||||
->editColumn('images', function (Study $study) {
|
->editColumn('images', function (Study $study) {
|
||||||
return $study->numInstances() . '<small class="text-muted ms-2 fw-lighter fs-xsmall">' . human_filesize($study->disk_size) . '</small>';
|
return $study->numInstances() . '<small class="text-muted ms-2 fw-lighter fs-xsmall">' . human_filesize($study->disk_size) . '</small>';
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Staff;
|
namespace App\Http\Controllers\Staff;
|
||||||
|
|
||||||
|
use App\DAL\Radiologist;
|
||||||
use App\Http\Controllers\HashidControllerBase;
|
use App\Http\Controllers\HashidControllerBase;
|
||||||
use App\Http\Requests\AssignPhysicianRequest;
|
use App\Http\Requests\AssignPhysicianRequest;
|
||||||
use App\Models\Enums\UserRole;
|
use App\Models\Enums\UserRole;
|
||||||
use App\Models\Study;
|
use App\Models\Study;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Services\AuditTrail\Activity;
|
use App\Services\AuditTrail\Activity;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Carbon\CarbonInterface;
|
||||||
|
|
||||||
class StudyAssignmentController extends HashidControllerBase
|
class StudyAssignmentController extends HashidControllerBase
|
||||||
{
|
{
|
||||||
@ -15,7 +18,15 @@ public function show()
|
|||||||
{
|
{
|
||||||
$this->decodeKeys();
|
$this->decodeKeys();
|
||||||
$study = Study::with('assignedPhysician')->findOrFail($this->key);
|
$study = Study::with('assignedPhysician')->findOrFail($this->key);
|
||||||
$rads = User::active()->role(UserRole::Radiologist)->get(['id', 'display_name', 'profile_photo_path', 'first_name', 'last_name']);
|
$rads = User::active()->role(UserRole::Radiologist)->get(['id', 'display_name', 'profile_photo_path', 'first_name', 'last_name', 'created_at']);
|
||||||
|
$stats = Radiologist::assignables();
|
||||||
|
foreach ($stats as $rad) {
|
||||||
|
$found = $rads->where('id', $rad->id)->first();
|
||||||
|
if ($found) {
|
||||||
|
$found->info['workload'] = $rad->workload;
|
||||||
|
$found->info['last_seen'] = 'Seen: '. ($rad->last_seen ?? Carbon::now()->addHours(-10))->diffForHumans();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return view('staff.studies.assign-form', compact('study', 'rads'));
|
return view('staff.studies.assign-form', compact('study', 'rads'));
|
||||||
}
|
}
|
||||||
@ -25,7 +36,7 @@ public function remove()
|
|||||||
$this->decodeKeys();
|
$this->decodeKeys();
|
||||||
$study = Study::with('assignedPhysician')->findOrFail($this->key);
|
$study = Study::with('assignedPhysician')->findOrFail($this->key);
|
||||||
if ($study->assigned_physician_id !== null) {
|
if ($study->assigned_physician_id !== null) {
|
||||||
$study->update(['assigned_physician_id' => null]);
|
$study->update(['assigned_physician_id' => null, 'assigned_at' => null]);
|
||||||
audit()
|
audit()
|
||||||
->did(Activity::Unassign_Physician)
|
->did(Activity::Unassign_Physician)
|
||||||
->notes("Unassigned: {$study->assignedPhysician?->display_name}")
|
->notes("Unassigned: {$study->assignedPhysician?->display_name}")
|
||||||
@ -41,7 +52,7 @@ public function save(AssignPhysicianRequest $request)
|
|||||||
$this->decodeKeys();
|
$this->decodeKeys();
|
||||||
$study = Study::findOrFail($this->key);
|
$study = Study::findOrFail($this->key);
|
||||||
$rad = User::active()->findOrFail($request->input('rad_id'));
|
$rad = User::active()->findOrFail($request->input('rad_id'));
|
||||||
$study->update(['assigned_physician_id' => $rad->id]);
|
$study->update(['assigned_physician_id' => $rad->id, 'assigned_at' => now()]);
|
||||||
audit()
|
audit()
|
||||||
->did(Activity::Assign_Physician)
|
->did(Activity::Assign_Physician)
|
||||||
->on($study)
|
->on($study)
|
||||||
|
@ -115,6 +115,11 @@ public function assignedPhysician(): BelongsTo
|
|||||||
return $this->belongsTo(User::class, 'assigned_physician_id');
|
return $this->belongsTo(User::class, 'assigned_physician_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isAssigned(int $rad_id): bool
|
||||||
|
{
|
||||||
|
return $this->assigned_physician_id === $rad_id;
|
||||||
|
}
|
||||||
|
|
||||||
public function getReportStatusLedAttribute(): string
|
public function getReportStatusLedAttribute(): string
|
||||||
{
|
{
|
||||||
$color = match ($this->report_status) {
|
$color = match ($this->report_status) {
|
||||||
|
@ -151,4 +151,6 @@ protected function casts(): array
|
|||||||
'password' => 'hashed',
|
'password' => 'hashed',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public array $info = [];
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
<div>
|
<div class="row mb-2">
|
||||||
Currently assigned: {{ $study->assignedPhysician?->display_name ?? 'None' }}
|
<div class="col-4">
|
||||||
@isset($study->assignedPhysician)
|
Currently assigned: {{ $study->assignedPhysician?->display_name }}
|
||||||
<form action="{{ route('staff.assign.remove', $study->hash) }}" class="inline" method="post">
|
</div>
|
||||||
@csrf
|
<div class="col-2">
|
||||||
@method('DELETE')
|
@isset($study->assignedPhysician)
|
||||||
<button class="btn btn-danger btn-xs" type="submit">Remove</button>
|
<form action="{{ route('staff.assign.remove', $study->hash) }}" class="inline" method="post">
|
||||||
</form>
|
@csrf
|
||||||
@endisset
|
@method('DELETE')
|
||||||
|
<button class="btn btn-danger btn-xs" type="submit">Remove</button>
|
||||||
|
</form>
|
||||||
|
@endisset
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-sm table-borderless">
|
<table class="table table-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Physician</th>
|
<th>Physician</th>
|
||||||
@ -29,20 +33,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<span class="text-truncate fw-semibold mb-0">{{ $doc->display_name }}</span>
|
<span class="text-truncate fw-semibold mb-0">
|
||||||
<small class="text-truncate">last seen</small>
|
{{ $doc->display_name }}
|
||||||
|
@if($study->isAssigned($doc->id))
|
||||||
|
<span class="badge bg-success badge-dot ms-2"></span>
|
||||||
|
@endif
|
||||||
|
</span>
|
||||||
|
<small class="text-truncate fw-light text-muted">{{ $doc->info['last_seen'] }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
0 / 0
|
{{ $doc->info['workload'] }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<form action="{{ route('staff.assign.save', $study->hash) }}" class="inline" method="post">
|
@if($study->isAssigned($doc->id))
|
||||||
@csrf
|
@else
|
||||||
<input type="hidden" name="rad_id" value="{{ $doc->id }}">
|
<form action="{{ route('staff.assign.save', $study->hash) }}" class="inline" method="post">
|
||||||
<button class="btn btn-primary btn-xs" type="submit">Assign</button>
|
@csrf
|
||||||
</form>
|
<input type="hidden" name="rad_id" value="{{ $doc->id }}">
|
||||||
|
<button class="btn btn-primary btn-xs" type="submit">Assign</button>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
<div class="d-flex justify-content-start">
|
||||||
|
<div class="avatar-wrapper">
|
||||||
|
<div class="avatar avatar-sm me-2">
|
||||||
|
<img src="{{ $avatar_url }}" class="rounded-circle">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<span class="text-truncate fw-light mb-1">
|
||||||
|
{{ $name }}
|
||||||
|
</span>
|
||||||
|
<small class="text-truncate fw-lighter text-muted">
|
||||||
|
{{ $time }}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in New Issue
Block a user