Aller au contenu

Story CP-021: Module Gating Frontend: Navigation + Upsell Cards

Module: control-plane Slice: Slice 7c from architecture (split from CP-007) Brand context: Papillon HR Suite (upsell display is Papillon-only) Priority: 7 (after CP-020) Depends on: CP-020 Estimated complexity: M


Objective

Implement the frontend module gating experience: locked modules appear in the navigation with distinct styling, and tapping them shows an upsell card. Admins see a subscribe button; employees see a "contact your admin" message. This slice consumes the module catalog API from CP-020 and the module gating backend from CP-007.


Backend Scope

No new backend work in this slice. Consumes: - GET /api/v1/tenant/modules (from CP-007) — tenant's module statuses - GET /api/v1/tenant/modules/catalog (from CP-020) — full catalog with pricing


Frontend Scope

Pages & Routes

  • No dedicated page. Module gating manifests as:
  • Navigation items (locked modules in sidebar/bottom nav)
  • Upsell cards (when locked module is tapped)

Components

  • ModuleCard.tsx — Component spec in design §19.2. Props: name, description, icon, price, available, selected, locked, comingSoonDate, onSelect.
  • ModuleUpsellSheet.tsx — Bottom sheet (mobile) / popover (desktop) with module description, feature list, and subscribe CTA.
  • Navigation integration: modify sidebar/bottom nav to show locked modules with styling.

Module descriptions are hardcoded per module (not DB-driven for MVP). Each module has: name, icon, one-line description, feature bullet list, starting price.

UI States (ALL REQUIRED)

Module Upsell Card:

State Behavior French Copy
Loading Skeleton card
Available, unselected White bg, standard border
Available, selected Primary-light bg, primary border, checkmark
Locked (released) 60% opacity, lock icon Module description + "Souscrire" (admin) or "Contactez votre administrateur pour activer ce module." (employee)
Locked (coming soon) 60% opacity, sparkle badge "Bientot . {date}"
Error Toast "Une erreur est survenue."

Responsive Behavior

  • 360px (mobile): Locked modules in "Plus" bottom sheet with lock icon. Tap → upsell bottom sheet.
  • 1024px+ (desktop): Locked modules in sidebar with 50% opacity and lock icon. Click → upsell popover from sidebar.

Interactions

  • Admin taps locked module: Shows upsell card with "Souscrire ce module" button → navigates to billing (CP-009 subscription management).
  • Employee taps locked module: Shows upsell card with "Contactez votre administrateur pour activer ce module." text (no button).

French micro-copy for upsell:

Key French Text
modules.subscribe "Souscrire"
modules.subscribe_cta "Souscrire ce module"
modules.contact_admin "Contactez votre administrateur pour activer ce module."
modules.coming_soon "Bientot . {date}"
modules.error "Une erreur est survenue."

Acceptance Criteria

AC-057: Navigation shows locked modules
Given my tenant has ABSMGT=ACTIVE and PAYROL=INACTIVE
When I view the sidebar navigation
Then ABSMGT appears with full color and is clickable
And PAYROL appears at 50% opacity with lock icon

AC-058: Upsell card for admin
Given I am DG and tap a locked module
When the upsell card appears
Then I see the module description, feature list, price
And a "Souscrire ce module" button

AC-059: Upsell card for employee
Given I am EMPLOYE and tap a locked module
When the upsell card appears
Then I see the module description
And the text "Contactez votre administrateur pour activer ce module."
And no subscribe button

OHADA & Regulatory Rules

  • No direct OHADA regulatory requirements for module gating UI.

Standards & Conventions

  • docs/standards/react-typescript-guidelines.md — §Navigation integration, §Bottom sheet pattern, §Component props typing
  • docs/design/control-plane-design.md — §19.2 ModuleCard, §Module upsell

Testing Requirements

Unit Tests

  • ModuleCard: renders correctly for each state (available, selected, locked, coming soon)
  • ModuleUpsellSheet: shows subscribe button for admin role
  • ModuleUpsellSheet: shows contact admin text for employee role (no button)
  • Navigation: locked modules rendered with opacity + lock icon

Integration Tests

  • Navigation fetches module catalog and renders active/locked modules correctly
  • Upsell card content matches hardcoded module metadata

What QA Will Validate

  • Locked modules visible in navigation with correct styling (50% opacity, lock icon)
  • Upsell card shows correct content for admin vs employee
  • Mobile: bottom sheet upsell behavior
  • Desktop: popover upsell behavior
  • Admin subscribe button navigates to billing (CP-009)

Out of Scope

  • Module activation/deactivation UI — CP-009 (Billing/Subscription management)
  • Per-module suspension display — V2
  • Admin module override — CP-012

Definition of Done

  • [ ] All backend endpoints implemented and returning correct responses — N/A (frontend-only)
  • [ ] All frontend pages render correctly at 360px, 768px, 1024px
  • [ ] All 5 UI states implemented (loading, empty, error, offline, success)
  • [ ] French micro-copy matches design spec exactly
  • [ ] All acceptance criteria pass manually
  • [ ] Unit tests written and passing
  • [ ] Integration tests written and passing
  • [ ] Multi-tenant isolation verified — N/A (frontend reads tenant-scoped API)
  • [ ] Offline write+sync works (Papillon) — module catalog cached for offline read
  • [ ] No TypeScript any — all types explicit
  • [ ] No Java raw types — N/A (frontend-only)
  • [ ] API responses follow standard envelope format — N/A (consumer only)
  • [ ] Audit trail entries created for every data mutation — N/A (no mutations)