feat: smart assign person dialog with conflict details and assignable-persons endpoint
Add GET /events/{event}/shifts/{shift}/assignable-persons endpoint that
returns approved persons with availability status, conflict details, and
already-assigned flags. Improve ShiftAssignmentService conflict errors to
include section name, time slot, and time range. Replace both assign
dialogs with a new AssignPersonDialog featuring search, crowd type
filtering, availability toggle, and inline conflict warnings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,7 @@ final class ShiftAssignmentService
|
||||
$this->validateShiftIsOpen($shift);
|
||||
$this->validatePersonApproved($person);
|
||||
$this->validateClaimCapacity($shift);
|
||||
$this->validateNoConflict($shift, $person);
|
||||
$this->validateNoConflict($shift, $person, isClaim: true);
|
||||
|
||||
$autoApprove = $shift->festivalSection->crew_auto_accepts;
|
||||
$status = $autoApprove
|
||||
@@ -323,20 +323,30 @@ final class ShiftAssignmentService
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateNoConflict(Shift $shift, Person $person): void
|
||||
private function validateNoConflict(Shift $shift, Person $person, bool $isClaim = false): void
|
||||
{
|
||||
if ($shift->allow_overlap) {
|
||||
return;
|
||||
}
|
||||
|
||||
$conflict = ShiftAssignment::where('person_id', $person->id)
|
||||
$existingAssignment = ShiftAssignment::where('person_id', $person->id)
|
||||
->where('time_slot_id', $shift->time_slot_id)
|
||||
->active()
|
||||
->exists();
|
||||
->with(['shift.festivalSection', 'shift.timeSlot'])
|
||||
->first();
|
||||
|
||||
if ($existingAssignment) {
|
||||
$section = $existingAssignment->shift->festivalSection->name;
|
||||
$timeSlot = $existingAssignment->shift->timeSlot->name;
|
||||
$time = $existingAssignment->shift->timeSlot->start_time
|
||||
. '–' . $existingAssignment->shift->timeSlot->end_time;
|
||||
|
||||
$message = $isClaim
|
||||
? "Je bent al ingepland bij \"{$section}\" voor {$timeSlot} ({$time})."
|
||||
: "Deze persoon is al ingepland bij \"{$section}\" voor {$timeSlot} ({$time}).";
|
||||
|
||||
if ($conflict) {
|
||||
throw ValidationException::withMessages([
|
||||
'person_id' => ['Deze persoon is al ingepland voor dit tijdslot.'],
|
||||
'person_id' => [$message],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user