feat(workstate): UI des délégations en file par agent (Lot B frontend)

Affiche les tickets en attente dans `ProjectWorkStatePanel` à partir du
snapshot de file exposé par le read-model : type de domaine et adaptateur
mock alignés sur le DTO `camelCase`, panneau enrichi (requester, aperçu de
tâche, position FIFO), hook de lecture mis à jour.

Tests verts : workstate.test.tsx + projects.test.tsx (2 fichiers / 17),
`tsc --noEmit` OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-20 18:52:23 +02:00
parent cc7d99a63e
commit c60060494d
5 changed files with 300 additions and 41 deletions

View File

@ -1654,8 +1654,11 @@ export class MockWorkStateGateway implements WorkStateGateway {
private states = new Map<string, ProjectWorkState>();
/** Seeds the read-model returned for a project (deterministic tests/dev). */
_setProjectWorkState(projectId: string, state: ProjectWorkState): void {
this.states.set(projectId, structuredClone(state));
_setProjectWorkState(
projectId: string,
state: ProjectWorkState | LegacyProjectWorkState,
): void {
this.states.set(projectId, normalizeProjectWorkState(state));
}
async getProjectWorkState(projectId: string): Promise<ProjectWorkState> {
@ -1663,6 +1666,23 @@ export class MockWorkStateGateway implements WorkStateGateway {
}
}
type LegacyProjectWorkState = {
agents: Array<Omit<ProjectWorkState["agents"][number], "tickets"> & {
tickets?: ProjectWorkState["agents"][number]["tickets"];
}>;
};
function normalizeProjectWorkState(
state: ProjectWorkState | LegacyProjectWorkState,
): ProjectWorkState {
return {
agents: state.agents.map((agent) => ({
...structuredClone(agent),
tickets: structuredClone(agent.tickets ?? []),
})),
};
}
function mostRestrictive(
project?: PermissionSet["fallback"],
agent?: PermissionSet["fallback"],