Correction de l'affichage en tant que mono détenteur

This commit is contained in:
2026-07-04 18:32:51 +02:00
parent 69d006d358
commit 11790c63fe
6 changed files with 109 additions and 37 deletions
@@ -132,6 +132,8 @@ export default function ComptesSection() {
});
};
const multiDetenteur = investisseurs.length > 1;
return (
<>
<div className="card">
@@ -154,7 +156,7 @@ export default function ComptesSection() {
<tr>
<th>Nom</th>
<th style={{ width: '14%' }}>Type</th>
<th style={{ width: '22%' }}>Détenteur</th>
{multiDetenteur && <th style={{ width: '22%' }}>Détenteur</th>}
<th style={{ width: '16%' }}>Banque</th>
<th style={{ width: '10%' }}>Exonération</th>
<th style={{ width: 80 }} />
@@ -162,7 +164,7 @@ export default function ComptesSection() {
</thead>
<tbody>
{comptes.length === 0 && (
<tr><td colSpan={6} className="text-muted" style={{ textAlign: 'center', fontStyle: 'italic' }}>
<tr><td colSpan={multiDetenteur ? 6 : 5} className="text-muted" style={{ textAlign: 'center', fontStyle: 'italic' }}>
Aucun compte défini.
</td></tr>
)}
@@ -172,7 +174,7 @@ export default function ComptesSection() {
<tr key={c.id}>
<td style={{ fontWeight: 500 }}>{c.nom}</td>
<td><span className="badge">{TYPE_COMPTE_LABELS[c.type] ?? c.type}</span></td>
<td>{inv ? memberLabel(inv) : <span className="text-muted"></span>}</td>
{multiDetenteur && <td>{inv ? memberLabel(inv) : <span className="text-muted"></span>}</td>}
<td>{c.banque || <span className="text-muted"></span>}</td>
<td>
{c.exoneration_fiscale && c.exoneration_fiscale !== 'aucune' ? (
@@ -17,6 +17,12 @@ function dlBlob(content, filename, type) {
URL.revokeObjectURL(url);
}
/** Date du jour au format YYYY-MM-DD, en heure locale (ne pas utiliser toISOString ici, décale d'un jour selon le fuseau). */
function localToday() {
const d = new Date();
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}
const countryLabel = code => COUNTRIES.find(c => c.code === code)?.name ?? code ?? '—';
const FISCALITE_LABELS = {
flat_tax: 'Flat Tax',
@@ -283,6 +289,13 @@ function PlatDetailPanel({ plat, onEdit }) {
function PlatPickerModal({ open, onClose, referentiel, onSelect, onManual, err }) {
const [search, setSearch] = useState('');
const [domFilter, setDomFilter] = useState('all'); // 'all' | 'fr' | 'etr'
const [confirming, setConfirming] = useState(null); // ref en cours de confirmation
const [dateOuverture, setDateOuverture] = useState('');
useEffect(() => {
if (open) { setConfirming(null); setDateOuverture(''); }
}, [open]);
if (!open) return null;
const q = search.trim().toLowerCase();
@@ -298,6 +311,53 @@ function PlatPickerModal({ open, onClose, referentiel, onSelect, onManual, err }
return f ? (LOGO_BASE + f) : null;
};
/* ── Étape de confirmation : date d'ouverture du compte ── */
if (confirming) {
const img = imgFor(confirming);
return (
<Modal
open={open}
title="Ajouter une plateforme"
onClose={onClose}
width={480}
footer={
<div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
<button type="button" className="ghost" onClick={() => setConfirming(null)}> Retour</button>
<button type="button" className="primary" onClick={() => onSelect(confirming, dateOuverture)}>
Ajouter
</button>
</div>
}
>
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
{err && <div className="error">{err}</div>}
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
{img
? <img src={img} alt={confirming.nom} style={{ width: 44, height: 44, objectFit: 'contain', borderRadius: 8, flexShrink: 0 }} />
: <div style={{ width: 44, height: 44, borderRadius: 8, flexShrink: 0, background: 'var(--surface-2)', border: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 18, color: 'var(--text-muted)' }}>🏦</div>
}
<div style={{ fontWeight: 600, fontSize: 'var(--fs-md)' }}>{confirming.nom}</div>
</div>
<p style={{ margin: 0, color: 'var(--text-muted)', fontSize: 'var(--fs-sm)', lineHeight: 1.5 }}>
Pouvez-vous SVP préciser la date d'ouverture de votre compte sur cette plateforme ?
</p>
<div>
<label style={{ display: 'block', fontWeight: 600, marginBottom: 4, fontSize: 'var(--fs-sm)' }}>
Date d'ouverture du compte
</label>
<input
type="date"
autoFocus
value={dateOuverture}
onChange={e => setDateOuverture(e.target.value)}
style={{ width: '100%', boxSizing: 'border-box' }}
/>
</div>
</div>
</Modal>
);
}
return (
<Modal
open={open}
@@ -372,7 +432,7 @@ function PlatPickerModal({ open, onClose, referentiel, onSelect, onManual, err }
<button
key={r.id}
type="button"
onClick={() => onSelect(r)}
onClick={() => { setConfirming(r); setDateOuverture(localToday()); }}
style={{
display: 'flex', flexDirection: 'column', alignItems: 'center',
gap: 8, padding: '16px 10px 12px',
@@ -779,7 +839,7 @@ export default function PlateformesSection() {
};
/* ── Ajouter depuis le référentiel ──────────────────────────── */
const addPlatFromRef = async (ref) => {
const addPlatFromRef = async (ref, dateOuverture) => {
try {
await api.post('/plateformes', {
nom: ref.nom,
@@ -792,6 +852,7 @@ export default function PlateformesSection() {
type_pret_defaut: ref.type_pret_defaut || null,
freq_interets_defaut: ref.freq_interets_defaut || null,
referentiel_id: ref.id,
date_ouverture: dateOuverture || null,
});
setShowAddPicker(false);
await load();
@@ -942,6 +1003,8 @@ export default function PlateformesSection() {
} catch (e) { setErr(e.message); }
};
const multiDetenteur = new Set(plats.map(p => p.investisseur_id)).size > 1;
/* ── PFU CRUD ────────────────────────────────────────────────── */
@@ -1000,14 +1063,14 @@ export default function PlateformesSection() {
<th style={{ padding: '10px 8px', textAlign: 'left' }}>Domiciliation</th>
<th style={{ padding: '10px 8px', textAlign: 'left' }}>Catégories</th>
<th style={{ padding: '10px 8px', textAlign: 'left' }}>Secteurs</th>
<th style={{ padding: '10px 8px', textAlign: 'left' }}>Détenteur</th>
{multiDetenteur && <th style={{ padding: '10px 8px', textAlign: 'left' }}>Détenteur</th>}
<th style={{ padding: '10px 16px', textAlign: 'center', width: 60 }}>Invest.</th>
<th style={{ padding: '10px 8px', width: 40 }}></th>
</tr>
</thead>
<tbody>
{plats.length === 0 && (
<tr><td colSpan={7} className="text-muted" style={{ textAlign: 'center', padding: 24 }}>Aucune plateforme</td></tr>
<tr><td colSpan={multiDetenteur ? 8 : 7} className="text-muted" style={{ textAlign: 'center', padding: 24 }}>Aucune plateforme</td></tr>
)}
{plats.map((p, i) => {
const imgSrc = p.icone_filename ? logoUrl(p.icone_filename) : p.logo_filename ? logoUrl(p.logo_filename) : null;
@@ -1054,9 +1117,11 @@ export default function PlateformesSection() {
{sects.length === 0 && <span style={{ fontSize: 11, color: 'var(--text-muted)' }}></span>}
</div>
</td>
<td style={{ padding: '10px 8px', fontSize: 12, color: 'var(--text-muted)' }}>
{inv ? memberLabel(inv) : ''}
</td>
{multiDetenteur && (
<td style={{ padding: '10px 8px', fontSize: 12, color: 'var(--text-muted)' }}>
{inv ? memberLabel(inv) : '—'}
</td>
)}
<td style={{ padding: '10px 16px', textAlign: 'center', fontWeight: 600,
color: (p.nb_investissements ?? 0) > 0 ? 'var(--text)' : 'var(--text-muted)' }}>
{p.nb_investissements ?? 0}