Attainly/backend/app/Http/Controllers/ScheduleController.php

198 lines
5.6 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Element\Element;
use App\Exceptions\BadRequestException;
use App\Exceptions\NotFoundException;
use App\Schedule\Schedule;
use App\Schedule\ScheduleAssignment;
use App\Schedule\UseCases\CreateSchedule\CreateSchedule;
use App\Schedule\UseCases\CreateSchedule\CreateScheduleRequest;
use App\Schedule\UseCases\GetSchedule\GetSchedule;
use App\Schedule\UseCases\GetSchedule\GetScheduleRequest;
use App\Schedule\UseCases\ListSchedules\ListSchedules;
use App\Shared\Http\RequestInput;
use App\User\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ScheduleController extends Controller
{
public function __construct(
private CreateSchedule $createSchedule,
private ListSchedules $listSchedules,
private GetSchedule $getSchedule,
) {}
public function store(Request $request): JsonResponse
{
$input = new RequestInput($request);
$user = $this->user($request);
try {
$schedule = $this->createSchedule->execute(
new CreateScheduleRequest(
user: $user,
setId: $input->integer('setId'),
elementKind: $input->string('elementKind'),
startDate: $input->string('startDate'),
targetDate: $input->string('targetDate'),
),
);
} catch (BadRequestException $exception) {
return new JsonResponse(
['error' => $exception->getMessage()],
400,
);
} catch (NotFoundException $exception) {
return new JsonResponse(
['error' => $exception->getMessage()],
404,
);
}
return new JsonResponse(
['schedule' => $this->detailPayload($schedule)],
201,
);
}
public function index(Request $request): JsonResponse
{
$schedules = array_map(
function (Schedule $schedule): array {
return $this->summaryPayload($schedule);
},
$this->listSchedules->execute($this->user($request)),
);
return new JsonResponse(['schedules' => $schedules]);
}
public function show(Request $request, int $scheduleId): JsonResponse
{
try {
$schedule = $this->getSchedule->execute(
new GetScheduleRequest(
scheduleId: $scheduleId,
user: $this->user($request),
),
);
} catch (NotFoundException $exception) {
return new JsonResponse(
['error' => $exception->getMessage()],
404,
);
}
return new JsonResponse([
'schedule' => $this->detailPayload($schedule),
]);
}
/**
* @return array<string, mixed>
*/
private function summaryPayload(Schedule $schedule): array
{
$set = $schedule->getSet();
return [
'id' => $schedule->getId(),
'set' => [
'id' => $set->getId(),
'name' => $set->getName(),
],
'elementKind' => $schedule->getElementKind(),
'startDate' => $schedule->getStartDate()->format('Y-m-d'),
'targetDate' => $schedule->getTargetDate()->format('Y-m-d'),
'assignmentCount' => count($schedule->getAssignments()),
];
}
/**
* @return array<string, mixed>
*/
private function detailPayload(Schedule $schedule): array
{
$payload = $this->summaryPayload($schedule);
$payload['days'] = $this->dayPayloads($schedule);
return $payload;
}
/**
* @return list<array{date: string, assignments: list<mixed>}>
*/
private function dayPayloads(Schedule $schedule): array
{
$assignmentsByDate = [];
foreach ($schedule->getAssignments() as $assignment) {
$date = $assignment->getScheduledDate()->format('Y-m-d');
$assignmentsByDate[$date][] = $this->assignmentPayload(
$assignment,
);
}
$days = [];
$date = $schedule->getStartDate();
while ($date <= $schedule->getTargetDate()) {
$formattedDate = $date->format('Y-m-d');
$days[] = [
'date' => $formattedDate,
'assignments' => $assignmentsByDate[$formattedDate] ?? [],
];
$date = $date->modify('+1 day');
}
return $days;
}
/**
* @return array{element: array{
* id: int,
* name: string,
* kind: string,
* path: list<string>
* }}
*/
private function assignmentPayload(
ScheduleAssignment $assignment,
): array {
$element = $assignment->getElement();
return [
'element' => [
'id' => $element->getId(),
'name' => $element->getName(),
'kind' => $element->getKind(),
'path' => $this->elementPath($element),
],
];
}
/**
* @return list<string>
*/
private function elementPath(Element $element): array
{
$path = [];
$currentElement = $element;
while ($currentElement !== null) {
array_unshift($path, $currentElement->getName());
$currentElement = $currentElement->getParentElement();
}
return $path;
}
private function user(Request $request): User
{
/** @var User $user */
$user = $request->attributes->get('user');
return $user;
}
}