feat: Afficher la couleur des matières dans l'emploi du temps élève et parent
Some checks failed
CI / Backend Tests (push) Has been cancelled
CI / Frontend Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Naming Conventions (push) Has been cancelled
CI / Build Check (push) Has been cancelled

L'admin pouvait attribuer une couleur à chaque matière, mais cette
couleur n'était utilisée que dans la vue admin de l'emploi du temps.
Les APIs élève et parent ne renvoyaient pas cette information, ce qui
donnait un affichage générique (gris/bleu) pour tous les créneaux.

L'API renvoie désormais subjectColor dans chaque créneau, et les vues
jour/semaine/widget/détails affichent la bordure colorée correspondante.
Le marqueur "Prochain cours" conserve sa priorité visuelle via une
surcharge CSS variable.
This commit is contained in:
2026-03-09 11:20:50 +01:00
parent bda63bd98c
commit 81e97c4f3b
27 changed files with 188 additions and 70 deletions

View File

@@ -15,9 +15,9 @@ interface ScheduleDisplayReader
/**
* @param string ...$subjectIds Identifiants des matières
*
* @return array<string, string> Map subjectId => nom de la matière
* @return array<string, array{name: string, color: string|null}> Map subjectId => {name, color}
*/
public function subjectNames(string $tenantId, string ...$subjectIds): array;
public function subjectDisplay(string $tenantId, string ...$subjectIds): array;
/**
* @param string ...$teacherIds Identifiants des enseignants

View File

@@ -111,13 +111,14 @@ final readonly class GetChildrenScheduleHandler
array_map(static fn (ResolvedScheduleSlot $s): string => (string) $s->teacherId, $slots),
));
$subjectNames = $this->displayReader->subjectNames($tenantId, ...$subjectIds);
$subjects = $this->displayReader->subjectDisplay($tenantId, ...$subjectIds);
$teacherNames = $this->displayReader->teacherNames($tenantId, ...$teacherIds);
return array_map(
static fn (ResolvedScheduleSlot $s): StudentScheduleSlotDto => StudentScheduleSlotDto::fromResolved(
$s,
$subjectNames[(string) $s->subjectId] ?? '',
$subjects[(string) $s->subjectId]['name'] ?? '',
$subjects[(string) $s->subjectId]['color'] ?? null,
$teacherNames[(string) $s->teacherId] ?? '',
),
$slots,

View File

@@ -74,13 +74,14 @@ final readonly class GetStudentScheduleHandler
array_map(static fn (ResolvedScheduleSlot $s): string => (string) $s->teacherId, $slots),
));
$subjectNames = $this->displayReader->subjectNames($tenantId, ...$subjectIds);
$subjects = $this->displayReader->subjectDisplay($tenantId, ...$subjectIds);
$teacherNames = $this->displayReader->teacherNames($tenantId, ...$teacherIds);
return array_map(
static fn (ResolvedScheduleSlot $s): StudentScheduleSlotDto => StudentScheduleSlotDto::fromResolved(
$s,
$subjectNames[(string) $s->subjectId] ?? '',
$subjects[(string) $s->subjectId]['name'] ?? '',
$subjects[(string) $s->subjectId]['color'] ?? null,
$teacherNames[(string) $s->teacherId] ?? '',
),
$slots,

View File

@@ -16,6 +16,7 @@ final readonly class StudentScheduleSlotDto
public string $endTime,
public string $subjectId,
public string $subjectName,
public ?string $subjectColor,
public string $teacherId,
public string $teacherName,
public ?string $room,
@@ -27,6 +28,7 @@ final readonly class StudentScheduleSlotDto
public static function fromResolved(
ResolvedScheduleSlot $slot,
string $subjectName,
?string $subjectColor,
string $teacherName,
): self {
return new self(
@@ -37,6 +39,7 @@ final readonly class StudentScheduleSlotDto
endTime: $slot->timeSlot->endTime,
subjectId: (string) $slot->subjectId,
subjectName: $subjectName,
subjectColor: $subjectColor,
teacherId: (string) $slot->teacherId,
teacherName: $teacherName,
room: $slot->room,

View File

@@ -29,9 +29,6 @@ use function usort;
/**
* Endpoints de consultation de l'emploi du temps des enfants pour le parent connecté.
*
* @see Story 4.4 - Consultation EDT par le Parent
* @see FR30 - Consulter emploi du temps enfant (parent)
*/
#[IsGranted(ScheduleSlotVoter::VIEW)]
final readonly class ParentScheduleController
@@ -190,6 +187,7 @@ final readonly class ParentScheduleController
'endTime' => $slot->endTime,
'subjectId' => $slot->subjectId,
'subjectName' => $slot->subjectName,
'subjectColor' => $slot->subjectColor,
'teacherId' => $slot->teacherId,
'teacherName' => $slot->teacherName,
'room' => $slot->room,

View File

@@ -29,9 +29,6 @@ use function usort;
/**
* Endpoints de consultation de l'emploi du temps pour l'élève connecté.
*
* @see Story 4.3 - Consultation EDT par l'Élève
* @see FR29 - Consulter emploi du temps (élève)
*/
#[IsGranted(ScheduleSlotVoter::VIEW)]
final readonly class StudentScheduleController
@@ -178,6 +175,7 @@ final readonly class StudentScheduleController
'endTime' => $slot->endTime,
'subjectId' => $slot->subjectId,
'subjectName' => $slot->subjectName,
'subjectColor' => $slot->subjectColor,
'teacherId' => $slot->teacherId,
'teacherName' => $slot->teacherName,
'room' => $slot->room,

View File

@@ -20,29 +20,31 @@ final readonly class DoctrineScheduleDisplayReader implements ScheduleDisplayRea
}
#[Override]
public function subjectNames(string $tenantId, string ...$subjectIds): array
public function subjectDisplay(string $tenantId, string ...$subjectIds): array
{
if ($subjectIds === []) {
return [];
}
$rows = $this->connection->fetchAllAssociative(
'SELECT id, name FROM subjects WHERE id IN (:ids) AND tenant_id = :tenantId',
'SELECT id, name, color FROM subjects WHERE id IN (:ids) AND tenant_id = :tenantId',
['ids' => $subjectIds, 'tenantId' => $tenantId],
['ids' => ArrayParameterType::STRING],
);
$names = [];
$display = [];
foreach ($rows as $row) {
/** @var string $id */
$id = $row['id'];
/** @var string $name */
$name = $row['name'];
$names[$id] = $name;
/** @var string|null $color */
$color = $row['color'];
$display[$id] = ['name' => $name, 'color' => $color];
}
return $names;
return $display;
}
#[Override]

View File

@@ -265,9 +265,14 @@ final class GetChildrenScheduleHandlerTest extends TestCase
) {
}
public function subjectNames(string $tenantId, string ...$subjectIds): array
public function subjectDisplay(string $tenantId, string ...$subjectIds): array
{
return $this->subjects;
$display = [];
foreach ($this->subjects as $id => $name) {
$display[$id] = ['name' => $name, 'color' => null];
}
return $display;
}
public function teacherNames(string $tenantId, string ...$teacherIds): array

View File

@@ -210,9 +210,14 @@ final class GetStudentScheduleHandlerTest extends TestCase
) {
}
public function subjectNames(string $tenantId, string ...$subjectIds): array
public function subjectDisplay(string $tenantId, string ...$subjectIds): array
{
return $this->subjects;
$display = [];
foreach ($this->subjects as $id => $name) {
$display[$id] = ['name' => $name, 'color' => null];
}
return $display;
}
public function teacherNames(string $tenantId, string ...$teacherIds): array