Levée communautaire (mobile investisseur)¶
Documentation du parcours levée de fonds communautaire 2026 dans front-mobile-app : feature flags, routing V1/V2, data layer partagée, progression en polling, modales d'intention et d'achat (wallet, Checkout, PEA-PME).
Contrat API : module company-internal-fundraising.
Feature flags et bascule V1 / V2¶
| Switch | Où | Effet |
|---|---|---|
DISPLAY_COMPANY_FUNDRAISING |
API feature flags → FeatureFlagsProvider |
Coupe toute la levée côté app (home, provider, polls, route /fundraising). |
FUNDRAISING_V2_ENABLED |
featureSwitch.ts (const compile-time) |
true → écran et modales V2 ; false → module legacy fundraising (V1). |
La route fundraising.tsx exporte withUnmountUnfocusedScreen(FUNDRAISING_V2_ENABLED ? FundraisingV2Screen : FundraisingScreen).
Architecture modules¶
fundraising— data layer : hooks React Query (useCurrentCompanyFundraisingCampaign, intentions, achats wallet), types, utils (getCampaignState,applyRaisedAmountToCurrentCampaign), modales V1, écran V1, provider global.fundraising-v2— UI « Levée 2026 » : page présentation (FundraisingV2Screen), dock, sections scroll, cartes d'entrée home (CampaignSnippetCard), modalesFundraisingV2IntentionModaletFundraisingV2PurchaseModal(dont flux PEA-PME dédié).
Ne pas dupliquer les appels API dans V2 : réutiliser les services du module fundraising.
Provider global¶
FundraisingCampaignProvider (layout authentifié) :
- Fetch campagne courante + horloge locale (
useFundraisingCampaignClock). - Lance le poll
raised-amountviauseCurrentCompanyFundraisingRaisedAmount. - Deep link
?invest-fundraising=true→ ouvre la modale d'achat (V1 ou V2 selonFUNDRAISING_V2_ENABLED) si le flag display est actif et droits KYC OK. - Explainer V1 : modale
FundraisingExplainerModalau premier passage sur une campagne ouverte non investie — désactivée quand V2 est actif (pas de pré-modale explainer en V2).
Progression : polling, pas de SSE¶
La barre de progression et les compteurs investisseurs ne passent pas par Server-Sent Events. Le front appelle :
GET /customers/company-internal-fundraising/campaigns/current/raised-amount
Hook : useCurrentCompanyFundraisingRaisedAmount.ts.
| Condition campagne | Intervalle |
|---|---|
isOpen ou earlyAccess.hasStarted |
3 s (OPEN_RAISED_AMOUNT_POLL_INTERVAL_MS) |
| Campagne planifiée (progression « live » mais pas encore ouverte) | 10 s (SCHEDULED_RAISED_AMOUNT_POLL_INTERVAL_MS) |
Campagne clôturée (isClosed) |
Poll désactivé (isCampaignProgressLive = false) |
Chaque réponse valide patche le cache GET …/campaigns/current via applyRaisedAmountToCurrentCampaign (alignement lifecycleStatus, montants, passage scheduled → open → closed). Erreurs poll : silencieuses (showErrorNotification: false).
Entrées utilisateur¶
| Entrée | Comportement |
|---|---|
| Home — carousel projets | Si flag display + campagne en cache : CampaignSnippetCard en tête de liste → router.navigate('/(authenticated)/fundraising'). |
Route /fundraising |
Présentation V2 ou wizard V1 selon le switch. |
Query invest-fundraising=true |
Ouvre modale achat (provider). |
| Actionnariat | ShareholdingScreen — gated par le même flag display. |
Modale intention (V2)¶
FundraisingV2IntentionModal — intention déclarative avant ouverture officielle :
- Montant : multiple de 10 € ; le champ peut être vidé (RHF : ne pas repasser par
undefinedseul au clear — voirIntentionAmountStep). - Suppression d'intention : action dans le corps de la modale (pas dans le header).
- Écriture API :
PUT|DELETE …/declarative-intention(voir doc API).
Modale achat (V2)¶
- Wallet : quote + confirm partagés avec V1 (
useBricksTotalBalance), Checkout si money-in requis ; après succès Checkout, le front enchaîne le confirm (pas un second quote). - PEA-PME : chemin séparé
usePeaPmePurchase→POST …/purchase/pea-pme(pas de quote, pas de WT). Compte individual uniquement. Référence virementBRICKS-PEA-XXXXXX; bannière / modale dossier PEA sur la page présentation si intentionwaitingouconfirmed. - Erreur
pea-pme-already-exists(409) : affichage succès avec dossier existant (autre appareil / cache stale).
États campagne (UI)¶
Utilitaires : campaignVisibility.ts.
getCampaignState:future|ongoing|closed(combineisOpen,isClosed,isNewInvestmentAllowed).- Cartes home et dock V2 s'appuient sur
earlyAccess,isOpen, montants pollés et intention déclarative.
Fichiers clés¶
| Rôle | Chemin |
|---|---|
| Query keys | src/modules/fundraising/services/queryKeys.ts |
| Campagne courante | useCurrentCompanyFundraisingCampaign.ts |
| Poll progression | useCurrentCompanyFundraisingRaisedAmount.ts |
| Patch cache poll | utils/applyRaisedAmountToCurrentCampaign.ts |
| Écran V2 | fundraising-v2/screens/FundraisingV2Screen/ |
| Switch V2 | fundraising-v2/featureSwitch.ts |
Pièges courants¶
- Modifier V2 sans toucher les hooks
fundraising/services→ risque de double fetch ou clés query incohérentes. - Confondre
isOpen(GET current) etlifecycleStatusdu poll : pendant l'avant-première, le poll peut êtrescheduledalors que le front patche quand même les montants confirmés. - Oublier
DISPLAY_COMPANY_FUNDRAISING: l'UI disparaît mais les query keys peuvent rester documentées côté tests — toujours gateenabledsur les hooks. - PEA-PME : ne pas appeler le quote wallet (plafond money-in incompatible avec les montants PEA min).