feat: Permettre à l'élève de rendre un devoir avec réponse texte et pièces jointes
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'élève peut désormais répondre à un devoir via un éditeur WYSIWYG,
joindre des fichiers (PDF, JPEG, PNG, DOCX), sauvegarder un brouillon
et soumettre définitivement son rendu. Le système détecte automatiquement
les soumissions en retard par rapport à la date d'échéance.

Côté enseignant, une page dédiée affiche la liste complète des élèves
avec leur statut (soumis, en retard, brouillon, non rendu), le détail
de chaque rendu avec ses pièces jointes téléchargeables, et les
statistiques de rendus par classe.
This commit is contained in:
2026-03-25 19:38:25 +01:00
parent ab835e5c3d
commit df25a8cbb0
48 changed files with 4519 additions and 12 deletions

View File

@@ -5,12 +5,14 @@ declare(strict_types=1);
namespace App\Scolarite\Application\Query\GetStudentHomework;
use App\Administration\Domain\Model\SchoolClass\ClassId;
use App\Administration\Domain\Model\User\UserId;
use App\Scolarite\Application\Port\ScheduleDisplayReader;
use App\Scolarite\Application\Port\StudentClassReader;
use App\Scolarite\Domain\Model\Homework\Homework;
use App\Scolarite\Domain\Model\Homework\HomeworkId;
use App\Scolarite\Domain\Repository\HomeworkAttachmentRepository;
use App\Scolarite\Domain\Repository\HomeworkRepository;
use App\Scolarite\Domain\Repository\HomeworkSubmissionRepository;
use App\Shared\Domain\Tenant\TenantId;
use function array_filter;
@@ -29,6 +31,7 @@ final readonly class GetStudentHomeworkHandler
private StudentClassReader $studentClassReader,
private HomeworkRepository $homeworkRepository,
private HomeworkAttachmentRepository $attachmentRepository,
private HomeworkSubmissionRepository $submissionRepository,
private ScheduleDisplayReader $displayReader,
) {
}
@@ -56,7 +59,7 @@ final readonly class GetStudentHomeworkHandler
usort($homeworks, static fn (Homework $a, Homework $b): int => $a->dueDate <=> $b->dueDate);
return $this->enrichHomeworks($homeworks, $query->tenantId);
return $this->enrichHomeworks($homeworks, $query->studentId, $query->tenantId);
}
/**
@@ -64,7 +67,7 @@ final readonly class GetStudentHomeworkHandler
*
* @return array<StudentHomeworkDto>
*/
private function enrichHomeworks(array $homeworks, string $tenantId): array
private function enrichHomeworks(array $homeworks, string $studentId, string $tenantId): array
{
if ($homeworks === []) {
return [];
@@ -83,6 +86,14 @@ final readonly class GetStudentHomeworkHandler
$homeworkIds = array_map(static fn (Homework $h): HomeworkId => $h->id, $homeworks);
$attachmentMap = $this->attachmentRepository->hasAttachments(...$homeworkIds);
$studentUserId = UserId::fromString($studentId);
$tenantIdObj = TenantId::fromString($tenantId);
$submissionStatusMap = $this->submissionRepository->findStatusesByStudent(
$studentUserId,
$tenantIdObj,
...$homeworkIds,
);
return array_map(
static fn (Homework $h): StudentHomeworkDto => StudentHomeworkDto::fromDomain(
$h,
@@ -90,6 +101,7 @@ final readonly class GetStudentHomeworkHandler
$subjects[(string) $h->subjectId]['color'] ?? null,
$teacherNames[(string) $h->teacherId] ?? '',
$attachmentMap[(string) $h->id] ?? false,
$submissionStatusMap[(string) $h->id] ?? null,
),
$homeworks,
);

View File

@@ -20,6 +20,7 @@ final readonly class StudentHomeworkDto
public string $dueDate,
public string $createdAt,
public bool $hasAttachments,
public ?string $submissionStatus = null,
) {
}
@@ -29,6 +30,7 @@ final readonly class StudentHomeworkDto
?string $subjectColor,
string $teacherName,
bool $hasAttachments,
?string $submissionStatus = null,
): self {
return new self(
id: (string) $homework->id,
@@ -42,6 +44,7 @@ final readonly class StudentHomeworkDto
dueDate: $homework->dueDate->format('Y-m-d'),
createdAt: $homework->createdAt->format('Y-m-d\TH:i:sP'),
hasAttachments: $hasAttachments,
submissionStatus: $submissionStatus,
);
}
}