Aller au contenu

Story CP-015 : Améliorations UI de la Gestion des Utilisateurs

Module : control-plane Slice : Slice 3 from architecture (split from CP-003) Brand context : [BOTH] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priority : 3 Depends on : CP-003 Estimated complexity : S


Objectif

Améliorer la page de Gestion des Utilisateurs avec l'affichage du statut d'invitation (actif/expiré avec renvoi) et l'UX de détection multi-tenant pendant le flux d'invitation. Ce sont des améliorations axées frontend qui s'appuient sur la liste d'utilisateurs et le flux d'invitation établis dans CP-003.


Périmètre Backend

Entités & Records

Aucune nouvelle entité. Cette story consomme les entités User, UserTenantMembership et autres entités connexes de CP-003.

Couche Service

UserService.java (ajouts) : - resendInvitation(UUID userId, UUID tenantId) → void — Renvoie l'email d'invitation pour les invitations expirées : 1. Vérifier que l'utilisateur a le statut=INVITED et une adhésion dans le tenant 2. Appeler KeycloakAdminService.sendPasswordSetupEmail(email) 3. Publier l'événement UserInvitationResent - checkExistingUser(String email) → Optional<UserExistsResponse> — Retourne les informations d'existence d'un utilisateur pour la détection multi-tenant : - Si l'email existe sur la plateforme : retourne {exists: true, firstName, lastName} (pas de détails tenant — confidentialité) - Sinon : retourne {exists: false}

DTOs (ajouts) :

public record UserExistsResponse(boolean exists, @Nullable String firstName, @Nullable String lastName) {}

Endpoints API

Méthode Chemin Corps de requête Réponse Auth
POST /api/v1/users/{id}/resend-invite 204 ROLE_DG, ROLE_RH_MANAGER
GET /api/v1/users/check-email?email= UserExistsResponse ROLE_DG, ROLE_RH_MANAGER

Règles de validation

  • Renvoi d'invitation : l'utilisateur doit avoir le statut=INVITED et être membre du tenant courant
  • Vérification email : format email valide, max 254 caractères

Périmètre Frontend

Composants

Utilise UserManagementPage.tsx et InviteUserSheet.tsx de CP-003. Cette story ajoute des comportements à ces composants.

Améliorations UI

Liste d'utilisateurs — affichage du statut d'invitation (AC-024) :

Chaque carte/ligne d'utilisateur affiche le statut :

Statut Utilisateur Visuel (Carte Mobile) Visuel (Ligne Bureau)
ACTIVE Point vert + "Actif" Point vert + "Actif"
INVITED (valide) Point bleu + "Invitation en cours" Point bleu + "Invitation en cours"
INVITED (expiré) Point orange + lien "Expiré — Renvoyer →" Point orange + lien "Expiré — Renvoyer →"
DISABLED Point gris + "Désactivé" Point gris + "Désactivé"
  • Expiration de l'invitation : Les liens d'invitation expirent après 72 heures (configurable). L'expiration est déterminée en comparant created_date + 72h avec l'heure courante.
  • Action de renvoi : Appuyer sur "Renvoyer →" appelle POST /api/v1/users/{id}/resend-invite et affiche un toast : "Invitation renvoyée à {email}"

Flux d'invitation — détection multi-tenant (AC-025) :

Dans InviteUserSheet.tsx, après que l'utilisateur saisit un email et que le champ perd le focus (onBlur) : 1. Appeler GET /api/v1/users/check-email?email={email} 2. Si exists: true, afficher une bannière d'information sous le champ email : - "Cet utilisateur existe déjà sur la plateforme. Il sera ajouté à votre entreprise avec le rôle sélectionné." - Style : fond bleu info, icône info, texte en français 3. Si exists: false, aucune bannière affichée (flux normal)

États UI

État Comportement Texte en Français
Chargement renvoi Spinner sur le lien "Renvoyer"
Succès renvoi Toast vert "Invitation renvoyée à {email}"
Erreur renvoi Toast rouge "Une erreur est survenue. Veuillez réessayer."
Multi-tenant détecté Bannière info sous le champ email "Cet utilisateur existe déjà sur la plateforme. Il sera ajouté à votre entreprise avec le rôle sélectionné."

Comportement responsive

Mêmes points de rupture que la page Gestion des Utilisateurs de CP-003. Les badges de statut et les liens de renvoi s'adaptent à la disposition en carte (mobile) ou en ligne de tableau (bureau).


Critères d'acceptation

AC-024: User list shows invite status
Given I am on the User Management page with 3 users (2 active, 1 invited with expired link)
When the page loads
Then I see 2 users with green "Actif" dots
And 1 user with "Expiré — Renvoyer →" link

AC-025: Invite flow multi-tenant detection
Given I tap "+" to invite "[email protected]" who already exists on the platform
When I enter the email and the field loses focus
Then I see the info message: "Cet utilisateur existe déjà sur la plateforme. Il sera ajouté à votre entreprise avec le rôle sélectionné."

Règles OHADA & Réglementaires

  • Loi 2013-450 (Art. 36) : L'endpoint check-email retourne des informations minimales (exists + prénom/nom uniquement, pas de détails tenant) pour éviter de fuiter des informations inter-tenant.

Standards & Conventions

  • docs/standards/react-typescript-guidelines.md — §Composants liste, §Pattern toast, §Bannière info
  • docs/standards/api-guidelines.md — §Enveloppe standard

Exigences de test

Tests unitaires

  • UserService.resendInvitation : envoie l'email pour une invitation expirée
  • UserService.resendInvitation : rejette si l'utilisateur n'est pas INVITED
  • UserService.checkExistingUser : retourne exists=true avec le nom pour un utilisateur existant
  • UserService.checkExistingUser : retourne exists=false pour un email inconnu

Tests d'intégration

  • POST /api/v1/users/{id}/resend-invite — succès pour une invitation expirée
  • POST /api/v1/users/{id}/resend-invite — 400 pour un utilisateur non-INVITED
  • GET /api/v1/users/check-email — utilisateur existant retourne des informations minimales
  • GET /api/v1/users/check-email — email inconnu retourne exists=false

Ce que le QA validera

  • La liste d'utilisateurs affiche les points de statut et labels corrects pour chaque état
  • L'invitation expirée affiche le lien "Expiré — Renvoyer →"
  • Le renvoi d'invitation envoie l'email et affiche le toast de succès
  • Le message de détection multi-tenant apparaît après la saisie d'un email existant
  • Aucune fuite d'informations inter-tenant dans la réponse check-email

Hors périmètre

  • UI de désactivation/suppression d'utilisateur — V2
  • UI de configuration d'expiration d'invitation — V2 (72h par défaut codé en dur)
  • UI de changement de tenant — CP-011

Définition de Done

  • [ ] La liste d'utilisateurs affiche le statut correct pour ACTIVE, INVITED (valide), INVITED (expiré), DISABLED
  • [ ] Le flux de renvoi d'invitation fonctionne de bout en bout
  • [ ] La bannière de détection multi-tenant s'affiche correctement
  • [ ] Tous les critères d'acceptation passent manuellement
  • [ ] Tests unitaires écrits et passants
  • [ ] Tests d'intégration écrits et passants
  • [ ] Les micro-textes français correspondent exactement à la spec design
  • [ ] Tous les états UI s'affichent correctement à 360px, 768px, 1024px
  • [ ] Pas de any TypeScript — tous les types explicites
  • [ ] Les réponses API respectent le format d'enveloppe standard