schedule explicit set levels

This commit is contained in:
Yisroel Baum 2026-08-11 22:57:15 +03:00
parent a64df64b76
commit 3cf1aff6a9
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
10 changed files with 156 additions and 38 deletions

View file

@ -34,7 +34,7 @@ class ScheduleController extends Controller
new CreateScheduleRequest(
user: $user,
setId: $input->integer('setId'),
elementKind: $input->string('elementKind'),
levelId: $input->integer('levelId'),
startDate: $input->string('startDate'),
targetDate: $input->string('targetDate'),
),

View file

@ -7,6 +7,7 @@ use App\Set\Set;
use App\Set\UseCases\GetSetLayout\ElementLayoutNode;
use App\Set\UseCases\GetSetLayout\GetSetLayout;
use App\Set\UseCases\GetSetLayout\GetSetLayoutRequest;
use App\Set\UseCases\GetSetLayout\SetLayoutLevel;
use App\Set\UseCases\ListSets\ListSets;
use Illuminate\Http\JsonResponse;
@ -49,6 +50,19 @@ class SetController extends Controller
'id' => $set->getId(),
'name' => $set->getName(),
],
'levels' => array_map(
function (SetLayoutLevel $layoutLevel): array {
$level = $layoutLevel->getLevel();
return [
'id' => $level->getId(),
'kind' => $level->getKind(),
'depth' => $level->getDepth(),
'elementCount' => $layoutLevel->getElementCount(),
];
},
$layout->getLevels(),
),
'elements' => array_map(
function (ElementLayoutNode $node): array {
return $this->elementPayload($node);
@ -63,6 +77,7 @@ class SetController extends Controller
* id: int,
* name: string,
* kind: string,
* levelId: int,
* children: list<mixed>
* }
*/
@ -74,6 +89,7 @@ class SetController extends Controller
'id' => $element->getId(),
'name' => $element->getName(),
'kind' => $element->getKind(),
'levelId' => $element->getLevel()->getId(),
'children' => array_map(
function (ElementLayoutNode $childNode): array {
return $this->elementPayload($childNode);

View file

@ -11,6 +11,7 @@ use App\Schedule\CreateScheduleDto;
use App\Schedule\Schedule;
use App\Schedule\ScheduleRepository;
use App\Set\Set;
use App\Set\SetLevelRepository;
use App\Set\SetRepository;
use DateTimeImmutable;
use DateTimeZone;
@ -19,6 +20,7 @@ class CreateSchedule
{
public function __construct(
private SetRepository $setRepository,
private SetLevelRepository $setLevelRepository,
private ElementRepository $elementRepository,
private ScheduleRepository $scheduleRepository,
) {}
@ -38,8 +40,18 @@ class CreateSchedule
throw new NotFoundException('set not found');
}
if ($request->elementKind === null || $request->elementKind === '') {
throw new BadRequestException('elementKind is required');
if ($request->levelId === null || $request->levelId < 1) {
throw new BadRequestException('levelId is required');
}
$level = $this->setLevelRepository->find($request->levelId);
if (
$level === null
|| $level->getSet()->getId() !== $set->getId()
) {
throw new BadRequestException(
'level is not available for set',
);
}
$startDate = $this->parseDate($request->startDate, 'startDate');
@ -52,14 +64,12 @@ class CreateSchedule
$elements = array_values(array_filter(
$this->orderedElements($set),
function (Element $element) use ($request): bool {
return $element->getKind() === $request->elementKind;
function (Element $element) use ($level): bool {
return $element->getLevel()->getId() === $level->getId();
},
));
if ($elements === []) {
throw new BadRequestException(
'elementKind is not available for set',
);
throw new BadRequestException('level has no elements');
}
$assignments = $this->assignments(
@ -71,7 +81,7 @@ class CreateSchedule
return $this->scheduleRepository->create(new CreateScheduleDto(
user: $request->user,
setName: $set->getName(),
elementKind: $request->elementKind,
elementKind: $level->getKind(),
startDate: $startDate,
targetDate: $targetDate,
assignments: $assignments,

View file

@ -9,7 +9,7 @@ final readonly class CreateScheduleRequest
public function __construct(
public User $user,
public ?int $setId,
public ?string $elementKind,
public ?int $levelId,
public ?string $startDate,
public ?string $targetDate,
) {}

View file

@ -6,11 +6,13 @@ use App\Element\Element;
use App\Element\ElementRepository;
use App\Exceptions\NotFoundException;
use App\Set\SetRepository;
use App\Set\SetLevelRepository;
class GetSetLayout
{
public function __construct(
private SetRepository $setRepository,
private SetLevelRepository $setLevelRepository,
private ElementRepository $elementRepository,
) {}
@ -24,10 +26,15 @@ class GetSetLayout
throw new NotFoundException('set not found');
}
$elements = $this->elementRepository->findBySet($set);
$elementsByParentId = [];
foreach ($this->elementRepository->findBySet($set) as $element) {
$elementCountsByLevelId = [];
foreach ($elements as $element) {
$parentId = $element->getParentElement()?->getId() ?? 0;
$elementsByParentId[$parentId][] = $element;
$levelId = $element->getLevel()->getId();
$elementCountsByLevelId[$levelId]
= ($elementCountsByLevelId[$levelId] ?? 0) + 1;
}
foreach ($elementsByParentId as &$siblings) {
@ -46,8 +53,17 @@ class GetSetLayout
}
unset($siblings);
$layoutLevels = [];
foreach ($this->setLevelRepository->findBySet($set) as $level) {
$layoutLevels[] = new SetLayoutLevel(
level: $level,
elementCount: $elementCountsByLevelId[$level->getId()] ?? 0,
);
}
return new SetLayout(
set: $set,
levels: $layoutLevels,
elements: $this->buildNodes(0, $elementsByParentId),
);
}

View file

@ -7,10 +7,12 @@ use App\Set\Set;
final readonly class SetLayout
{
/**
* @param list<SetLayoutLevel> $levels
* @param list<ElementLayoutNode> $elements
*/
public function __construct(
private Set $set,
private array $levels,
private array $elements,
) {}
@ -19,6 +21,14 @@ final readonly class SetLayout
return $this->set;
}
/**
* @return list<SetLayoutLevel>
*/
public function getLevels(): array
{
return $this->levels;
}
/**
* @return list<ElementLayoutNode>
*/

View file

@ -0,0 +1,23 @@
<?php
namespace App\Set\UseCases\GetSetLayout;
use App\Set\SetLevel;
final readonly class SetLayoutLevel
{
public function __construct(
private SetLevel $level,
private int $elementCount,
) {}
public function getLevel(): SetLevel
{
return $this->level;
}
public function getElementCount(): int
{
return $this->elementCount;
}
}