Améliorations private equity

This commit is contained in:
ocroguennec committed 2026-09-26 16:37:40 +02:00
1 parent e8e3ca34cc
commit f2bdf29b16
2 files changed
+38 -14

No files matched your search

+5 -1
View File
@@ -227,7 +227,11 @@ export default function App() {
<Route path="frais" element={<FraisRouter />} /> <Route path="frais" element={<FraisRouter />} />
<Route path="simul" element={<RequireWorkspace type="crowdlending"><SimulRemboursements /></RequireWorkspace>} /> <Route path="simul" element={<RequireWorkspace type="crowdlending"><SimulRemboursements /></RequireWorkspace>} />
<Route path="taxreport" element={<TaxReportRouter />} /> <Route path="taxreport" element={<TaxReportRouter />} />
<Route path="assistant-ia" element={<RequireWorkspace type="crowdlending"><AssistantIA /></RequireWorkspace>} /> {/* 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). */}
<Route path="assistant-ia" element={<AssistantIA />} />
<Route path="2778-sd" element={<Navigate to="/taxreport" replace />} /> <Route path="2778-sd" element={<Navigate to="/taxreport" replace />} />
<Route path="imports" element={<Navigate to="/settings?section=imports" replace />} /> <Route path="imports" element={<Navigate to="/settings?section=imports" replace />} />
<Route path="settings" element={<Settings />} /> <Route path="settings" element={<Settings />} />
+33 -13
View File
@@ -72,6 +72,12 @@ function ProjectSearch() {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const { activeId, activeView } = useInvestisseur(); 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 [query, setQuery] = useState('');
const [allInv, setAllInv] = useState([]); const [allInv, setAllInv] = useState([]);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@@ -83,10 +89,13 @@ function ProjectSearch() {
const loadInv = useCallback(async () => { const loadInv = useCallback(async () => {
try { try {
const scopeParams = activeView === 'all' ? { scope: 'all' } : {}; const scopeParams = activeView === 'all' ? { scope: 'all' } : {};
const rows = await api.get('/investissements', scopeParams); const endpoint = isPe ? '/investissements-pe' : '/investissements';
setAllInv(rows); 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 {} } catch {}
}, [activeView]); }, [activeView, isPe]);
useEffect(() => { loadInv(); }, [loadInv, activeId]); useEffect(() => { loadInv(); }, [loadInv, activeId]);
@@ -115,7 +124,7 @@ function ProjectSearch() {
const q = query.trim().toLowerCase(); const q = query.trim().toLowerCase();
if (!q) return []; if (!q) return [];
return allInv 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); .slice(0, 8);
})(); })();
@@ -161,12 +170,23 @@ function ProjectSearch() {
procedure: 'procédure', procedure: 'procédure',
cloture: 'clôturé', 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) => { const statutColor = (s) => {
if (s === 'en_cours') return 'var(--b-en_cours-fg)'; if (s === 'en_cours') return 'var(--b-en_cours-fg)';
if (s === 'rembourse') return 'var(--b-rembourse-fg)'; if (s === 'rembourse') return 'var(--b-rembourse-fg)';
if (s === 'en_retard') return 'var(--b-en_retard-fg)'; if (s === 'en_retard') return 'var(--b-en_retard-fg)';
if (s === 'procedure') return 'var(--b-procedure-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)'; return 'var(--text-muted)';
}; };
@@ -208,11 +228,11 @@ function ProjectSearch() {
onMouseDown={() => goTo(inv)} onMouseDown={() => goTo(inv)}
onMouseEnter={() => setActiveIdx(i)} onMouseEnter={() => setActiveIdx(i)}
> >
<div className="project-search-item-name">{inv.nom_projet}</div> <div className="project-search-item-name">{inv.nom}</div>
<div className="project-search-item-meta"> <div className="project-search-item-meta">
<span>{inv.plateforme_nom}</span> <span>{inv.plateforme_nom}</span>
<span>·</span> <span>·</span>
<span style={{ color: statutColor(inv.statut) }}>{STATUT_LABELS[inv.statut] ?? inv.statut?.replace('_', ' ')}</span> <span style={{ color: statutColor(inv.statut) }}>{statutLabels[inv.statut] ?? inv.statut?.replace('_', ' ')}</span>
{inv.montant_investi != null && ( {inv.montant_investi != null && (
<> <>
<span>·</span> <span>·</span>
@@ -371,21 +391,21 @@ export default function Layout() {
{/* Fiscalité (20/09/26, chantier "Fiscalité PE") a désormais son équivalent PE {/* Fiscalité (20/09/26, chantier "Fiscalité PE") a désormais son équivalent PE
(TaxReportPe.jsx, TaxReportRouter dans App.jsx) — sortie du bloc isCrowdlendingActive (TaxReportPe.jsx, TaxReportRouter dans App.jsx) — sortie du bloc isCrowdlendingActive
pour devenir visible quel que soit le workspace actif, même principe que pour devenir visible quel que soit le workspace actif, même principe que
Plateformes/Investissements/Dépôts-Retraits/Remboursements ci-dessus. Assistant IA Plateformes/Investissements/Dépôts-Retraits/Remboursements ci-dessus. */}
reste, lui, réservé au crowdlending (aucun équivalent PE, cf. RequireWorkspace sur
sa route dans App.jsx). */}
<NavLink to="/taxreport" title="Fiscalité"> <NavLink to="/taxreport" title="Fiscalité">
<NavIcon libFilename={navIcons.tax} Fallback={IconFlatTax} /><span className="nav-label">Fiscalité</span> <NavIcon libFilename={navIcons.tax} Fallback={IconFlatTax} /><span className="nav-label">Fiscalité</span>
</NavLink> </NavLink>
{isCrowdlendingActive && ( {/* 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 && ( {aiEnabled && (
<NavLink to="/assistant-ia" title="Assistant IA"> <NavLink to="/assistant-ia" title="Assistant IA">
<NavIcon libFilename={navIcons.assistantIa} Fallback={IconAssistantIa} /><span className="nav-label">Assistant IA</span> <NavIcon libFilename={navIcons.assistantIa} Fallback={IconAssistantIa} /><span className="nav-label">Assistant IA</span>
</NavLink> </NavLink>
)} )}
</>
)}
</nav> </nav>