Correction de solde

This commit is contained in:
ocroguennec committed 2026-08-16 17:48:40 +02:00
1 parent 1bab97b5b3
commit 849e16de33
3 files changed
+188 -6

No files matched your search

+98 -2
View File
@@ -134,6 +134,99 @@ export function ExportDropdown({ disabled, onCSV, onXLS, onJSON }) {
);
}
/* ── Menu déroulant "+" — actions rapides sur les mouvements (extensible :
pour l'instant uniquement la création d'une correction de solde) ── */
export function AddDropdown({ disabled, onNewCorrection }) {
const [open, setOpen] = useState(false);
const ref = useRef(null);
useEffect(() => {
if (!open) return;
const h = e => { if (!ref.current?.contains(e.target)) setOpen(false); };
document.addEventListener('mousedown', h);
return () => document.removeEventListener('mousedown', h);
}, [open]);
const choose = fn => { setOpen(false); fn(); };
return (
<div ref={ref} style={{ position: 'relative' }}>
<button type="button" className="icon-btn" disabled={disabled}
onClick={() => setOpen(o => !o)} title="Ajouter">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
</svg>
</button>
{open && (
<div className="export-dropdown" role="menu">
<button role="menuitem" onClick={() => choose(onNewCorrection)}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 20V10"/><path d="M18 20V4"/><path d="M6 20v-4"/>
</svg>
<span><strong>Correction de solde</strong><small>Ajuster manuellement le solde porte-monnaie</small></span>
</button>
</div>
)}
</div>
);
}
/** Petite modale de sélection plateforme + date, avant d'ouvrir CorrectionModal
en saisie libre (déclenchée depuis AddDropdown, pas depuis un mouvement existant). */
export function CorrectionPickerModal({ open, onClose, onContinue, plateformes = [], multiDetenteur, defaultPlateformeId }) {
const [platId, setPlatId] = useState('');
const [date, setDate] = useState('');
useEffect(() => {
if (open) {
setPlatId(defaultPlateformeId ? String(defaultPlateformeId) : '');
setDate(today());
}
}, [open, defaultPlateformeId]);
if (!open) return null;
return (
<div style={{
position: 'fixed', inset: 0, zIndex: 1000,
display: 'flex', alignItems: 'center', justifyContent: 'center',
background: 'rgba(0,0,0,0.4)',
}}>
<div style={{
background: 'var(--surface)', borderRadius: 10,
padding: '24px 28px', width: 380, maxWidth: '90vw',
boxShadow: '0 8px 32px rgba(0,0,0,0.18)',
border: '1px solid var(--border)',
}}>
<div style={{ marginBottom: 6, fontWeight: 700, fontSize: 'var(--fs-base)' }}>
Nouvelle correction de solde
</div>
<div style={{ fontSize: 'var(--fs-sm)', color: 'var(--text-muted)', marginBottom: 18, lineHeight: 1.5 }}>
Choisissez la plateforme et la date de référence pour la correction.
</div>
<div style={{ marginBottom: 12 }}>
<label style={{ fontSize: 'var(--fs-sm)', fontWeight: 500, display: 'block', marginBottom: 4 }}>Plateforme</label>
<select value={platId} onChange={e => setPlatId(e.target.value)} style={{ width: '100%' }} autoFocus>
<option value="">— Choisir —</option>
{plateformes.map(p => (
<option key={p.id} value={p.id}>{p.nom}{multiDetenteur && p.investisseur_nom ? ` — ${p.investisseur_nom}` : ''}</option>
))}
</select>
</div>
<div style={{ marginBottom: 18 }}>
<label style={{ fontSize: 'var(--fs-sm)', fontWeight: 500, display: 'block', marginBottom: 4 }}>Date</label>
<input type="date" value={date} onChange={e => setDate(e.target.value)} style={{ width: '100%' }} />
</div>
<div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
<button onClick={onClose}>Annuler</button>
<button className="primary" disabled={!platId || !date}
onClick={() => onContinue({ plateforme_id: Number(platId), date })}>
Continuer
</button>
</div>
</div>
</div>
);
}
/* ── Panneau de détail d'un mouvement ────────────────────────── */
export function DetailPanel({ row, onEdit, onDeleteCorrection, onViewRemb, onViewInvestissement }) {
if (!row) return (
@@ -371,8 +464,11 @@ export function CorrectionModal({ open, onClose, onConfirm,
fontSize: 'var(--fs-sm)', color: 'var(--text-muted)',
marginBottom: 18, lineHeight: 1.5,
}}>
Après ce {isRetrait ? 'retrait' : 'dépôt'} sur <strong>{plateforme_nom}</strong>,
quel est le solde indiqué sur la plateforme ?
{type_operation ? (
<>Après ce {isRetrait ? 'retrait' : 'dépôt'} sur <strong>{plateforme_nom}</strong>, quel est le solde indiqué sur la plateforme ?</>
) : (
<>Quel est le solde indiqué sur <strong>{plateforme_nom}</strong> à la date du {date ? fmtDate(date) : ''} ?</>
)}
{' '}Si différent du solde calculé, une correction sera créée automatiquement.
</div>