From eb961cbed42041ad0d895a979998862770891b79 Mon Sep 17 00:00:00 2001 From: Olivier Date: Wed, 17 Jun 2026 22:45:08 +0200 Subject: [PATCH] Correction des redirections --- frontend/src/components/InvMensuelTable.jsx | 4 +- frontend/src/components/Layout.jsx | 21 ++++++++- frontend/src/pages/Imports.jsx | 5 ++- frontend/src/pages/InvestissementDetail.jsx | 11 +++-- frontend/src/pages/Investissements.jsx | 44 ++++++++++++++----- frontend/src/pages/Plateformes.jsx | 16 ++++--- .../src/pages/settings/ImportsSection.jsx | 5 ++- 7 files changed, 80 insertions(+), 26 deletions(-) diff --git a/frontend/src/components/InvMensuelTable.jsx b/frontend/src/components/InvMensuelTable.jsx index b897316..c1a50c7 100644 --- a/frontend/src/components/InvMensuelTable.jsx +++ b/frontend/src/components/InvMensuelTable.jsx @@ -27,7 +27,7 @@ const STATUT_FG = { cloture: 'var(--text-muted)', }; -export default function InvMensuelTable({ rows, allRembs, allReinvests, year }) { +export default function InvMensuelTable({ rows, allRembs, allReinvests, year, originFrom }) { const navigate = useNavigate(); const currentYear = new Date().getFullYear(); const currentMonth = new Date().getMonth() + 1; @@ -142,7 +142,7 @@ export default function InvMensuelTable({ rows, allRembs, allReinvests, year }) {grid.map(({ inv, months }) => ( navigate(`/investissements/${inv.id}`)}> + onClick={() => navigate(`/investissements/${inv.id}`, originFrom ? { state: { from: originFrom } } : undefined)}> {inv.nom_projet || '—'} diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index 39ea429..537394b 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useRef, useState } from 'react'; -import { NavLink, Outlet, useNavigate } from 'react-router-dom'; +import { NavLink, Outlet, useLocation, useNavigate } from 'react-router-dom'; import { api } from '../api.js'; import { useInvestisseur } from '../context/InvestisseurContext.jsx'; import { useUi } from '../context/UiContext.jsx'; @@ -64,6 +64,7 @@ const IconPanelExpand = () => ( /* ── Recherche rapide de projet ─────────────────────────────── */ function ProjectSearch() { const navigate = useNavigate(); + const location = useLocation(); const { activeId, activeView } = useInvestisseur(); const [query, setQuery] = useState(''); const [allInv, setAllInv] = useState([]); @@ -118,9 +119,25 @@ function ProjectSearch() { setActiveIdx(-1); }, [results.length, query]); /* eslint-disable-line */ + const PAGE_LABELS = { + '/': 'Tableau de bord', + '/investissements': 'Investissements', + '/remboursements': 'Remboursements', + '/depots-retraits': 'Dépôts / Retraits', + '/2778-sd': 'Fiscalité', + '/plateformes': 'Plateformes', + '/taxreport': 'Fiscalité', + '/settings': 'Paramètres', + '/compte': 'Mon compte', + '/admin': 'Administration', + }; + const currentLabel = PAGE_LABELS[location.pathname] ?? 'Recherche'; + const goTo = (inv) => { setQuery(''); setOpen(false); - navigate(`/investissements/${inv.id}`); + navigate(`/investissements/${inv.id}`, { + state: { from: { path: location.pathname, search: location.search, label: currentLabel } }, + }); }; const handleKeyDown = (e) => { diff --git a/frontend/src/pages/Imports.jsx b/frontend/src/pages/Imports.jsx index 2e9d9d3..06b51f8 100644 --- a/frontend/src/pages/Imports.jsx +++ b/frontend/src/pages/Imports.jsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { api } from '../api.js'; import { useInvestisseur } from '../context/InvestisseurContext.jsx'; import { fmtDate } from '../utils/format.js'; @@ -52,6 +52,7 @@ const MODULE_LABEL = { export default function Imports() { const { activeId } = useInvestisseur(); const navigate = useNavigate(); + const location = useLocation(); // ── Import classique (xlsx/csv/json) ────────────────────────── const [module, setModule] = useState('depots_retraits'); @@ -444,7 +445,7 @@ function DossierImport({ {' '} diff --git a/frontend/src/pages/InvestissementDetail.jsx b/frontend/src/pages/InvestissementDetail.jsx index cc05da0..b0b1b68 100644 --- a/frontend/src/pages/InvestissementDetail.jsx +++ b/frontend/src/pages/InvestissementDetail.jsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react'; -import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; +import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { api } from '../api.js'; import { useInvestisseur } from '../context/InvestisseurContext.jsx'; import { useUi } from '../context/UiContext.jsx'; @@ -103,6 +103,8 @@ function xirr(cashflows) { export default function InvestissementDetail() { const { id } = useParams(); const navigate = useNavigate(); + const location = useLocation(); + const navOrigin = location.state?.from ?? null; const [searchParams, setSearchParams] = useSearchParams(); const { activeId, investisseurs } = useInvestisseur(); const { displayMode } = useUi(); @@ -806,8 +808,11 @@ export default function InvestissementDetail() { · {inv.nom_projet} - diff --git a/frontend/src/pages/Investissements.jsx b/frontend/src/pages/Investissements.jsx index 378f6a7..dd52008 100644 --- a/frontend/src/pages/Investissements.jsx +++ b/frontend/src/pages/Investissements.jsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react'; import { usePagination } from '../hooks/usePagination.js'; import Pagination from '../components/Pagination.jsx'; import PageIcon from '../components/PageIcon.jsx'; -import { useLocation, useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; import { api } from '../api.js'; import InvSelect from '../components/InvSelect.jsx'; import { useInvestisseur } from '../context/InvestisseurContext.jsx'; @@ -275,8 +275,9 @@ function dayOfMonth(isoDate) { export default function Investissements() { const { activeId, activeView, investisseurs } = useInvestisseur(); const { displayMode } = useUi(); - const { search } = useLocation(); + const location = useLocation(); const navigate = useNavigate(); + const [searchParams, setSearchParams] = useSearchParams(); const platsRef = useRef([]); const lastValidSouscriptionRef = useRef(''); @@ -286,12 +287,35 @@ export default function Investissements() { const [plats, setPlats] = useState([]); const [comptesCourants, setComptesCourants] = useState([]); const [comptesInvestisseur, setComptesInvestisseur] = useState([]); - const [activeTab, setActiveTab] = useState('plateformes'); + /* activeTab, filter, platYear → URL params pour survivre au retour arrière */ + const activeTab = searchParams.get('tab') || 'plateformes'; + const setActiveTab = (tab) => setSearchParams(p => { const n = new URLSearchParams(p); n.set('tab', tab); return n; }, { replace: true }); const [listFocused, setListFocused] = useState(false); - const [filter, setFilter] = useState({ statut: '', plateforme_id: '', categorie_inv_id: '', secteur_inv_id: '', year: '', month: '' }); + const filter = { + statut: searchParams.get('statut') || '', + plateforme_id: searchParams.get('pid') || '', + categorie_inv_id: searchParams.get('cat') || '', + secteur_inv_id: searchParams.get('sect') || '', + year: searchParams.get('yr') || '', + month: searchParams.get('mo') || '', + }; + const setFilter = (updater) => setSearchParams(p => { + const cur = { statut: p.get('statut')||'', plateforme_id: p.get('pid')||'', categorie_inv_id: p.get('cat')||'', secteur_inv_id: p.get('sect')||'', year: p.get('yr')||'', month: p.get('mo')||'' }; + const nf = typeof updater === 'function' ? updater(cur) : updater; + const n = new URLSearchParams(p); + ['statut','pid','cat','sect','yr','mo'].forEach(k => n.delete(k)); + if (nf.statut) n.set('statut', nf.statut); + if (nf.plateforme_id) n.set('pid', nf.plateforme_id); + if (nf.categorie_inv_id) n.set('cat', nf.categorie_inv_id); + if (nf.secteur_inv_id) n.set('sect', nf.secteur_inv_id); + if (nf.year) n.set('yr', nf.year); + if (nf.month) n.set('mo', nf.month); + return n; + }, { replace: true }); const [categoriesInv, setCategoriesInv] = useState([]); const [secteursInv, setSecteursInv] = useState([]); - const [platYear, setPlatYear] = useState(String(new Date().getFullYear())); + const platYear = searchParams.get('platYear') || String(new Date().getFullYear()); + const setPlatYear = (y) => setSearchParams(p => { const n = new URLSearchParams(p); n.set('platYear', y); return n; }, { replace: true }); const [modalOpen, setModalOpen] = useState(false); const [editingId, setEditingId] = useState(null); const [form, setForm] = useState(empty); @@ -605,8 +629,8 @@ export default function Investissements() { /* ── Ouverture auto depuis le bouton global ── */ const pendingNew = useRef(false); useEffect(() => { - if (new URLSearchParams(search).get('new') !== '1') return; - navigate('/investissements', { replace: true }); + if (searchParams.get('new') !== '1') return; + navigate({ pathname: '/investissements', search: (() => { const n = new URLSearchParams(searchParams); n.delete('new'); return n.toString() ? '?' + n.toString() : ''; })() }, { replace: true }); if (plats.length > 0) { setEditingId(null); setForm({ ...empty }); @@ -615,7 +639,7 @@ export default function Investissements() { } else { pendingNew.current = true; } - }, [search]); /* eslint-disable-next-line */ + }, [searchParams]); /* eslint-disable-next-line */ useEffect(() => { if (!pendingNew.current || !plats.length) return; @@ -746,7 +770,7 @@ export default function Investissements() { const hasFilter = !!(filter.statut || filter.plateforme_id || filter.categorie_inv_id || filter.secteur_inv_id || filter.year || filter.month); const netMode = displayMode === 'net'; - const clearFilter = () => setFilter({ statut: '', plateforme_id: '', categorie_inv_id: '', secteur_inv_id: '', year: '', month: '' }); + const clearFilter = () => setSearchParams(p => { const n = new URLSearchParams(p); ['statut','pid','cat','sect','yr','mo'].forEach(k => n.delete(k)); return n; }, { replace: true }); const multiDetenteur = new Set(plats.map(p => p.investisseur_id)).size > 1; if (!loading && plats.length === 0) return ( @@ -1186,7 +1210,7 @@ export default function Investissements() { const capRestant = Math.max(0, capInv - (r.capital_rembourse || 0)); return ( navigate(`/investissements/${r.id}`)} + onClick={() => navigate(`/investissements/${r.id}`, { state: { from: { path: '/investissements', search: location.search, label: 'Investissements' } } })} style={{ cursor: 'pointer' }} onMouseEnter={e => e.currentTarget.style.opacity = '0.8'} onMouseLeave={e => e.currentTarget.style.opacity = '1'} diff --git a/frontend/src/pages/Plateformes.jsx b/frontend/src/pages/Plateformes.jsx index b287d3f..bab1098 100644 --- a/frontend/src/pages/Plateformes.jsx +++ b/frontend/src/pages/Plateformes.jsx @@ -1,5 +1,5 @@ import { Fragment, useEffect, useMemo, useRef, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; import { api } from '../api.js'; import { useInvestisseur } from '../context/InvestisseurContext.jsx'; import { useUi } from '../context/UiContext.jsx'; @@ -272,6 +272,8 @@ export default function Plateformes() { const { activeId, activeView, investisseurs } = useInvestisseur(); const { displayMode, chartInterets, chartCapital, chartCashback } = useUi(); const navigate = useNavigate(); + const location = useLocation(); + const [searchParams, setSearchParams] = useSearchParams(); /* ── État données ── */ const [allRows, setAllRows] = useState([]); @@ -283,7 +285,9 @@ export default function Plateformes() { const [loading, setLoading] = useState(false); /* ── État sélecteurs ── */ - const [selectedPlatName, setSelectedPlatName] = useState(null); + /* selectedPlatName et activeTab sont dans l'URL pour survivre au retour arrière */ + const selectedPlatName = searchParams.get('plat') || null; + const setSelectedPlatName = (nom) => setSearchParams(p => { const n = new URLSearchParams(p); n.set('plat', nom); return n; }, { replace: true }); const [selectedDetenteurId, setSelectedDetenteurId] = useState('all'); const [selectedYear, setSelectedYear] = useState(String(new Date().getFullYear())); const [windowStart, setWindowStart] = useState(0); @@ -320,7 +324,8 @@ export default function Plateformes() { const [pfuRates, setPfuRates] = useState([]); /* ── État UI ── */ - const [activeTab, setActiveTab] = useState('depots-retraits'); + const activeTab = searchParams.get('tab') || 'depots-retraits'; + const setActiveTab = (tab) => setSearchParams(p => { const n = new URLSearchParams(p); n.set('tab', tab); return n; }, { replace: true }); const [listFocused, setListFocused] = useState(false); /* ── Chargement ── */ @@ -1020,7 +1025,7 @@ export default function Plateformes() { const rowTotal = months.reduce((s, v) => s + (v?.value ?? 0), 0); return ( navigate(`/investissements/${inv.id}`)}> + onClick={() => navigate(`/investissements/${inv.id}`, { state: { from: { path: location.pathname, search: location.search, label: 'Plateformes' } } })}> {inv.nom_projet || '—'} @@ -1423,6 +1428,7 @@ export default function Plateformes() { allRembs={allRembs} allReinvests={allReinvests} year={selectedYear} + originFrom={{ path: location.pathname, search: location.search, label: 'Plateformes' }} /> @@ -1473,7 +1479,7 @@ export default function Plateformes() { : (rembParInv[r.id]?.interets_bruts || 0); return ( navigate(`/investissements/${r.id}`)}> + onClick={() => navigate(`/investissements/${r.id}`, { state: { from: { path: location.pathname, search: location.search, label: 'Plateformes' } } })}> {r.nom_projet} {r.emetteur || '—'} {fmtDate(r.date_souscription)} diff --git a/frontend/src/pages/settings/ImportsSection.jsx b/frontend/src/pages/settings/ImportsSection.jsx index 79f13e2..c883d1b 100644 --- a/frontend/src/pages/settings/ImportsSection.jsx +++ b/frontend/src/pages/settings/ImportsSection.jsx @@ -1,5 +1,5 @@ import { useState, useEffect, useRef } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { api } from '../../api.js'; import { fmtDate } from '../../utils/format.js'; import { useInvestisseur } from '../../context/InvestisseurContext.jsx'; @@ -239,7 +239,7 @@ function DossierImport({ {' '} @@ -253,6 +253,7 @@ function DossierImport({ export default function ImportsSection() { const { activeId } = useInvestisseur(); const navigate = useNavigate(); + const location = useLocation(); const [module, setModule] = useState('depots_retraits'); const [file, setFile] = useState(null);