diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index e1f490e..aea2bb5 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -227,7 +227,11 @@ export default function App() { } /> } /> } /> - } /> + {/* Assistant IA (26/09/26, demande Olivier) : n'est plus réservé au crowdlending — + visible et accessible aussi depuis l'espace Private Equity (cf. Layout.jsx, nav + "Assistant IA" sortie du bloc isCrowdlendingActive) ; ses outils MCP couvrent déjà + le PE (crowdlending_list_investissements_pe / crowdlending_get_investissement_pe). */} + } /> } /> } /> } /> diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index 2dc6531..5a61263 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -72,6 +72,12 @@ function ProjectSearch() { const navigate = useNavigate(); const location = useLocation(); const { activeId, activeView } = useInvestisseur(); + const { active: activeWorkspace } = useWorkspace() || {}; + // Bug corrige le 26/09/26 (demande Olivier) : la recherche globale doit toujours rester + // scopee a l'espace de travail affiche (crowdlending vs Private Equity), au lieu + // d'interroger systematiquement l'endpoint crowdlending. Meme critere que le pattern + // *Router() deja utilise ailleurs (cf. InvestissementDetailRouter, App.jsx). + const isPe = !!(activeWorkspace && activeWorkspace.type !== 'crowdlending'); const [query, setQuery] = useState(''); const [allInv, setAllInv] = useState([]); const [open, setOpen] = useState(false); @@ -83,10 +89,13 @@ function ProjectSearch() { const loadInv = useCallback(async () => { try { const scopeParams = activeView === 'all' ? { scope: 'all' } : {}; - const rows = await api.get('/investissements', scopeParams); - setAllInv(rows); + const endpoint = isPe ? '/investissements-pe' : '/investissements'; + const rows = await api.get(endpoint, scopeParams); + // Normalise les deux formes (crowdlending: nom_projet / PE: nom_deal) vers un champ + // commun "nom" pour eviter de dupliquer le filtre et le rendu ci-dessous. + setAllInv(rows.map(r => ({ ...r, nom: isPe ? r.nom_deal : r.nom_projet }))); } catch {} - }, [activeView]); + }, [activeView, isPe]); useEffect(() => { loadInv(); }, [loadInv, activeId]); @@ -115,7 +124,7 @@ function ProjectSearch() { const q = query.trim().toLowerCase(); if (!q) return []; return allInv - .filter(r => r.nom_projet?.toLowerCase().includes(q) || r.plateforme_nom?.toLowerCase().includes(q)) + .filter(r => r.nom?.toLowerCase().includes(q) || r.plateforme_nom?.toLowerCase().includes(q)) .slice(0, 8); })(); @@ -161,12 +170,23 @@ function ProjectSearch() { procedure: 'procédure', cloture: 'clôturé', }; + // Libellés des deals Private Equity (cf. STATUT_LABELS, InvestissementsPe.jsx) : statuts + // distincts du crowdlending, sauf 'cloture' partagé par les deux. + const STATUT_LABELS_PE = { + en_attente: 'en attente', + valide: 'validé', + cloture: 'clôturé', + perte_definitive: 'perte définitive', + }; + const statutLabels = isPe ? STATUT_LABELS_PE : STATUT_LABELS; const statutColor = (s) => { - if (s === 'en_cours') return 'var(--b-en_cours-fg)'; - if (s === 'rembourse') return 'var(--b-rembourse-fg)'; - if (s === 'en_retard') return 'var(--b-en_retard-fg)'; - if (s === 'procedure') return 'var(--b-procedure-fg)'; + if (s === 'en_cours') return 'var(--b-en_cours-fg)'; + if (s === 'rembourse') return 'var(--b-rembourse-fg)'; + if (s === 'en_retard') return 'var(--b-en_retard-fg)'; + if (s === 'procedure') return 'var(--b-procedure-fg)'; + if (s === 'cloture') return 'var(--b-cloture-fg)'; + if (s === 'perte_definitive') return 'var(--b-perte_definitive-fg)'; return 'var(--text-muted)'; }; @@ -208,11 +228,11 @@ function ProjectSearch() { onMouseDown={() => goTo(inv)} onMouseEnter={() => setActiveIdx(i)} > -
{inv.nom_projet}
+
{inv.nom}
{inv.plateforme_nom} · - {STATUT_LABELS[inv.statut] ?? inv.statut?.replace('_', ' ')} + {statutLabels[inv.statut] ?? inv.statut?.replace('_', ' ')} {inv.montant_investi != null && ( <> · @@ -371,20 +391,20 @@ export default function Layout() { {/* Fiscalité (20/09/26, chantier "Fiscalité PE") a désormais son équivalent PE (TaxReportPe.jsx, TaxReportRouter dans App.jsx) — sortie du bloc isCrowdlendingActive pour devenir visible quel que soit le workspace actif, même principe que - Plateformes/Investissements/Dépôts-Retraits/Remboursements ci-dessus. Assistant IA - reste, lui, réservé au crowdlending (aucun équivalent PE, cf. RequireWorkspace sur - sa route dans App.jsx). */} + Plateformes/Investissements/Dépôts-Retraits/Remboursements ci-dessus. */} Fiscalité - {isCrowdlendingActive && ( - <> - {aiEnabled && ( - - Assistant IA - - )} - + {/* Assistant IA (26/09/26, demande Olivier : absent de l'espace "Private Equity") — + même principe que les liens ci-dessus, sorti du bloc isCrowdlendingActive pour + rester visible (toujours en dernière position) quel que soit le workspace actif ; + ses outils MCP couvrent déjà le PE (crowdlending_list_investissements_pe / + crowdlending_get_investissement_pe, cf. mcp-server/tools.js) — cf. suppression du + RequireWorkspace correspondant sur la route "assistant-ia" dans App.jsx. */} + {aiEnabled && ( + + Assistant IA + )}