Files
ladill-care/resources/views/care/nursing/roster.blade.php
T
isaaccladandCursor b7aca6ee2b
Deploy Ladill Care / deploy (push) Successful in 30s
Separate unit placements from shift duty assignments.
Roster no longer writes temporary staff assignments; unit assignment UI drops shift fields and labels clarify the two workflows.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-20 11:49:18 +00:00

125 lines
8.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<x-app-layout title="Roster · {{ $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.show', $unit) }}" class="text-indigo-600 hover:text-indigo-800">{{ $unit->name }}</a>
<span class="text-slate-300">/</span>
Duty roster
</p>
<h1 class="mt-1 text-2xl font-semibold text-slate-900">Shift assignments</h1>
<p class="mt-1 text-sm text-slate-500">
{{ $weekStart->format('d M Y') }} {{ $weekStart->copy()->addDays(6)->format('d M Y') }}
· {{ $unit->department?->name }}
</p>
</div>
<div class="flex flex-wrap items-center gap-2">
<a href="{{ route('care.care-units.roster', ['careUnit' => $unit, 'week' => $prevWeek]) }}" class="btn-secondary">Previous</a>
<a href="{{ route('care.care-units.roster', ['careUnit' => $unit, 'week' => now()->startOfWeek(\Carbon\Carbon::MONDAY)->toDateString()]) }}" class="btn-secondary">This week</a>
<a href="{{ route('care.care-units.roster', ['careUnit' => $unit, 'week' => $nextWeek]) }}" class="btn-secondary">Next</a>
@if ($canManage)
<a href="{{ route('care.shifts.index') }}" class="btn-secondary">Shift templates</a>
@endif
</div>
</div>
<div class="overflow-x-auto rounded-2xl border border-slate-200 bg-white">
<table class="min-w-full text-sm">
<thead class="bg-slate-50 text-left text-xs uppercase text-slate-500">
<tr>
<th class="sticky left-0 z-10 bg-slate-50 px-3 py-3">Shift</th>
@foreach ($days as $day)
<th class="min-w-[9rem] px-3 py-3 {{ $day->isToday() ? 'bg-indigo-50 text-indigo-700' : '' }}">
<div>{{ $day->format('D') }}</div>
<div class="font-normal normal-case text-slate-400">{{ $day->format('d M') }}</div>
</th>
@endforeach
</tr>
</thead>
<tbody class="divide-y divide-slate-100">
@foreach ($shifts as $shift)
<tr>
<td class="sticky left-0 z-10 bg-white px-3 py-3 align-top">
<div class="flex items-center gap-2 font-medium text-slate-900">
<span class="inline-block h-2.5 w-2.5 rounded-full" style="background: {{ $shift->color ?? '#64748b' }}"></span>
{{ $shift->label }}
</div>
<div class="mt-0.5 text-xs text-slate-400">{{ $shift->timeLabel() }}</div>
</td>
@foreach ($days as $day)
@php
$key = $day->toDateString().'|'.$shift->id;
$entries = $cells[$key] ?? [];
@endphp
<td class="px-2 py-2 align-top {{ $day->isToday() ? 'bg-indigo-50/40' : '' }}">
<div class="space-y-1.5">
@forelse ($entries as $entry)
<div class="rounded-lg border border-slate-100 bg-slate-50 px-2 py-1.5">
<div class="text-xs font-medium text-slate-800">
{{ $memberLabels[$entry->member_id] ?? ($entry->member?->user_ref ?? 'Staff') }}
</div>
@if ($canManage)
<form method="POST" action="{{ route('care.care-units.roster.destroy', [$unit, $entry]) }}" class="mt-1" onsubmit="return confirm('Remove from roster?')">
@csrf
@method('DELETE')
<button type="submit" class="text-[11px] text-red-600 hover:text-red-800">Remove</button>
</form>
@endif
</div>
@empty
<p class="px-1 text-[11px] text-slate-300"></p>
@endforelse
</div>
</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
</div>
@if ($canManage)
<div class="rounded-2xl border border-slate-200 bg-white p-6">
<h2 class="text-base font-semibold text-slate-900">Add shift assignment</h2>
<p class="mt-1 text-sm text-slate-500">Schedules who works this unit on a specific date and shift. Does not change their unit placement.</p>
<form method="POST" action="{{ route('care.care-units.roster.store', $unit) }}" class="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-5">
@csrf
<div>
<label class="block text-xs font-medium uppercase text-slate-500">Date</label>
<input type="date" name="duty_date" value="{{ old('duty_date', now()->toDateString()) }}" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
@error('duty_date')<p class="mt-1 text-xs text-red-600">{{ $message }}</p>@enderror
</div>
<div>
<label class="block text-xs font-medium uppercase text-slate-500">Shift</label>
<select name="shift_id" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
@foreach ($shifts as $shift)
<option value="{{ $shift->id }}" @selected(old('shift_id') == $shift->id)>{{ $shift->label }} ({{ $shift->timeLabel() }})</option>
@endforeach
</select>
@error('shift_id')<p class="mt-1 text-xs text-red-600">{{ $message }}</p>@enderror
</div>
<div class="lg:col-span-2">
<label class="block text-xs font-medium uppercase text-slate-500">Staff</label>
<select name="member_id" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
<option value="">Select…</option>
@foreach ($members as $member)
<option value="{{ $member->id }}" @selected(old('member_id') == $member->id)>
{{ $memberLabels[$member->id] ?? $member->user_ref }}
</option>
@endforeach
</select>
@error('member_id')<p class="mt-1 text-xs text-red-600">{{ $message }}</p>@enderror
</div>
<div class="flex items-end">
<button type="submit" class="btn-primary w-full">Assign</button>
</div>
<div class="sm:col-span-2 lg:col-span-5">
<label class="block text-xs font-medium uppercase text-slate-500">Notes</label>
<input type="text" name="notes" value="{{ old('notes') }}" class="mt-1 w-full rounded-lg border-slate-300 text-sm" placeholder="Optional">
</div>
</form>
</div>
@endif
</div>
</x-app-layout>