Deploy Ladill Care / deploy (push) Successful in 1m0s
Phase 3 staff management: real shift entities, week roster linked to temporary assignments, and a nursing ops module surface (registry, today’s allocation, unit shortcuts). Co-authored-by: Cursor <cursoragent@cursor.com>
218 lines
13 KiB
PHP
218 lines
13 KiB
PHP
<x-app-layout title="{{ $unit->name }}">
|
|
<div class="space-y-6">
|
|
<div class="flex flex-wrap items-start justify-between gap-4">
|
|
<div>
|
|
<p class="text-sm text-slate-500">
|
|
<a href="{{ route('care.care-units.index') }}" class="text-indigo-600 hover:text-indigo-800">Care units</a>
|
|
<span class="text-slate-300">/</span>
|
|
{{ $unit->department?->name }}
|
|
</p>
|
|
<h1 class="mt-1 text-2xl font-semibold text-slate-900">{{ $unit->name }}</h1>
|
|
<p class="mt-1 text-sm text-slate-500">
|
|
{{ $kinds[$unit->kind] ?? $unit->kind }}
|
|
@if ($unit->code) · {{ $unit->code }} @endif
|
|
· {{ $unit->department?->branch?->name }}
|
|
@unless ($unit->is_active)
|
|
· <span class="text-amber-700">Inactive</span>
|
|
@endunless
|
|
</p>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
@php
|
|
$member = auth()->user()
|
|
? app(\App\Services\Care\OrganizationResolver::class)->memberFor(auth()->user())
|
|
: null;
|
|
$permissions = app(\App\Services\Care\CarePermissions::class);
|
|
$canManageUnit = $permissions->can($member, 'admin.departments.manage');
|
|
$canMar = $permissions->can($member, 'mar.view');
|
|
$canNotes = $permissions->can($member, 'nursing.notes.view');
|
|
$canHandover = $permissions->can($member, 'nursing.handover.view');
|
|
$canAssess = $permissions->can($member, 'nursing.assessments.view');
|
|
$canPerf = $permissions->can($member, 'nursing.performance.view');
|
|
$canRoster = $permissions->can($member, 'nursing.roster.view');
|
|
@endphp
|
|
@if ($canMar)
|
|
<a href="{{ route('care.care-units.mar', $unit) }}" class="btn-primary">MAR board</a>
|
|
@endif
|
|
@if ($canRoster)
|
|
<a href="{{ route('care.care-units.roster', $unit) }}" class="btn-secondary">Duty roster</a>
|
|
@endif
|
|
@if ($canAssess)
|
|
<a href="{{ route('care.care-units.assessments', $unit) }}" class="btn-secondary">Assessments</a>
|
|
@endif
|
|
@if ($canNotes)
|
|
<a href="{{ route('care.care-units.notes', $unit) }}" class="btn-secondary">Nursing notes</a>
|
|
@endif
|
|
@if ($canHandover)
|
|
<a href="{{ route('care.care-units.handovers', $unit) }}" class="btn-secondary">Handovers</a>
|
|
@endif
|
|
@if ($canPerf)
|
|
<a href="{{ route('care.care-units.performance', $unit) }}" class="btn-secondary">Performance</a>
|
|
@endif
|
|
@if ($canManageUnit)
|
|
<a href="{{ route('care.care-units.edit', $unit) }}" class="btn-secondary">Edit unit</a>
|
|
<a href="{{ route('care.staff-assignments.create', ['care_unit_id' => $unit->id]) }}" class="btn-secondary">Assign staff</a>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Current patients --}}
|
|
<div class="rounded-2xl border border-slate-200 bg-white p-6">
|
|
<div class="flex flex-wrap items-center justify-between gap-3">
|
|
<div>
|
|
<h2 class="text-base font-semibold text-slate-900">Patients on this unit</h2>
|
|
<p class="text-sm text-slate-500">Active visit placements — open MAR, notes, and handovers from the actions above.</p>
|
|
</div>
|
|
<p class="text-sm font-medium text-slate-700">{{ $placedVisits->count() }} placed</p>
|
|
</div>
|
|
|
|
<div class="mt-4 overflow-x-auto">
|
|
<table class="min-w-full text-sm">
|
|
<thead class="text-left text-xs uppercase text-slate-500">
|
|
<tr>
|
|
<th class="pb-2 pr-4">Patient</th>
|
|
<th class="pb-2 pr-4">Bed</th>
|
|
<th class="pb-2 pr-4">Placed</th>
|
|
<th class="pb-2"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-100">
|
|
@forelse ($placedVisits as $visit)
|
|
<tr>
|
|
<td class="py-3 pr-4 font-medium">
|
|
{{ $visit->patient?->fullName() ?? '—' }}
|
|
@if ($visit->patient?->patient_number)
|
|
<span class="text-xs text-slate-400">{{ $visit->patient->patient_number }}</span>
|
|
@endif
|
|
</td>
|
|
<td class="py-3 pr-4">{{ $visit->bed?->label ?? '—' }}</td>
|
|
<td class="py-3 pr-4 whitespace-nowrap">{{ $visit->placed_at?->format('d M Y H:i') ?? '—' }}</td>
|
|
<td class="py-3 text-right whitespace-nowrap">
|
|
@if ($canMar ?? false)
|
|
<a href="{{ route('care.visits.mar', $visit) }}" class="mr-2 text-indigo-600 hover:text-indigo-800">MAR</a>
|
|
@endif
|
|
@if ($canPlace)
|
|
<form method="POST" action="{{ route('care.visits.placement.destroy', $visit) }}" class="inline" onsubmit="return confirm('Discharge placement and free the bed?')">
|
|
@csrf @method('DELETE')
|
|
<button type="submit" class="text-red-600 hover:text-red-800">Discharge bed</button>
|
|
</form>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr><td colspan="4" class="py-4 text-slate-500">No patients placed on this unit.</td></tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
@if ($canPlace && $unit->kind !== 'float_pool')
|
|
<form method="POST" action="{{ route('care.care-units.placements.store', $unit) }}" class="mt-6 grid gap-3 border-t border-slate-100 pt-5 sm:grid-cols-4">
|
|
@csrf
|
|
<div class="sm:col-span-2">
|
|
<label class="block text-xs font-medium uppercase text-slate-500">Open visit</label>
|
|
<select name="visit_id" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
<option value="">Select patient visit…</option>
|
|
@foreach ($placeableVisits as $visit)
|
|
<option value="{{ $visit->id }}">
|
|
{{ $visit->patient?->fullName() ?? 'Patient' }}
|
|
· {{ $visit->checked_in_at?->format('d M H:i') ?? $visit->status }}
|
|
@if ($visit->careUnit) (now: {{ $visit->careUnit->name ?? 'placed' }}) @endif
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
@error('visit_id')<p class="mt-1 text-xs text-red-600">{{ $message }}</p>@enderror
|
|
@error('care_unit_id')<p class="mt-1 text-xs text-red-600">{{ $message }}</p>@enderror
|
|
@error('bed_id')<p class="mt-1 text-xs text-red-600">{{ $message }}</p>@enderror
|
|
</div>
|
|
@if ($unit->supportsBeds())
|
|
<div>
|
|
<label class="block text-xs font-medium uppercase text-slate-500">Bed</label>
|
|
<select name="bed_id" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
<option value="">No bed yet</option>
|
|
@foreach ($availableBeds as $bed)
|
|
<option value="{{ $bed->id }}">{{ $bed->label }}@if ($bed->room) ({{ $bed->room }}) @endif</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
@else
|
|
<div></div>
|
|
@endif
|
|
<div class="flex items-end">
|
|
<button type="submit" class="btn-primary w-full">Place on unit</button>
|
|
</div>
|
|
</form>
|
|
@endif
|
|
</div>
|
|
|
|
@if ($unit->supportsBeds())
|
|
<div class="rounded-2xl border border-slate-200 bg-white p-6">
|
|
<div class="flex items-center justify-between gap-3">
|
|
<div>
|
|
<h2 class="text-base font-semibold text-slate-900">Beds</h2>
|
|
<p class="text-sm text-slate-500">Rooms and bed labels for this inpatient unit.</p>
|
|
</div>
|
|
</div>
|
|
|
|
@if ($canManageUnit ?? false)
|
|
<form method="POST" action="{{ route('care.care-units.beds.store', $unit) }}" class="mt-4 grid gap-3 sm:grid-cols-4">
|
|
@csrf
|
|
<input type="text" name="label" required placeholder="Bed label" class="rounded-lg border-slate-300 text-sm" value="{{ old('label') }}">
|
|
<input type="text" name="room" placeholder="Room" class="rounded-lg border-slate-300 text-sm" value="{{ old('room') }}">
|
|
<select name="status" class="rounded-lg border-slate-300 text-sm">
|
|
@foreach ($bedStatuses as $value => $label)
|
|
<option value="{{ $value }}" @selected(old('status', 'available') === $value)>{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
<button type="submit" class="btn-primary">Add bed</button>
|
|
</form>
|
|
@endif
|
|
|
|
<div class="mt-4 overflow-x-auto">
|
|
<table class="min-w-full text-sm">
|
|
<thead class="text-left text-xs uppercase text-slate-500">
|
|
<tr>
|
|
<th class="pb-2 pr-4">Label</th>
|
|
<th class="pb-2 pr-4">Room</th>
|
|
<th class="pb-2 pr-4">Status</th>
|
|
<th class="pb-2 pr-4">Occupant</th>
|
|
<th class="pb-2"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-100">
|
|
@forelse ($unit->beds as $bed)
|
|
@php
|
|
$occupant = $placedVisits->firstWhere('bed_id', $bed->id);
|
|
@endphp
|
|
<tr class="{{ $bed->is_active ? '' : 'opacity-50' }}">
|
|
<td class="py-3 pr-4 font-medium">{{ $bed->label }}</td>
|
|
<td class="py-3 pr-4">{{ $bed->room ?: '—' }}</td>
|
|
<td class="py-3 pr-4">{{ $bedStatuses[$bed->status] ?? $bed->status }}</td>
|
|
<td class="py-3 pr-4">{{ $occupant?->patient?->fullName() ?? '—' }}</td>
|
|
<td class="py-3 text-right">
|
|
@if ($canManageUnit ?? false)
|
|
<form method="POST" action="{{ route('care.care-units.beds.destroy', [$unit, $bed]) }}" class="inline" onsubmit="return confirm('Remove this bed?')">
|
|
@csrf @method('DELETE')
|
|
<button type="submit" class="text-red-600 hover:text-red-800">Remove</button>
|
|
</form>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr><td colspan="5" class="py-4 text-slate-500">No beds yet.</td></tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
@else
|
|
<div class="rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-6 py-5 text-sm text-slate-600">
|
|
This unit kind does not use beds. Outpatient clinics, service units, and float pools assign staff without bed inventory.
|
|
@if ($unit->kind === 'float_pool')
|
|
Patients cannot be placed on a float pool.
|
|
@endif
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</x-app-layout>
|