Aller au contenu

Design: Control Plane

Brand: Papillon HR Suite (tenant-facing) + Admin Console (ALTARYS operators)

Date: 26/02/2026

Version: 1.0

Author: DESIGNER (Claude — Senior UX/UI Designer)

PRD Source: docs/prd/control-plane-prd.md v1.0


For the DEVELOPER: This document is your single source of truth for all Control Plane screens. It references design tokens from docs/design/host-shell-design.md §2 — reuse them, never redefine. The Admin Console is a separate React application (see docs/_kb/seperate_admin-app_reasons.md). If something is ambiguous, the design is wrong — flag it.


Table of Contents

  1. Scope & Screens Index
  2. User Flow Diagrams
  3. Tenant Self-Onboarding (Channel A)
  4. Email Verification & Post-Verification Routing
  5. Payment Flow
  6. Company Settings
  7. Organization & Master Data
  8. Employee Management (Baseline)
  9. User Management & Invitations
  10. Module Gating & Upsell
  11. Billing & Subscription Management
  12. Audit Trail Viewer
  13. Multi-Tenant Switcher
  14. Tenant Status Banners
  15. Admin Console (Separate App)
  16. Offline Behavior Specifications
  17. Responsive Behavior Summary
  18. French Micro-copy Document
  19. New Component Specifications
  20. Brand Compliance Checklist

1. Scope & Screens Index

The Control Plane touches every surface of the application but most of its UI is administrative setup — screens visited once or occasionally, not daily. The design prioritizes clarity over density.

Screen Map — Papillon HR Suite (Tenant-Facing)

Screen Location in Nav Frequency Offline? Section
Self-Registration (Channel A) Public — papillon.ci/inscription One-time No §3
Email Verification Public — email link One-time No §4
Module Selection Registration flow step 2 One-time No §3.3
Payment Registration flow step 3 One-time (then monthly) No §5
Company Settings Admin → Paramètres → Entreprise Rare Partial (read) §6
Org Structure Admin → Paramètres → Structure Monthly Yes (read) §7
Position Catalog Admin → Paramètres → Postes Monthly Yes (read) §7.4
Employee List RH → Employés Daily Yes (full) §8
Employee Form (Create/Edit) RH → Employés → Nouveau Weekly Yes (create) §8.3
User Management Admin → Utilisateurs Monthly No §9
Invite User Admin → Utilisateurs → Inviter Monthly No §9
Module Catalog (Upsell) Nav → locked module click Occasional No §10
Subscription Management Admin → Abonnement Monthly No §11
Invoice History Admin → Abonnement → Factures Monthly No §11
Audit Trail Admin → Audit Rare No §12
Tenant Switcher Header → "Mes entreprises" Per session No §13

Screen Map — Admin Console (ALTARYS Operators)

Screen Frequency Section
Tenant List (Dashboard) Daily §15.2
Tenant Detail Daily §15.3
Pending Payments Daily §15.4
Module Override Weekly §15.5
Country Config Editor Rare §15.6
Platform Metrics Weekly §15.7

2. User Flow Diagrams

2.1 Tenant Self-Onboarding (Channel A)

flowchart TD
    A[Visiteur arrive sur papillon.ci] --> B[Clique 'Inscription']
    B --> C[Formulaire d'inscription]
    C --> D{Validation côté client}
    D -->|Erreurs| C
    D -->|OK| E{hCaptcha}
    E -->|Échec| C
    E -->|OK| F{Vérification doublons}
    F -->|Email/Tél existant| G[Erreur: compte existe déjà]
    F -->|Nom similaire| H[Flag ops + continuer]
    F -->|OK| I[Enregistrement tenant<br>Status: PENDING_VERIFICATION]
    H --> I
    I --> J[Email de vérification envoyé]
    J --> K{L'utilisateur clique le lien}
    K -->|Lien expiré| L[Page: lien expiré<br>+ bouton renvoyer]
    L --> J
    K -->|Lien valide| M{A choisi l'essai gratuit ?}
    M -->|Oui| N[Pipeline de provisionnement]
    M -->|Non| O[Page: Sélection modules<br>+ choix de paiement]
    N --> P[Status: TRIAL<br>Redirect → Dashboard]
    O --> Q{Méthode de paiement}
    Q -->|Mobile Money| R[Widget paiement]
    Q -->|Virement bancaire| S[Status: ACTIVE_PAYMENT_PENDING<br>Instructions virement affichées]
    R -->|Succès| T{RCCM + NIF fournis ?}
    R -->|Échec| U[Status: PAYMENT_REQUIRED<br>Modules en lecture seule]
    T -->|Oui| V[Status: ACTIVE]
    T -->|Non| W[Status: ACTIVE_INCOMPLETE<br>Bandeau persistant]
    V --> X[Redirect → Dashboard 🎉]
    W --> X
    U --> Y[Redirect → Dashboard<br>+ bandeau paiement]
    S --> Z[Redirect → Dashboard<br>+ bandeau virement]

    style P fill:#DCFCE7
    style V fill:#DCFCE7
    style W fill:#FEF9C3
    style U fill:#FEE2E2
    style X fill:#DCFCE7

2.2 Channel B — CRM Salesperson Onboarding

flowchart TD
    A[Commercial dans CRM:<br>'Convertir en client'] --> B[Tenant créé<br>Status: PENDING]
    B --> C[Email #1: lien création<br>mot de passe]
    B --> D[Email #2: lien paiement<br>+ résumé modules]
    C --> E{Admin crée son mot de passe}
    E -->|Lien expiré| F[Contacter commercial]
    E -->|Mot de passe créé| G{Paiement effectué ?}
    G -->|Mobile Money OK| H[Status: ACTIVE]
    G -->|Virement choisi| I[Status: ACTIVE_PAYMENT_PENDING]
    G -->|Pas encore| J[Status: PAYMENT_REQUIRED]
    D --> K[Admin clique opt-out ?]
    K -->|Oui| L[Tenant supprimé<br>Page de confirmation]

    style H fill:#DCFCE7
    style I fill:#FEF9C3
    style J fill:#FEE2E2
    style L fill:#E8E0D4

2.3 Tenant Lifecycle State Machine

stateDiagram-v2
    [*] --> PENDING_VERIFICATION : Channel A
    [*] --> PENDING : Channel B (CRM)

    PENDING_VERIFICATION --> TRIAL : Email vérifié + essai
    PENDING_VERIFICATION --> PAYMENT_REQUIRED : Email vérifié, pas d'essai

    PENDING --> PAYMENT_REQUIRED : Mot de passe créé
    PENDING --> ACTIVE_PAYMENT_PENDING : MdP + virement
    PENDING --> ACTIVE : MdP + paiement API

    TRIAL --> ACTIVE : Paiement reçu
    TRIAL --> ACTIVE_INCOMPLETE : Paiement reçu, info légale manquante
    TRIAL --> ACTIVE_PAYMENT_PENDING : Virement choisi
    TRIAL --> SUSPENDED : 14 jours expirés

    PAYMENT_REQUIRED --> TRIAL : Essai unique demandé
    PAYMENT_REQUIRED --> ACTIVE : Paiement reçu
    PAYMENT_REQUIRED --> ACTIVE_INCOMPLETE : Paiement, info manquante
    PAYMENT_REQUIRED --> ACTIVE_PAYMENT_PENDING : Virement choisi
    PAYMENT_REQUIRED --> SUSPENDED : 14 jours expirés

    ACTIVE_PAYMENT_PENDING --> ACTIVE : Paiement confirmé
    ACTIVE_PAYMENT_PENDING --> ACTIVE_INCOMPLETE : Confirmé, info manquante
    ACTIVE_PAYMENT_PENDING --> SUSPENDED : 10 jours expirés

    ACTIVE_INCOMPLETE --> ACTIVE : Info légale complétée

    ACTIVE --> SUSPENDED : Abonnement expiré + grâce
    ACTIVE --> SUSPENDED : Suspension manuelle admin

    SUSPENDED --> ACTIVE : Paiement / réactivation
    SUSPENDED --> DELETED : 30 jours sans action

2.4 Employee Creation (Online + Offline)

flowchart TD
    A[Admin/RH clique<br>'Nouvel employé'] --> B[Formulaire employé]
    B --> C{Connectivité ?}

    C -->|En ligne| D[Validation côté client]
    D -->|Erreurs| B
    D -->|OK| E[UUID v7 généré côté client]
    E --> F[POST /api/v1/employees]
    F --> G{Réponse serveur}
    G -->|201 Created| H[Matricule assigné par serveur<br>Toast: 'Employé créé ✓']
    G -->|409 Conflit| I[Doublon email/tél<br>Afficher résolution]
    G -->|Erreur réseau| J[Sauvegarder IndexedDB<br>File de sync]

    C -->|Hors ligne| K[Validation côté client]
    K -->|Erreurs| B
    K -->|OK| L[UUID v7 généré côté client]
    L --> M[Sauvegardé IndexedDB<br>Matricule: 'Numéro en attente']
    M --> N[Toast: 'Employé enregistré<br>hors ligne ●']
    N --> O{Connectivité restaurée}
    O --> F

    style H fill:#DCFCE7
    style N fill:#FEF9C3
    style I fill:#FEE2E2
    style J fill:#FEF9C3

3. Tenant Self-Onboarding (Channel A)

3.1 Registration Page — Step 1: Company Information

URL: papillon.ci/inscription Public: No authentication required No offline support — onboarding requires connectivity

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│           (warm bg #FFFDF7)          │
│                                      │
│           🦋                         │
│      Créez votre compte              │
│      Papillon en 5 minutes           │
│                                      │
│  ┌──────────────────────────────┐    │
│  │                              │    │
│  │  Nom de l'entreprise *       │    │
│  │  ┌──────────────────────┐    │    │
│  │  │                      │    │    │
│  │  └──────────────────────┘    │    │
│  │                              │    │
│  │  Pays                        │    │
│  │  ┌──────────────────────┐    │    │
│  │  │ 🇨🇮 Côte d'Ivoire  ▾ │    │    │  ← Pre-selected, disabled for MVP
│  │  └──────────────────────┘    │    │
│  │                              │    │
│  │  Nombre de salariés *        │    │
│  │  ┌──────────────────────┐    │    │
│  │  │        ▾             │    │    │  ← Dropdown with ranges
│  │  └──────────────────────┘    │    │
│  │                              │    │
│  │  Votre nom complet *         │    │
│  │  ┌──────────────────────┐    │    │
│  │  │                      │    │    │
│  │  └──────────────────────┘    │    │
│  │                              │    │
│  │  Adresse e-mail *            │    │
│  │  ┌──────────────────────┐    │    │
│  │  │                      │    │    │
│  │  └──────────────────────┘    │    │
│  │                              │    │
│  │  Numéro de téléphone *       │    │
│  │  ┌─────┬────────────────┐    │    │
│  │  │+225 │                │    │    │  ← Country code pre-filled
│  │  └─────┴────────────────┘    │    │
│  │                              │    │
│  │  RCCM (optionnel)            │    │
│  │  ┌──────────────────────┐    │    │
│  │  │                      │    │    │
│  │  └──────────────────────┘    │    │
│  │  ℹ Vous pourrez le fournir   │    │
│  │    plus tard                  │    │
│  │                              │    │
│  │  ☐ Démarrer un essai         │    │
│  │    gratuit de 14 jours       │    │  ← Checkbox, unchecked by default
│  │                              │    │
│  │  ┌──────────────────────┐    │    │
│  │  │   Continuer →         │    │    │  ← Primary button → Step 2
│  │  └──────────────────────┘    │    │
│  │                              │    │
│  │  Déjà inscrit ?              │    │
│  │  Se connecter                │    │  ← Link to login
│  │                              │    │
│  └──────────────────────────────┘    │
│                                      │
│      © 2026 ALTARYS ENTERPRISE       │
└──────────────────────────────────────┘

Layout — Desktop (1024px+)

Split layout like the login screen (host-shell-design.md §4.1): - Left panel (50%): Deep teal #0D6B6E with warm geometric SVG illustration, tagline "Simplifiez la gestion de vos RH", trust badges ("Conforme OHADA", "Données sécurisées", "Support réactif") - Right panel (50%): White card surface with the form fields

Field Specifications

Field Type Required Validation Max Length
company_name text input Yes min 2 chars 200
country_code select (disabled MVP) Yes Pre-set: "CI"
employee_count select (dropdown) Yes Ranges: 2-12, 13-29, 30-49, 50-99, 100-199, 200-350
admin_full_name text input Yes min 2 chars 200
admin_email email input Yes email format, unique 254
admin_phone phone input with prefix Yes CI format: 10 digits, unique 10 digits
rccm text input No 50
free_trial checkbox No

Employee Count Dropdown Options: - "2 – 12 salariés" - "13 – 29 salariés" - "30 – 49 salariés" - "50 – 99 salariés" - "100 – 199 salariés" - "200 – 350 salariés"

Why ranges not exact number: Ranges map directly to pricing segments (S1–S6). Users don't need to count exactly — they know their rough size. This avoids analysis paralysis ("Is it 47 or 48?") and prevents gaming (entering a lower number to get a cheaper plan — the system snapshots actual active employees at billing time).

Interaction Specification

State Behavior
Empty All fields empty except country (pre-filled). Button enabled.
Typing Real-time validation: email format check after blur, phone format check as user types (auto-format: XX XX XX XX XX)
Validation error Red border on field + error message below field in --color-error. Field shakes once (150ms).
Duplicate email/phone After submit: "Un compte existe déjà avec ces informations. Essayez de vous connecter." with link to login.
hCaptcha Appears after "Continuer" click, before submission. Invisible reCaptcha first; fallback to challenge if suspicious.
Submitting Button: spinner + "Envoi en cours…" — all fields disabled
Server error Toast: "Une erreur est survenue. Veuillez réessayer." + fields remain filled (never clear on error)
Rate limited Toast: "Trop de tentatives. Veuillez réessayer dans quelques minutes."

3.2 Registration Page — Step 2: Module Selection

After Step 1 validation, user advances to module selection. This is the first time the user sees the product catalog. It must be aspirational — show the breadth of what Papillon offers, make the selection exciting (not administrative).

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ← Retour    Inscription (2/3)       │
├──────────────────────────────────────┤
│                                      │
│  Choisissez vos modules              │
│  Sélectionnez au moins 1 module.     │
│  Vous pourrez en ajouter plus tard.  │
│                                      │
│  ── Disponible maintenant ────────   │
│                                      │
│  ┌──────────────────────────────┐    │
│  │ ☐  📅  Gestion des Absences │    │
│  │       Congés, demandes,     │    │
│  │       approbations          │    │
│  │                12 000 FCFA  │    │  ← Price per segment
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │ ☐  📱  Contrôle Présence    │    │
│  │       Pointage QR Code      │    │
│  │                 5 000 FCFA  │    │
│  └──────────────────────────────┘    │
│                                      │
│  ── Bientôt disponible ──────────   │
│                                      │
│  ┌──────────────────────────────┐    │
│  │ 🔒 💳  Paie                 │    │  ← Locked, greyed
│  │       Juin 2026             │    │
│  └──────────────────────────────┘    │
│  ┌──────────────────────────────┐    │
│  │ 🔒 🧾  Notes de Frais      │    │
│  │       Avril 2026            │    │
│  └──────────────────────────────┘    │
│  ...                                 │
│                                      │
│  ── Votre sélection ─────────────   │  ← Sticky bottom summary
│  ┌──────────────────────────────┐    │
│  │  2 modules · 17 000 FCFA/m  │    │
│  │  Pack Contrôle appliqué     │    │  ← Auto-detected pack
│  │  → 15 000 FCFA/mois (-12%) │    │
│  │                              │    │
│  │  ┌──────────────────────┐    │    │
│  │  │   Continuer →         │    │    │
│  │  └──────────────────────┘    │    │
│  └──────────────────────────────┘    │
└──────────────────────────────────────┘

Module Card Component

Each module card contains: - Checkbox (left): for selection. Touch target 48×48px. - Icon (center-left): Module icon in --color-primary (available) or --color-text-tertiary (locked) - Title: Module name (--font-h4) - Subtitle: One-line description (--font-small, --color-text-secondary) - Price: Monthly price for the user's segment (--font-body-medium, --color-primary) - Lock badge (for unavailable modules): "Bientôt · [date]"

Card states: - Available, unselected: White background, standard border - Available, selected: --color-primary-light background, --color-primary border, amber checkmark - Locked: 60% opacity, no checkbox, lock icon replaces checkbox, "Bientôt" badge

Pack Auto-Detection

When the user's selection matches a pack combination (as defined in docs/specs/tarifs_papillon_hr_suite.md): - The sticky summary shows: "Pack [name] détecté · -XX%" with crossed-out original price - Animation: price slides from original to discounted with a brief sparkle - Pack detection is instant (client-side calculation)

3.3 Registration Page — Step 3: Payment Choice

Shown only if user did NOT select free trial in Step 1. If free trial was selected, Steps 1 + 2 → email verification → TRIAL → Dashboard.

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ← Retour    Inscription (3/3)       │
├──────────────────────────────────────┤
│                                      │
│  Comment souhaitez-vous payer ?      │
│                                      │
│  ── Résumé de votre abonnement ──   │
│  ┌──────────────────────────────┐    │
│  │  Absences + Présence QR      │    │
│  │  Pack Contrôle               │    │
│  │  15 000 FCFA / mois          │    │
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  📱  Paiement Mobile Money   │    │  ← Primary option
│  │       Orange Money, Wave,    │    │
│  │       MTN Money              │    │
│  │                              │    │
│  │  Paiement instantané.       │    │
│  │  Accès immédiat.            │    │
│  │                              │    │
│  │  ┌──────────────────────┐    │    │
│  │  │  Payer 15 000 FCFA    │    │    │  ← Primary button
│  │  └──────────────────────┘    │    │
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  🏦  Virement bancaire       │    │  ← Secondary option
│  │                              │    │
│  │  Délai de traitement :       │    │
│  │  10 jours maximum.          │    │
│  │  Accès complet pendant       │    │
│  │  cette période.             │    │
│  │                              │    │
│  │  ┌──────────────────────┐    │    │
│  │  │  Choisir le virement  │    │    │  ← Secondary button (outlined)
│  │  └──────────────────────┘    │    │
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  🎁  Essai gratuit 14 jours │    │  ← If not yet used
│  │  Testez avant de payer.     │    │
│  │  Démarrer l'essai →         │    │  ← Text link
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

Payment Method Interaction

Mobile Money selected: 1. Button changes to spinner + "Redirection…" 2. Payment provider widget opens (in-app WebView or redirect) 3. On success → webhook confirms → tenant provisioned → redirect to Dashboard 4. On failure → return to payment page with toast: "Le paiement n'a pas abouti. Réessayez ou choisissez un autre mode." 5. On abandon (user closes widget) → return to payment page, no error

Virement bancaire selected: 1. Show bank details screen: - Bank name, IBAN, account holder - Reference to include in transfer (tenant ID short code) - "Prenez une capture d'écran de ces informations" - Copy-to-clipboard buttons for IBAN and reference 2. Tenant provisioned with status ACTIVE_PAYMENT_PENDING 3. Redirect to Dashboard with banner (see §14)

Essai gratuit selected: 1. Confirm modal: "Votre essai de 14 jours commence maintenant. Tous les modules sélectionnés seront actifs." 2. Tenant provisioned with status TRIAL 3. Redirect to Dashboard with welcome celebration 🎉


4. Email Verification & Post-Verification Routing

4.1 Verification Email

Subject: "Confirmez votre inscription Papillon" From: [email protected] Body (French, Papillon-branded):

Bonjour [admin_full_name],

Bienvenue sur Papillon ! 🦋

Cliquez sur le bouton ci-dessous pour confirmer votre adresse e-mail et finaliser votre inscription.

[Confirmer mon adresse e-mail] ← Primary CTA button

Ce lien expire dans 24 heures.

Si vous n'avez pas demandé cette inscription, ignorez cet e-mail.

L'équipe Papillon ALTARYS ENTERPRISE

4.2 Verification Landing Page

URL: papillon.ci/verification?token=xxx

State Screen
Valid token "✓ Adresse e-mail confirmée !" → auto-redirect after 2s to next step (Trial setup or Payment choice)
Expired token "Ce lien a expiré." + "Renvoyer un e-mail de vérification" button (max 3 resends / 24h)
Invalid token "Ce lien n'est pas valide." + "Retour à l'inscription" link
Already verified "Votre adresse est déjà confirmée." + "Se connecter" link

4.3 Post-Verification Routing Logic

IF free_trial = true AND trial_not_used:
    → Provision tenant (TRIAL status)
    → Redirect to password creation
    → Redirect to Dashboard

IF free_trial = false:
    → Redirect to Module Selection (if not already done)
    → Redirect to Payment Choice
    → Provision tenant based on payment outcome

5. Payment Flow

5.1 Mobile Money Payment Widget

The payment flow uses the PaymentProvider adapter pattern. The UI renders a provider-agnostic experience:

  1. Pre-payment screen: Summary card (modules, price, pack if applicable)
  2. Provider selection (if multiple providers available):
  3. "Orange Money" with orange logo
  4. "Wave" with wave logo
  5. "MTN Money" with MTN logo
  6. Each shows phone number input pre-filled with admin phone
  7. Provider redirect/widget: Handled by provider SDK
  8. Confirmation: Webhook-based — user sees "Paiement en cours de traitement…" with a pulsing indicator
  9. Success: Green checkmark + "Paiement confirmé ! Bienvenue sur Papillon."

5.2 Payment States

State UI Timing
Initiating Button spinner + "Redirection vers [provider]…" 1-3s
Processing Full-screen loading: "Veuillez confirmer le paiement sur votre téléphone" 5-60s
Success Green checkmark + success message + auto-redirect to Dashboard (3s) Instant
Failed Toast: "Le paiement a échoué. Veuillez réessayer." + return to payment choice Instant
Timeout After 90s: "Le paiement prend plus de temps que prévu. Nous vous notifierons par e-mail dès confirmation." + redirect to Dashboard (PAYMENT_REQUIRED) 90s

6. Company Settings

Location in nav: Admin → Paramètres → Entreprise Access: DG and RH Manager roles Offline: Read-only (view settings). Write requires connectivity.

6.1 Company Information Tab

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ← Paramètres    Entreprise          │
├──────────────────────────────────────┤
│                                      │
│  ┌──────────────────────────────┐    │
│  │    [Logo placeholder]        │    │
│  │    📷 Modifier le logo       │    │  ← Tap to upload
│  └──────────────────────────────┘    │
│                                      │
│  Nom de l'entreprise                 │
│  ┌──────────────────────────────┐    │
│  │ Acme SARL                    │    │
│  └──────────────────────────────┘    │
│                                      │
│  Forme juridique                     │
│  ┌──────────────────────────────┐    │
│  │ SARL                      ▾  │    │
│  └──────────────────────────────┘    │
│                                      │
│  RCCM                                │
│  ┌──────────────────────────────┐    │
│  │ CI-ABJ-2024-B-12345         │    │
│  └──────────────────────────────┘    │
│                                      │
│  NIF                                 │
│  ┌──────────────────────────────┐    │
│  │                              │    │  ← Empty if ACTIVE_INCOMPLETE
│  └──────────────────────────────┘    │
│  ⚠ Requis pour la facturation       │
│    normalisée (FNE)                  │
│                                      │
│  Adresse                             │
│  ┌──────────────────────────────┐    │
│  │ Abidjan, Cocody, Rue X      │    │
│  └──────────────────────────────┘    │
│                                      │
│  Secteur d'activité                  │
│  ┌──────────────────────────────┐    │
│  │ Commerce                  ▾  │    │
│  └──────────────────────────────┘    │
│                                      │
│  ── Configuration ────────────────   │
│                                      │
│  Année fiscale (début)               │
│  ┌──────────────────────────────┐    │
│  │ Janvier                   ▾  │    │
│  └──────────────────────────────┘    │
│                                      │
│  Jours ouvrables / semaine           │
│  ┌──────────────────────────────┐    │
│  │ 5                         ▾  │    │
│  └──────────────────────────────┘    │
│                                      │
│  Heures / jour                       │
│  ┌──────────────────────────────┐    │
│  │ 8                         ▾  │    │
│  └──────────────────────────────┘    │
│                                      │
│  Classe de risque AT/MP              │
│  ┌──────────────────────────────┐    │
│  │ Classe 1 (2%)             ▾  │    │
│  └──────────────────────────────┘    │
│  ℹ Utilisé pour le calcul           │
│    des cotisations CNPS              │
│                                      │
│  ── Format Matricule Employé ─────   │
│                                      │
│  Préfixe                             │
│  ┌──────────────────────────────┐    │
│  │ EMP                          │    │
│  └──────────────────────────────┘    │
│                                      │
│  Nombre de chiffres                  │
│  ┌──────────────────────────────┐    │
│  │ 4                         ▾  │    │
│  └──────────────────────────────┘    │
│  Aperçu : EMP-2026-03-001             │
│                                      │
│  ── Approbateur par défaut ───────   │
│                                      │
│  ┌──────────────────────────────┐    │
│  │ 👤 Éric Blonvia (DG)     ▾  │    │
│  └──────────────────────────────┘    │
│  ℹ Reçoit les demandes si un        │
│    employé n'a pas de manager        │
│                                      │
└──────────────────────────────────────┘

Auto-Save Behavior

  • Every field saves automatically on blur (no "Save" button)
  • On save: brief green checkmark appears next to the field label (150ms fade in, holds 2s, 300ms fade out)
  • On error: red border + error message below field
  • On offline: orange dot appears next to field + "Modification enregistrée hors ligne" toast

Desktop Layout (1024px+)

Two-column form layout: - Left column: Company identity fields (name, legal form, RCCM, NIF, address, sector) - Right column: Configuration fields (fiscal year, working days, hours, AT/MP class, matricule format, default approver)


7. Organization & Master Data

7.1 Org Structure Tree

Location in nav: Admin → Paramètres → Structure de l'entreprise Access: DG and RH Manager roles Offline: Read (browse tree). Write (add/edit units) queues for sync.

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ← Paramètres    Structure           │
├──────────────────────────────────────┤
│                                      │
│  🏢 Acme SARL                        │  ← Root Entity (non-editable)
│  │                                   │
│  ├── 📍 Siège Abidjan               │  ← Site (optional level)
│  │   ├── 🏛 Direction Générale      │
│  │   ├── 🏛 Ressources Humaines     │
│  │   ├── 🏛 Comptabilité            │
│  │   ├── 🏛 Commercial              │
│  │   ├── 🏛 Production              │
│  │   └── 🏛 Informatique            │
│  │                                   │
│  └── 📍 Usine San Pedro             │  ← Second site
│      └── 🏛 Production SP           │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  + Ajouter une unité         │    │  ← FAB or button at bottom
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

Tree Interaction

Action Mobile Desktop
Expand/collapse Tap node → toggles children Click chevron → toggles
View details Tap node name → bottom sheet with name, type, status, employee count Click → right panel slide-in
Add child Long-press parent → "Ajouter sous [name]" action Click "+" icon that appears on hover
Edit In detail bottom sheet: edit name, deactivate In detail panel: inline edit
Deactivate In detail bottom sheet: "Désactiver" → undo toast In detail panel: toggle switch
Reorder Not supported MVP Not supported MVP

Add Unit Flow

When "Ajouter une unité" is tapped:

┌──────────────────────────────────────┐
│                                      │
│  ── Nouvelle unité ──────────────   │  ← Bottom sheet (mobile)
│                                      │
│  Type *                              │
│  ┌──────────────────────────────┐    │
│  │  ○ Site / Établissement      │    │
│  │  ○ Département / Service     │    │
│  └──────────────────────────────┘    │
│                                      │
│  Nom *                               │
│  ┌──────────────────────────────┐    │
│  │                              │    │
│  └──────────────────────────────┘    │
│                                      │
│  Rattachée à *                       │
│  ┌──────────────────────────────┐    │
│  │ 🏢 Acme SARL (Entité)    ▾  │    │  ← Parent selector
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │        Ajouter               │    │
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

Validation rules: - Site's parent must be the Entity - Department's parent can be Entity or a Site - Name must be unique within the same parent

7.2 Org Structure — Desktop (1024px+)

Master-detail layout: - Left panel (40%): Interactive tree with expand/collapse chevrons, search filter at top - Right panel (60%): Selected unit details — name (editable), type badge, status toggle, employee count, "Ajouter un sous-département" button

7.3 Category Management

Location: Admin → Paramètres → Catégories de salariés Simple list view:

┌──────────────────────────────────────┐
│  Catégories de salariés              │
│                                      │
│  ℹ Les catégories système ne         │
│    peuvent pas être supprimées.      │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  CAD · Cadre           🔒   │    │  ← System (is_system = true)
│  ├──────────────────────────────┤    │
│  │  AM  · Agent de maîtrise 🔒 │    │
│  ├──────────────────────────────┤    │
│  │  EMP · Employé          🔒  │    │
│  ├──────────────────────────────┤    │
│  │  OUV · Ouvrier          🔒  │    │
│  ├──────────────────────────────┤    │
│  │  STG · Stagiaire        ✏️  │    │  ← Custom (is_system = false)
│  └──────────────────────────────┘    │
│                                      │
│  + Ajouter une catégorie             │
│                                      │
└──────────────────────────────────────┘

7.4 Position Catalog

Location: Admin → Paramètres → Postes Searchable list with category association:

┌──────────────────────────────────────┐
│  Référentiel des postes              │
│                                      │
│  🔍 Rechercher un poste…             │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  Directeur Général           │    │
│  │  Catégorie: Cadre · DG       │    │
│  ├──────────────────────────────┤    │
│  │  Responsable RH              │    │
│  │  Catégorie: Cadre · RH       │    │
│  ├──────────────────────────────┤    │
│  │  Comptable                   │    │
│  │  Catégorie: AM · Comptabilité│    │
│  ├──────────────────────────────┤    │
│  │  Chauffeur              ✨   │    │  ← Custom position (is_custom)
│  │  Catégorie: Ouvrier          │    │
│  └──────────────────────────────┘    │
│                                      │
│  + Ajouter un poste                  │
│                                      │
└──────────────────────────────────────┘

Add Position form (bottom sheet on mobile): - Title (required) - Category (required, dropdown from employee categories) - Department (optional, dropdown from org units of type DEPARTMENT) - Description (optional)

7.5 Contract Type Reference

Location: Admin → Paramètres → Types de contrat Read-mostly list — system types are locked, custom can be added:

┌──────────────────────────────────────┐
│  Types de contrat                    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  CDI · Contrat à Durée     🔒│    │
│  │        Indéterminée          │    │
│  ├──────────────────────────────┤    │
│  │  CDD · Contrat à Durée    🔒│    │
│  │        Déterminée            │    │
│  │        Max: 2 ans            │    │  ← Duration info
│  ├──────────────────────────────┤    │
│  │  Stage                    🔒│    │
│  │        Max: 2 ans            │    │
│  ├──────────────────────────────┤    │
│  │  Apprentissage            🔒│    │
│  │        Max: 3 ans            │    │
│  ├──────────────────────────────┤    │
│  │  Journalier               🔒│    │
│  ├──────────────────────────────┤    │
│  │  CTT · Travail Temporaire 🔒│    │
│  │        Max: 2 ans            │    │
│  └──────────────────────────────┘    │
│                                      │
│  + Ajouter un type                   │
│                                      │
└──────────────────────────────────────┘

8. Employee Management (Baseline)

8.1 Employee List

Location in nav: RH → Employés Access: DG, RH Manager, Manager (sees direct reports only) Offline: Full read (list loads from IndexedDB). Create queues for sync.

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ← Employés            [🔍] [+]     │
├──────────────────────────────────────┤
│                                      │
│  12 employés actifs                  │
│                                      │
│  ── Filtres ─────── [Actif ▾] ───   │  ← Status filter chip
│                                      │
│  ┌──────────────────────────────┐    │
│  │  👤 Moussa Koné              │    │
│  │     EMP-2026-03-001 · Cadre   │    │
│  │     Directeur Général        │    │
│  │     Direction Générale       │    │
│  │                    Actif  ●  │    │  ← Green dot
│  ├──────────────────────────────┤    │
│  │  👤 Aminata Diallo           │    │
│  │     EMP-2026-03-002 · AM      │    │
│  │     Responsable RH           │    │
│  │     Ressources Humaines      │    │
│  │                    Actif  ●  │    │
│  ├──────────────────────────────┤    │
│  │  👤 Jean Kouamé              │    │
│  │     ⏳ Numéro en attente     │    │  ← Created offline
│  │     Comptable                │    │
│  │     Comptabilité             │    │
│  │                    Actif  ● ○│    │  ← Orange sync dot
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  + Nouvel employé            │    │  ← FAB (Floating Action Button)
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

Employee Card States

State Visual
Active Green dot --color-success
Pre-hire Blue dot --color-info + "Embauche le DD/MM" caption
Suspended Orange dot --color-warning + "Suspendu" badge
Terminated Grey dot --color-text-tertiary + "Fin de contrat" badge
On leave (derived) Green dot + "🏖 En congé" small badge
Pending sync Card has subtle orange left border + small sync icon

Search (Mobile)

Tap 🔍 → full-screen search overlay: - Search by: name, matricule, position, department - Results appear as the user types (debounced 300ms) - Search works offline (queries IndexedDB)

Desktop Layout (1024px+)

Table view (not card list):

Matricule Nom complet Poste Département Catégorie Contrat Statut Manager
EMP-2026-03-001 Moussa Koné DG Direction Gén. Cadre CDI ● Actif
  • Column sorting on all headers
  • Multi-column filter bar above table: Department dropdown, Status dropdown, Category dropdown, search input
  • Bulk actions: not in MVP (V2 with Employee Management)

8.2 Employee Detail View

Accessed by: Tap on employee card (mobile) or row (desktop)

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ←  Moussa Koné           [✏️]      │
├──────────────────────────────────────┤
│                                      │
│  ┌──────────────────────────────┐    │
│  │       👤                     │    │
│  │    Moussa Koné               │    │
│  │    EMP-2026-03-001            │    │
│  │    ● Actif                   │    │
│  └──────────────────────────────┘    │
│                                      │
│  ── Informations ────────────────   │
│                                      │
│  Poste         Directeur Général     │
│  Département   Direction Générale    │
│  Catégorie     Cadre                 │
│  Contrat       CDI                   │
│  Date d'embauche  15/01/2020         │
│  Manager       — (aucun)             │
│                                      │
│  ── Coordonnées ─────────────────   │
│                                      │
│  E-mail        [email protected]│  Téléphone     +225 07 12 34 56 78   │
│                                      │
│  ── Module RH Core ──────────────   │  ← Upsell section
│  ┌──────────────────────────────┐    │
│  │  🔒 Dossier complet          │    │
│  │  Photo, contacts d'urgence,  │    │
│  │  info bancaire, documents…   │    │
│  │                              │    │
│  │  Souscrire au module RH Core │    │
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

8.3 Employee Create/Edit Form

Offline: Full create capability. UUID v7 generated client-side. Matricule shows "Numéro en attente" until sync.

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ←  Nouvel employé                   │
├──────────────────────────────────────┤
│                                      │
│  Nom complet *                       │
│  ┌──────────────────────────────┐    │
│  │                              │    │
│  └──────────────────────────────┘    │
│                                      │
│  E-mail                              │
│  ┌──────────────────────────────┐    │
│  │                              │    │  ← Optional
│  └──────────────────────────────┘    │
│  ℹ Pas obligatoire — certains       │
│    employés n'ont pas d'e-mail       │
│                                      │
│  Téléphone                           │
│  ┌─────┬────────────────────────┐    │
│  │+225 │                        │    │  ← Optional
│  └─────┴────────────────────────┘    │
│                                      │
│  Département *                       │
│  ┌──────────────────────────────┐    │
│  │ Sélectionner…             ▾  │    │  ← Dropdown from org tree
│  └──────────────────────────────┘    │
│                                      │
│  Poste *                             │
│  ┌──────────────────────────────┐    │
│  │ Rechercher ou créer…         │    │  ← Combobox with escape hatch
│  └──────────────────────────────┘    │
│  ℹ Tapez un nouveau poste pour      │
│    l'ajouter au référentiel          │
│                                      │
│  Catégorie *                         │
│  ┌──────────────────────────────┐    │
│  │ (auto-rempli via le poste)   │    │  ← Auto-filled from position
│  └──────────────────────────────┘    │
│  ℹ Déterminée par le poste.         │
│    Modifiable si nécessaire.         │
│                                      │
│  Type de contrat *                   │
│  ┌──────────────────────────────┐    │
│  │ CDI                       ▾  │    │
│  └──────────────────────────────┘    │
│                                      │
│  Date d'embauche *                   │
│  ┌──────────────────────────────┐    │
│  │ JJ/MM/AAAA          📅      │    │  ← Date picker
│  └──────────────────────────────┘    │
│  ℹ Si la date est future,           │
│    l'employé sera en statut          │
│    « Pré-embauche »                  │
│                                      │
│  Manager (N+1)                       │
│  ┌──────────────────────────────┐    │
│  │ Rechercher un employé…    ▾  │    │  ← Searchable employee select
│  └──────────────────────────────┘    │
│  ℹ Si non renseigné, les demandes   │
│    d'approbation iront à             │
│    l'approbateur par défaut          │
│                                      │
│  ┌──────────────────────────────┐    │
│  │     Enregistrer l'employé    │    │  ← Primary button
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

Position Combobox (Escape Hatch Pattern)

The Position field is a combobox — a combined search input + dropdown:

  1. User starts typing → dropdown shows matching positions from catalog
  2. If a match exists → user selects it → category auto-fills from the position's linked category
  3. If NO match exists → dropdown shows: "[typed text] — Ajouter comme nouveau poste"
  4. Clicking "Ajouter" → inline form expands: "Catégorie pour ce poste : [dropdown]"
  5. On save → position is created in catalog (is_custom = true) + employee is linked

Why this pattern: Forces structured data (position + category) without forcing the user to pre-configure the catalog. The DG at a 10-person company can type "Chauffeur" and get going — the catalog builds itself.

Form Auto-Save

  • Each field auto-saves to IndexedDB on blur (even if the full form isn't submitted)
  • If the user navigates away mid-form (back button, app switch), data is preserved
  • On return, form restores from IndexedDB
  • "Brouillon" (Draft) badge appears in the top bar when an incomplete form exists
  • Draft can be resumed or discarded

8.4 Employee Form — Desktop (1024px+)

Two-column layout: - Left column: Identity (name, email, phone) - Right column: Assignment (department, position, category, contract, hire date, manager) - Full width bottom: Action button


9. User Management & Invitations

9.1 User List

Location: Admin → Utilisateurs Access: DG and RH Manager Offline: No (users are always created online)

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ← Utilisateurs           [+]       │
├──────────────────────────────────────┤
│                                      │
│  5 utilisateurs · 3 actifs           │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  👤 Éric Blonvia             │    │
│  │     [email protected]             │    │
│  │     DG                  ● ✓  │    │  ← Active
│  ├──────────────────────────────┤    │
│  │  👤 Aminata Diallo           │    │
│  │     [email protected]          │    │
│  │     RH Manager          ● ✓  │    │
│  ├──────────────────────────────┤    │
│  │  📧 [email protected]           │    │  ← Invited (no name yet)
│  │     Employé           ◌ Invité│    │  ← Hollow dot = invited
│  │     Expiré — Renvoyer →      │    │  ← Re-invite link
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

9.2 Invite User Flow

Tap "+" button → bottom sheet (mobile) / side panel (desktop):

┌──────────────────────────────────────┐
│  ── Inviter un utilisateur ───────   │
│                                      │
│  Adresse e-mail *                    │
│  ┌──────────────────────────────┐    │
│  │                              │    │
│  └──────────────────────────────┘    │
│                                      │
│  Rôle *                              │
│  ┌──────────────────────────────┐    │
│  │  ○ DG (Directeur Général)    │    │
│  │    Accès complet              │    │
│  │                              │    │
│  │  ○ RH Manager                │    │
│  │    Gestion employés, congés  │    │
│  │                              │    │
│  │  ○ Comptable                 │    │
│  │    Budget, engagements, paie │    │
│  │                              │    │
│  │  ○ Employé                   │    │
│  │    Libre-service uniquement  │    │
│  │                              │    │
│  │  ○ Manager (Chef de service) │    │
│  │    Approbations équipe       │    │
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │      Envoyer l'invitation    │    │
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

Multi-Tenant User Detection

If the email already exists in another tenant: - Show info message: "Cet utilisateur existe déjà sur la plateforme. Il sera ajouté à votre entreprise avec le rôle sélectionné." - No new password email — just a notification: "Vous avez été ajouté à l'entreprise [name]" - User sees new tenant in their "Mes entreprises" switcher


10. Module Gating & Upsell

10.1 Navigation Display

Unsubscribed modules appear in the sidebar (desktop) and "Plus" bottom sheet (mobile) with distinct styling:

Subscribed module: - Full color icon - Normal text - Clickable → navigates to module

Unsubscribed module: - 50% opacity icon - Text in --color-text-tertiary - Small "✦ Bientôt" badge (for not-yet-released) or "🔒" icon (for released but not subscribed) - Clickable → opens upsell card (not navigation)

10.2 Module Upsell Card

Mobile: Bottom sheet Desktop: Popover card from sidebar

┌──────────────────────────────────────┐
│                                      │
│        📅  Gestion de la Paie       │
│                                      │
│  Calculez et générez les bulletins   │
│  de paie de vos employés,           │
│  conformément au Code du Travail     │
│  ivoirien.                           │
│                                      │
│  ✓ Calcul automatique ITS + CNPS    │
│  ✓ Bulletins de paie PDF            │
│  ✓ Livre de paie mensuel            │
│  ✓ Déclarations sociales            │
│                                      │
│  À partir de 30 000 FCFA/mois       │
│                                      │
│  ── Vous êtes administrateur ? ──   │
│                                      │
│  ┌──────────────────────────────┐    │
│  │     Souscrire ce module      │    │  ← Admin only → goes to §11
│  └──────────────────────────────┘    │
│                                      │
│  ── Vous êtes employé ? ──────────  │
│                                      │
│  Contactez votre administrateur      │
│  pour activer ce module.             │
│                                      │
└──────────────────────────────────────┘

Logic: - IF user has role DG or permission cp.tenant.manage → show "Souscrire" button - IF user is regular employee → show "Contactez votre administrateur" text - Module descriptions and feature lists are hardcoded per module (content managed, not DB-driven for MVP)


11. Billing & Subscription Management

11.1 Subscription Dashboard

Location: Admin → Abonnement Access: DG only Offline: No (billing is always online)

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ←  Abonnement                       │
├──────────────────────────────────────┤
│                                      │
│  ── Votre abonnement ────────────   │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  Statut: ● Actif              │    │
│  │  Segment: S1 (2-12 salariés) │    │
│  │  Prochaine échéance:          │    │
│  │  15/03/2026 (17 jours)        │    │
│  └──────────────────────────────┘    │
│                                      │
│  ── Modules souscrits ───────────   │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  ✓ Absences       12 000 FCFA│    │
│  │  ✓ Présence QR     5 000 FCFA│    │
│  │  ─────────────────────────── │    │
│  │  Pack Contrôle    15 000 FCFA│    │
│  │  Économie:        -2 000 FCFA│    │
│  │  ─────────────────────────── │    │
│  │  Total mensuel    15 000 FCFA│    │
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  + Ajouter un module          │    │  ← Goes to module catalog
│  └──────────────────────────────┘    │
│                                      │
│  ── Méthode de paiement ──────────  │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  📱 Orange Money              │    │
│  │  +225 07 XX XX XX XX          │    │
│  │                  Modifier →   │    │
│  └──────────────────────────────┘    │
│                                      │
│  ── Historique des factures ──────  │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  FAC-2026-00001 · Fév. 2026  │    │
│  │  15 000 FCFA     ● Payée     │    │
│  │                  PDF ↓ →     │    │
│  ├──────────────────────────────┤    │
│  │  FAC-2026-00002 · Mars 2026  │    │
│  │  15 000 FCFA     ◌ En attente│    │
│  │          Payer maintenant →   │    │
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

11.2 Add Module Flow

From "Ajouter un module" button → module catalog screen (similar to Step 2 of onboarding, §3.2): - Shows all available modules with current prices for the tenant's segment - Selected modules appear as "selected" - New module selection shows price delta: "+12 000 FCFA/mois" - Pack detection runs in real-time - Confirmation: "Votre abonnement sera mis à jour à la prochaine échéance." - Payment for the delta is not charged mid-cycle (MVP simplification)

11.3 Module Deactivation

From subscription dashboard, tap a subscribed module → detail:

┌──────────────────────────────────────┐
│                                      │
│  Désactiver « Présence QR » ?        │
│                                      │
│  ⚠ Vos données de pointage          │
│    resteront accessibles en          │
│    lecture seule.                     │
│                                      │
│  ⚠ Le Pack Contrôle ne sera         │
│    plus applicable. Votre            │
│    tarif Absences repassera à        │
│    12 000 FCFA/mois.                 │
│                                      │
│  ┌──────────────────────────────┐    │
│  │     Confirmer la              │    │
│  │     désactivation             │    │  ← Destructive secondary button
│  └──────────────────────────────┘    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │     Annuler                   │    │  ← Primary button (keep module)
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

Undo: After confirmation, 10-second undo toast: "Module désactivé. Annuler ?"


12. Audit Trail Viewer

12.1 Audit Log Screen

Location: Admin → Audit Access: DG only (tenant-scoped view) Offline: No

Layout — Mobile (360px)

┌──────────────────────────────────────┐
│  ←  Journal d'audit                  │
├──────────────────────────────────────┤
│                                      │
│  ── Filtres ─────────────────────   │
│  [Module ▾] [Action ▾] [Date ▾]     │  ← Filter chips
│                                      │
│  ┌──────────────────────────────┐    │
│  │  26/02/2026 14:32             │    │
│  │  Éric Blonvia                 │    │
│  │  Employé créé                 │    │  ← Human-readable action
│  │  « Jean Kouamé »              │    │
│  │  Module: Employés             │    │
│  │                  Détails →    │    │
│  ├──────────────────────────────┤    │
│  │  26/02/2026 10:15             │    │
│  │  Aminata Diallo               │    │
│  │  Département modifié          │    │
│  │  « Production » → « Prod. »   │    │  ← Before → After summary
│  │  Module: Structure            │    │
│  │                  Détails →    │    │
│  └──────────────────────────────┘    │
│                                      │
│  Charger plus…                       │  ← Pagination (50 per page)
│                                      │
└──────────────────────────────────────┘

Audit Detail View

Tap "Détails" → bottom sheet (mobile) / side panel (desktop) showing the full before/after JSON diff in a human-readable format:

┌──────────────────────────────────────┐
│  ── Détail de l'audit ────────────  │
│                                      │
│  Action: Modification                │
│  Entité: Département                 │
│  Par: Aminata Diallo                 │
│  Date: 26/02/2026 à 10:15           │
│                                      │
│  ── Modifications ────────────────  │
│                                      │
│  Nom                                 │
│    Avant: Production                 │
│    Après: Prod.                      │
│                                      │
└──────────────────────────────────────┘

12.2 Audit Log — Desktop (1024px+)

Full-width table with columns: Date/Heure, Utilisateur, Action, Entité, Module, Résumé. Expandable rows showing before/after diff inline. Advanced filters: date range picker, module dropdown, action type checkboxes, user search.


13. Multi-Tenant Switcher

13.1 Tenant Switcher (Cabinet Comptable / Multi-Tenant Users)

Trigger: User avatar in top bar → "Mes entreprises" option

Layout — Mobile (full-screen bottom sheet)

┌──────────────────────────────────────┐
│  ── Mes entreprises ─────────────   │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  [Logo]  Acme SARL           │    │
│  │          ✓ Entreprise active  │    │  ← Current tenant (highlighted)
│  │          DG                   │    │
│  ├──────────────────────────────┤    │
│  │  [Logo]  Pharma Plus CI      │    │
│  │          Comptable            │    │
│  ├──────────────────────────────┤    │
│  │  [Logo]  Trans Express       │    │
│  │          Comptable            │    │
│  ├──────────────────────────────┤    │
│  │  [Logo]  Resto Le Palmier    │    │
│  │          Comptable            │    │
│  └──────────────────────────────┘    │
│                                      │
│  Tapez sur une entreprise pour       │
│  changer de contexte.                │
│                                      │
└──────────────────────────────────────┘

Behavior: - Tap a tenant → full-screen loading overlay: "Chargement de [tenant name]…" (token exchange happening) - New JWT issued → all cached data replaced → redirect to Dashboard of new tenant - Previous tenant context is cleared from memory - Switch takes < 2 seconds

Desktop Layout

Dropdown from user avatar menu (not a separate page): - Shows tenant list with logos, names, and user's role per tenant - Current tenant has checkmark - Click to switch — same token exchange flow

13.2 Home Tenant Dashboard (Multi-Tenant User Login)

When a user with multiple tenants logs in: - They land on their home_tenant_id dashboard - The "Mes entreprises" section appears as a card on the Dashboard (not just in the user menu) - Shows thumbnail cards for each tenant with: logo, name, role, quick-switch tap


14. Tenant Status Banners

Persistent, context-sensitive banners appear at the top of the content area (below the top bar) based on tenant status. These are not toasts — they persist until the condition is resolved.

14.1 Banner Specifications

Tenant Status Banner Color Message Dismissible? CTA
TRIAL --color-info-light + --color-info border "Période d'essai : [X] jours restants" No "Souscrire maintenant" (admin) / none (employee)
PAYMENT_REQUIRED --color-warning-light + --color-warning border "Modules en lecture seule. Finalisez votre paiement pour activer toutes les fonctionnalités." No "Payer maintenant" (admin)
ACTIVE_PAYMENT_PENDING --color-info-light + --color-info border "Virement en attente de confirmation. [X] jours restants." Yes (once per session) "Payer par Mobile Money" (admin)
ACTIVE_INCOMPLETE --color-warning-light + --color-warning border "Veuillez compléter vos informations légales (RCCM, NIF) dans les paramètres." Yes (once per day) "Compléter →" (admin)
ACTIVE_INCOMPLETE (3 months, read-only) --color-error-light + --color-error border "Accès en lecture seule. Complétez vos informations légales pour restaurer l'accès complet." No "Compléter →" (admin)
SUSPENDED --color-error-light + --color-error border "Compte suspendu. Vos données sont préservées. Renouvelez votre abonnement pour restaurer l'accès." No "Renouveler →" (admin)

14.2 Banner Layout

┌──────────────────────────────────────┐
│  ⚠ Période d'essai : 10 jours       │
│    restants.          [Souscrire →]  │
│                               [✕]   │  ← If dismissible
└──────────────────────────────────────┘
  • Height: auto (wraps content, typically 48-64px)
  • Full width of content area
  • Below top bar, above page content
  • Max one banner visible at a time (highest priority wins)
  • Priority order: SUSPENDED > ACTIVE_INCOMPLETE (read-only) > PAYMENT_REQUIRED > ACTIVE_INCOMPLETE > TRIAL > ACTIVE_PAYMENT_PENDING

15. Admin Console (Separate App)

15.1 Design Language — Admin Console

The Admin Console is a separate React application with a different design language from Papillon.

Aspect Papillon (tenant) Admin Console (ALTARYS)
Users HR managers, employees 3-5 ALTARYS operators
Device Phone-first (360px) Desktop only (1024px+)
Offline Mandatory (PWA) Not needed
Aesthetic Warm amber/teal Neutral grey/blue
Density Low (generous whitespace) Medium (data-dense tables)
Primary color #F59E0B (amber) #1E3A5F (navy)
Accent #0D6B6E (teal) #2563EB (blue)
Background #FFFDF7 (warm off-white) #F9FAFB (cool light grey)
Typography Inter 16px body Inter 14px body (denser)
Tone "Votre assistant RH de confiance" "Plateforme d'administration ALTARYS"

The Admin Console does NOT use Papillon design tokens. It has its own minimal token set:

Token Value Usage
--admin-primary #1E3A5F Headers, primary actions
--admin-accent #2563EB Links, active states
--admin-bg #F9FAFB Page background
--admin-surface #FFFFFF Cards, panels
--admin-border #E5E7EB Borders, dividers
--admin-text #111827 Primary text
--admin-text-secondary #6B7280 Secondary text
--admin-success #059669 Active, paid, healthy
--admin-warning #D97706 Pending, attention needed
--admin-error #DC2626 Suspended, failed, critical

15.2 Tenant List (Admin Dashboard)

The main screen ALTARYS operators see daily. Dense, filterable, sortable.

Layout — Desktop (1024px+)

┌──────────────────────────────────────────────────────────────────────────────┐
│  ALTARYS Admin                                            [🔔] [👤 Admin]   │
├──────────┬───────────────────────────────────────────────────────────────────┤
│          │                                                                   │
│ 📊 Tableau│  ── Aperçu rapide ─────────────────────────────────────────────  │
│    de bord│  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────────┐    │
│          │  │ 142     │ │ 12     │ │ 5      │ │ 1 845  │ │ 2.4M FCFA  │    │
│ 🏢 Tenants│ │ Tenants │ │Paiements│ │Suspendus│ │Employés│ │MRR         │    │
│          │  │ actifs  │ │en att.  │ │        │ │ total  │ │            │    │
│ 💳 Paie- │  └────────┘ └────────┘ └────────┘ └────────┘ └────────────┘    │
│    ments │                                                                   │
│          │  ── Tenants ──────────────── [🔍 Rechercher…    ] [Exporter ↓]  │
│ 📊 Statis-│ [Statut ▾] [Segment ▾] [Canal ▾] [Date ▾]                      │
│    tiques│                                                                   │
│          │  ┌──────┬───────────┬──────┬─────┬──────┬──────┬────────────────┐│
│ ⚙️ Config │ │Status │ Entreprise│ Seg. │Empl.│Canal │ Créé │ Paiement       ││
│   pays   │  ├──────┼───────────┼──────┼─────┼──────┼──────┼────────────────┤│
│          │  │● ACTIF│ Acme SARL │  S1  │  12 │ Self │15/01 │ ● Payé         ││
│          │  │● ACTIF│ Pharma+   │  S3  │  45 │ CRM  │20/01 │ ● Payé         ││
│          │  │◐ ESSAI│ TechCI    │  S1  │   5 │ Self │24/02 │ ◌ Essai (8j)   ││
│          │  │⚠ PEND.│ Transport │  S2  │  20 │ CRM  │25/02 │ ⚠ Virement att.││
│          │  │✕ SUSP.│ OldCorp   │  S1  │   8 │ Self │01/11 │ ✕ Impayé 22j   ││
│          │  └──────┴───────────┴──────┴─────┴──────┴──────┴────────────────┘│
│          │                                                                   │
│          │  Afficher 1-20 sur 142                [< 1 2 3 ... 8 >]          │
│          │                                                                   │
└──────────┴───────────────────────────────────────────────────────────────────┘
  200px                              Remaining width

Table Row Status Icons

Status Icon Color
ACTIVE --admin-success
TRIAL --admin-accent
ACTIVE_INCOMPLETE --admin-warning
ACTIVE_PAYMENT_PENDING --admin-warning
PAYMENT_REQUIRED --admin-warning
SUSPENDED --admin-error
DELETED --admin-text-secondary
PENDING --admin-text-secondary
PENDING_VERIFICATION --admin-text-secondary

15.3 Tenant Detail (Admin)

Click a tenant row → side panel or full page with tabs:

Tabs: Informations | Modules | Paiements | Audit | Actions

Informations tab: - Company: name, RCCM, NIF, country, address, sector - Admin: name, email, phone - Config: segment, DB profile, onboarding channel, salesperson ID, dates (created, activated, suspended) - Status badge with state machine context

Modules tab: - List of all modules with status per module (ACTIVE / INACTIVE / TRIAL) - "Activer" / "Désactiver" toggle per module (with confirmation) - Override capability: "Accorder un accès temporaire" (with expiry date)

Paiements tab: - Invoice list with statuses - "Confirmer le paiement" button for pending bank transfers - Manual payment recording form

Audit tab: - Tenant-specific audit trail (filtered view of global audit)

Actions tab: - "Suspendre ce tenant" (requires reason text input) - "Réactiver ce tenant" - "Supprimer ce tenant" (soft delete — requires typed confirmation: company name)

15.4 Pending Payments Dashboard (Admin)

Critical daily-use screen for ALTARYS operations.

┌────────────────────────────────────────────────────────────────────┐
│  Paiements en attente                          Auto-refresh: 5min │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ── Virements en attente (5) ──────────────────────────────────   │
│                                                                    │
│  ┌──────────┬──────────┬──────────┬──────┬──────────────────────┐ │
│  │Entreprise│ Montant  │ Créé le  │ Reste│ Action               │ │
│  ├──────────┼──────────┼──────────┼──────┼──────────────────────┤ │
│  │Transport │15 000 FCFA│20/02/2026│ 4j  │[Confirmer] [Relancer]│ │
│  │LogiCI    │25 000 FCFA│22/02/2026│ 6j  │[Confirmer] [Relancer]│ │
│  └──────────┴──────────┴──────────┴──────┴──────────────────────┘ │
│                                                                    │
│  ── Paiements échoués (2) ────────────────────────────────────   │
│                                                                    │
│  ┌──────────┬──────────┬──────────┬──────────────────────────────┐│
│  │Entreprise│ Montant  │ Échoué   │ Action                       ││
│  ├──────────┼──────────┼──────────┼──────────────────────────────┤│
│  │BoutiqueCI│15 000 FCFA│25/02/2026│[Renvoyer lien] [Marquer payé]││
│  └──────────┴──────────┴──────────┴──────────────────────────────┘│
│                                                                    │
│  ── Factures impayées (3) ────────────────────────────────────   │
│  ...                                                               │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

"Confirmer" action: 1. Click → confirmation dialog: "Confirmez-vous la réception du virement de [amount] de [company] ?" 2. On confirm → Invoice status → PAID, Tenant status updated per state machine 3. Audit entry created with admin's user_id 4. Email notification sent to tenant: "Paiement confirmé"

15.5 Module Override (Admin)

From tenant detail → Modules tab:

  • Toggle module ON/OFF for any tenant
  • "Accès promotionnel" option: activate module with expiry date (promotional access for demos/trials)
  • All overrides recorded in audit trail with admin user_id and reason

15.6 Country Configuration Editor (Admin)

Accessed: Admin → Config Pays Usage: Rare (when tax rates change, holidays are updated)

Two-panel layout: - Left: Country selector (CI for MVP) + config categories (Tax, Social Contributions, Leave Types, Holidays, Categories, Contract Types, Salary Grids) - Right: Editable data table for selected category

Special UI: Unverified rates (is_verified = false) displayed with orange background and "⚠ Non vérifié" badge. Admin can toggle is_verified after confirming with official sources.

15.7 Platform Metrics (Admin)

Simple KPI dashboard:

Metric Display
Total tenants by status Horizontal stacked bar
Total active employees Big number with trend
MRR (Monthly Recurring Revenue) Big number with trend
Module popularity Horizontal bar chart (modules ranked by subscription count)
Tenant growth Line chart (new tenants per week, last 12 weeks)
Payment method split Pie chart (Mobile Money vs. Bank Transfer)

16. Offline Behavior Specifications

16.1 Offline Capability Matrix

Screen / Feature Offline Read Offline Write Sync Behavior
Employee List ✅ Full (IndexedDB) Prefetched on login
Employee Create ✅ Full (UUID v7) Queue → POST on reconnect
Employee Edit ✅ Current data ✅ Edits queued Last-write-wins (with conflict detection)
Org Structure ✅ Full tree ✅ Add units Queue → POST on reconnect
Position Catalog ✅ Full list ✅ Add positions Queue → POST on reconnect
Company Settings ✅ Read Requires connectivity
User Management Always online
Billing/Payment Always online
Audit Trail Always online
Module Catalog ✅ Cached descriptions Always online for actions
Tenant Switcher Requires token exchange
Registration Always online

16.2 Sync Conflict Resolution

When an employee record is edited offline and conflicts with a server update:

┌──────────────────────────────────────┐
│  ⚠ Conflit de synchronisation        │
│                                      │
│  L'employé « Jean Kouamé » a été    │
│  modifié sur un autre appareil.      │
│                                      │
│  ── Votre version ────────────────  │
│  Département: Commercial             │
│  (modifié le 26/02 à 14:30)         │
│                                      │
│  ── Version du serveur ───────────  │
│  Département: Production             │
│  (modifié le 26/02 à 14:15 par      │
│   Aminata Diallo)                    │
│                                      │
│  ┌──────────────────────────────┐    │
│  │  Garder ma version           │    │  ← Overwrites server
│  └──────────────────────────────┘    │
│  ┌──────────────────────────────┐    │
│  │  Garder la version serveur   │    │  ← Discards local change
│  └──────────────────────────────┘    │
│                                      │
└──────────────────────────────────────┘

16.3 Prefetch Strategy

On login (or app open with valid token): 1. Immediate: Employee list, org structure tree, position catalog, contract types, categories 2. Background: Tenant settings, module list, notification count, permission matrix 3. On-demand: Audit trail, billing data, user list (not cached)


17. Responsive Behavior Summary

Breakpoints (from host-shell-design.md)

Breakpoint Width Layout Pattern
Phone 360px Single column, bottom sheet modals, bottom nav
Tablet 768px Collapsed sidebar (icons), content fills remaining width
Desktop 1024px Expanded sidebar (260px), master-detail panels
Large Desktop 1440px Same as desktop, content centered in max-width 1200px

Per-Screen Responsive Table

Screen Phone (360) Tablet (768) Desktop (1024+)
Registration Single column card Single column card (wider) Split: branding left, form right
Module Selection Stacked cards 2-column card grid 3-column card grid
Payment Choice Stacked options 2-column options 2-column with summary sidebar
Company Settings Single column form Two column form Two column form
Org Structure Indented list Tree with detail bottom sheet Master (tree) + detail panel
Employee List Card list Card list (2 columns) Data table
Employee Form Single column Two column Two column
Employee Detail Stacked sections Two column Two column + sidebar
User List Card list Table Table
Subscription Stacked cards Two column Two column + sidebar
Audit Trail Timeline list Table (compact) Full table with filters
Tenant Switcher Full screen bottom sheet Modal overlay Dropdown from avatar

18. French Micro-copy Document

18.1 Registration & Onboarding

Key French Text
registration.title "Créez votre compte Papillon en 5 minutes"
registration.subtitle "Simplifiez la gestion de vos ressources humaines"
registration.company_name.label "Nom de l'entreprise"
registration.company_name.placeholder "Ex : Acme SARL"
registration.country.label "Pays"
registration.employee_count.label "Nombre de salariés"
registration.employee_count.placeholder "Sélectionnez une tranche"
registration.admin_name.label "Votre nom complet"
registration.admin_name.placeholder "Ex : Moussa Koné"
registration.email.label "Adresse e-mail"
registration.email.placeholder "[email protected]"
registration.phone.label "Numéro de téléphone"
registration.phone.placeholder "07 12 34 56 78"
registration.rccm.label "RCCM (optionnel)"
registration.rccm.helper "Vous pourrez le fournir plus tard"
registration.trial.label "Démarrer un essai gratuit de 14 jours"
registration.submit "Continuer →"
registration.already_registered "Déjà inscrit ?"
registration.login_link "Se connecter"
registration.duplicate_email "Un compte existe déjà avec cet e-mail."
registration.duplicate_phone "Un compte existe déjà avec ce numéro."
registration.rate_limited "Trop de tentatives. Veuillez réessayer dans quelques minutes."
registration.server_error "Une erreur est survenue. Veuillez réessayer."

18.2 Module Selection

Key French Text
modules.title "Choisissez vos modules"
modules.subtitle "Sélectionnez au moins 1 module. Vous pourrez en ajouter plus tard."
modules.available_now "Disponible maintenant"
modules.coming_soon "Bientôt disponible"
modules.pack_detected "Pack {packName} détecté · -{discount}%"
modules.summary "{count} module(s) · {price} FCFA/mois"
modules.continue "Continuer →"
modules.subscribe "Souscrire"
modules.contact_admin "Contactez votre administrateur pour activer ce module."

18.3 Payment

Key French Text
payment.title "Comment souhaitez-vous payer ?"
payment.mobile_money.title "Paiement Mobile Money"
payment.mobile_money.providers "Orange Money, Wave, MTN Money"
payment.mobile_money.instant "Paiement instantané. Accès immédiat."
payment.mobile_money.button "Payer {amount} FCFA"
payment.bank_transfer.title "Virement bancaire"
payment.bank_transfer.delay "Délai de traitement : 10 jours maximum. Accès complet pendant cette période."
payment.bank_transfer.button "Choisir le virement"
payment.trial.title "Essai gratuit 14 jours"
payment.trial.subtitle "Testez avant de payer."
payment.trial.link "Démarrer l'essai →"
payment.processing "Veuillez confirmer le paiement sur votre téléphone"
payment.success "Paiement confirmé ! Bienvenue sur Papillon."
payment.failed "Le paiement a échoué. Veuillez réessayer."
payment.timeout "Le paiement prend plus de temps que prévu. Nous vous notifierons par e-mail dès confirmation."

18.4 Verification & Status

Key French Text
verification.email_sent "Un e-mail de vérification a été envoyé à {email}"
verification.check_inbox "Vérifiez votre boîte de réception (et les spams)"
verification.success "Adresse e-mail confirmée !"
verification.expired "Ce lien a expiré."
verification.resend "Renvoyer un e-mail de vérification"
verification.invalid "Ce lien n'est pas valide."
verification.already_done "Votre adresse est déjà confirmée."

18.5 Tenant Status Banners

Key French Text
banner.trial "Période d'essai : {days} jour(s) restant(s)"
banner.trial.cta "Souscrire maintenant"
banner.payment_required "Modules en lecture seule. Finalisez votre paiement pour activer toutes les fonctionnalités."
banner.payment_required.cta "Payer maintenant"
banner.payment_pending "Virement en attente de confirmation. {days} jour(s) restant(s)."
banner.payment_pending.cta "Payer par Mobile Money"
banner.incomplete "Veuillez compléter vos informations légales (RCCM, NIF) dans les paramètres de votre entreprise."
banner.incomplete.cta "Compléter →"
banner.incomplete_readonly "Accès en lecture seule. Complétez vos informations légales pour restaurer l'accès complet."
banner.suspended "Compte suspendu. Vos données sont préservées. Renouvelez votre abonnement pour restaurer l'accès."
banner.suspended.cta "Renouveler →"

18.6 Employee Management

Key French Text
employee.list.title "Employés"
employee.list.count "{count} employé(s) actif(s)"
employee.list.empty "Aucun employé pour le moment. Ajoutez votre premier collaborateur !"
employee.list.empty.cta "Ajouter un employé"
employee.create.title "Nouvel employé"
employee.edit.title "Modifier l'employé"
employee.form.name.label "Nom complet"
employee.form.email.label "E-mail"
employee.form.email.helper "Pas obligatoire — certains employés n'ont pas d'e-mail"
employee.form.phone.label "Téléphone"
employee.form.department.label "Département"
employee.form.department.placeholder "Sélectionner…"
employee.form.position.label "Poste"
employee.form.position.placeholder "Rechercher ou créer…"
employee.form.position.helper "Tapez un nouveau poste pour l'ajouter au référentiel"
employee.form.category.label "Catégorie"
employee.form.category.helper "Déterminée par le poste. Modifiable si nécessaire."
employee.form.contract.label "Type de contrat"
employee.form.hire_date.label "Date d'embauche"
employee.form.hire_date.helper_future "Si la date est future, l'employé sera en statut « Pré-embauche »"
employee.form.manager.label "Manager (N+1)"
employee.form.manager.placeholder "Rechercher un employé…"
employee.form.manager.helper "Si non renseigné, les demandes d'approbation iront à l'approbateur par défaut"
employee.form.submit "Enregistrer l'employé"
employee.created.online "Employé créé ✓"
employee.created.offline "Employé enregistré hors ligne ●"
employee.matricule.pending "Numéro en attente"
employee.status.active "Actif"
employee.status.pre_hire "Pré-embauche"
employee.status.suspended "Suspendu"
employee.status.terminated "Fin de contrat"
employee.status.on_leave "En congé"
employee.no_manager_alert "L'employé {name} n'a pas de responsable assigné. Veuillez assigner un N+1."

18.7 Organization & Settings

Key French Text
org.title "Structure de l'entreprise"
org.add_unit "Ajouter une unité"
org.unit_type.entity "Entité"
org.unit_type.site "Site / Établissement"
org.unit_type.department "Département / Service"
org.deactivate "Désactiver"
org.deactivate.confirm "Les employés rattachés ne seront pas affectés, mais aucune nouvelle affectation ne sera possible."
settings.title "Paramètres de l'entreprise"
settings.saved "Enregistré ✓"
settings.saved_offline "Modification enregistrée hors ligne"
settings.default_approver.label "Approbateur par défaut"
settings.default_approver.helper "Reçoit les demandes si un employé n'a pas de manager"
settings.matricule_preview "Aperçu : {prefix}-{YYYY}-{MM}-{example}"

18.8 Billing & Subscription

Key French Text
billing.title "Abonnement"
billing.status "Statut"
billing.segment "Segment : {code} ({range} salariés)"
billing.next_due "Prochaine échéance : {date} ({days} jours)"
billing.modules_subscribed "Modules souscrits"
billing.pack_applied "Pack {name} appliqué"
billing.savings "Économie : -{amount} FCFA"
billing.total_monthly "Total mensuel : {amount} FCFA"
billing.add_module "Ajouter un module"
billing.payment_method "Méthode de paiement"
billing.change_method "Modifier"
billing.invoices "Historique des factures"
billing.invoice.paid "Payée"
billing.invoice.pending "En attente"
billing.invoice.overdue "En retard"
billing.deactivate.title "Désactiver « {module} » ?"
billing.deactivate.data_warning "Vos données resteront accessibles en lecture seule."
billing.deactivate.pack_warning "Le Pack {name} ne sera plus applicable. Votre tarif {module} repassera à {price} FCFA/mois."
billing.deactivate.confirm "Confirmer la désactivation"
billing.deactivate.undo "Module désactivé. Annuler ?"

18.9 User Management

Key French Text
users.title "Utilisateurs"
users.count "{total} utilisateur(s) · {active} actif(s)"
users.invite "Inviter un utilisateur"
users.invite.email.label "Adresse e-mail"
users.invite.role.label "Rôle"
users.invite.submit "Envoyer l'invitation"
users.invite.success "Invitation envoyée à {email}"
users.invite.existing_user "Cet utilisateur existe déjà sur la plateforme. Il sera ajouté à votre entreprise avec le rôle sélectionné."
users.status.active "Actif"
users.status.invited "Invité"
users.status.disabled "Désactivé"
users.status.expired "Expiré — Renvoyer"
users.role.dg "DG (Directeur Général)"
users.role.dg.desc "Accès complet"
users.role.rh "RH Manager"
users.role.rh.desc "Gestion employés, congés, paie"
users.role.comptable "Comptable"
users.role.comptable.desc "Budget, engagements, notes de frais"
users.role.employee "Employé"
users.role.employee.desc "Libre-service uniquement"
users.role.manager "Manager (Chef de service)"
users.role.manager.desc "Approbations équipe"

18.10 Audit Trail

Key French Text
audit.title "Journal d'audit"
audit.filter.module "Module"
audit.filter.action "Action"
audit.filter.date "Période"
audit.action.create "Création"
audit.action.update "Modification"
audit.action.delete "Suppression"
audit.detail.title "Détail de l'audit"
audit.detail.action "Action"
audit.detail.entity "Entité"
audit.detail.by "Par"
audit.detail.date "Date"
audit.detail.changes "Modifications"
audit.detail.before "Avant"
audit.detail.after "Après"
audit.load_more "Charger plus…"

18.11 Multi-Tenant

Key French Text
tenant_switcher.title "Mes entreprises"
tenant_switcher.current "Entreprise active"
tenant_switcher.switching "Chargement de {name}…"
tenant_switcher.hint "Tapez sur une entreprise pour changer de contexte."

18.12 Empty States

Key French Text
empty.employees "Aucun employé pour le moment.\nAjoutez votre premier collaborateur !"
empty.employees.cta "Ajouter un employé"
empty.org_units "Votre structure organisationnelle est vide.\nCommencez par ajouter des départements."
empty.org_units.cta "Ajouter un département"
empty.positions "Aucun poste défini.\nLes postes seront créés automatiquement lorsque vous ajouterez des employés."
empty.users "Invitez vos collaborateurs pour qu'ils puissent accéder à Papillon."
empty.users.cta "Inviter un utilisateur"
empty.invoices "Aucune facture pour le moment."
empty.audit "Aucune activité enregistrée pour cette période."

18.13 Sync & Offline

Key French Text
sync.synced "Synchronisé"
sync.pending "{count} modification(s) en attente"
sync.syncing "Synchronisation en cours…"
sync.offline "Hors ligne"
sync.last_synced "Dernière sync : {time}"
sync.conflict.title "Conflit de synchronisation"
sync.conflict.description "L'élément « {name} » a été modifié sur un autre appareil."
sync.conflict.keep_mine "Garder ma version"
sync.conflict.keep_server "Garder la version serveur"
sync.conflict.your_version "Votre version"
sync.conflict.server_version "Version du serveur"

19. New Component Specifications

19.1 StepIndicator

Purpose: Shows progress through multi-step flows (registration).

  ●────────○────────○
Entreprise  Modules   Paiement
  (1/3)      (2/3)     (3/3)
Prop Type Default
steps { label: string }[] Required
currentStep number Required

States: - Completed step: --color-primary filled circle + solid line - Current step: --color-primary filled circle, pulsing ring - Future step: --color-border hollow circle + dashed line

Accessibility: aria-current="step" on current, aria-label="Étape {n} sur {total}: {label}"

19.2 ModuleCard

Purpose: Displays a module in selection / upsell contexts.

Prop Type Default
name string Required
description string Required
icon ReactNode Required
price string Required
available boolean true
selected boolean false
locked boolean false
comingSoonDate string \| null null
onSelect () => void

States: - Available, unselected: --color-bg-secondary bg, --color-border border - Available, selected: --color-primary-light bg, --color-primary border, checkmark - Locked: 60% opacity, lock icon, "Bientôt · {date}" badge - Disabled: not applicable (all cards are tappable)

19.3 TenantStatusBanner

Purpose: Persistent banner based on tenant status.

Prop Type Default
status TenantStatus Required
daysRemaining number \| null
ctaAction () => void
onDismiss (() => void) \| null null (non-dismissible)
isAdmin boolean false

Rendering: Full width, below top bar, sticky. Height auto. Max one visible.

19.4 OrgTreeNode

Purpose: Renders a node in the organisational tree.

Prop Type Default
unit OrgUnit Required
depth number 0
isExpanded boolean false
onToggle () => void
onSelect () => void
onAdd () => void

Icons by type: - ENTITY: 🏢 (building) - SITE: 📍 (pin) - DEPARTMENT: 🏛 (institution)

19.5 PositionCombobox

Purpose: Combined search + create input for position assignment.

Prop Type Default
positions Position[] Required
selectedId string \| null null
onSelect (position: Position) => void
onCreate (title: string) => void

Behavior: 1. User types → filter existing positions (debounced 200ms) 2. Matching positions shown in dropdown 3. If no match: show "{typed} — Ajouter comme nouveau poste" option 4. On create: triggers onCreate callback + adds to dropdown for future use

19.6 PriceSummaryBar (Sticky)

Purpose: Sticky bottom bar showing selection summary during module selection.

Prop Type Default
moduleCount number Required
totalPrice number Required
packName string \| null null
packPrice number \| null null
discountPercent number \| null null
onContinue () => void

Layout: Sticky to bottom, elevated (--shadow-lg), contains summary text + CTA button.

19.7 PaymentMethodSelector

Purpose: Radio-card selection for payment methods.

Prop Type Default
methods PaymentMethod[] Required
selected string \| null null
onSelect (method: string) => void
amount number Required

Each method is a card with: icon, title, subtitle, action button. Cards are radio-exclusive (select one).

19.8 ConflictResolver

Purpose: Displays side-by-side comparison for sync conflicts.

Prop Type Default
entityName string Required
localVersion Record<string, any> Required
serverVersion Record<string, any> Required
localTimestamp string Required
serverTimestamp string Required
serverAuthor string Required
onKeepLocal () => void
onKeepServer () => void

Layout: Two panels (stacked on mobile, side-by-side on desktop) showing differing fields highlighted.


20. Brand Compliance Checklist

Papillon HR Suite (Tenant-Facing Screens)

  • [x] Amber/gold primary color (#F59E0B) used throughout
  • [x] Mobile-first layout (360px designed first, all wireframes start mobile)
  • [x] Offline states specified for ALL write operations (Employee create, Org structure add, Position add)
  • [x] Touch targets 48px minimum (all buttons, checkboxes, nav items)
  • [x] French micro-copy warm and human ("Créez votre compte en 5 minutes", "Numéro en attente", "Tapez un nouveau poste…")
  • [x] Loading skeletons specified (not spinners — except payment processing)
  • [x] Generous whitespace — not crowded (single-column mobile forms, 16px padding)
  • [x] Celebration animation specified: welcome confetti on first login (from host shell), "✓" animations on employee create
  • [x] Auto-save on every field change (company settings, employee form draft)
  • [x] Undo for destructive actions (module deactivation: 10s undo toast)
  • [x] Sync status indicator specified (green/orange/blue/grey dots, "Dernière sync" timestamp)
  • [x] Error messages human-readable in French (never technical codes)
  • [x] Empty states with helpful illustrations and CTAs
  • [x] Progressive disclosure (escape hatch for positions, optional RCCM, hire date future = PRE_HIRE explained inline)

Admin Console (ALTARYS Operators)

  • [x] Navy/corporate color palette used (#1E3A5F primary, #2563EB accent)
  • [x] Desktop-only layout (1024px+ designed, no mobile wireframes)
  • [x] Information density appropriate for power users (data tables, KPI cards above fold)
  • [x] Batch operation flows specified (manual payment confirmation per-tenant)
  • [x] Keyboard shortcuts: not specified for MVP (V2 — admin console is low-frequency)
  • [x] Advanced filter/sort panels included (tenant list: status, segment, channel, date filters)
  • [x] Export to CSV specified (tenant list export button)
  • [x] Unverified data highlighted (orange background for is_verified=false rates)

End of document. This design covers all tenant-facing and operator-facing UI surfaces of the Control Plane module. Next steps: ARCHITECT produces docs/architecture/control-plane-arch.md, then PRODUCT_OWNER decomposes into stories.