Modification de l'import avec prompt IA

This commit is contained in:
2026-07-04 23:09:46 +02:00
parent 8834236840
commit 8bcd7e603d
5 changed files with 493 additions and 48 deletions
+32 -13
View File
@@ -15,6 +15,12 @@ import DepotsMensuelTable from '../components/DepotsMensuelTable.jsx';
import * as XLSX from 'xlsx';
/* ── Helpers export ──────────────────────────────────────────── */
/** Horodatage local AAAAMMJJ_HHmmss (jamais toISOString(), cf. décalage UTC) */
function timestampSuffix() {
const d = new Date();
const pad = n => String(n).padStart(2, '0');
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}_${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
}
function dlBlob(content, filename, type) {
const blob = new Blob([content], { type });
const url = URL.createObjectURL(blob);
@@ -375,14 +381,16 @@ export default function DepotsRetraits() {
const [allRows, setAllRows] = useState([]);
const [plats, setPlats] = useState([]);
const [dashData, setDashData] = useState(null);
const [filter, setFilter] = useState({ type: '', plateforme_ids: [], year: '', month: '' });
// Année sélectionnée, partagée entre l'onglet Plateformes et le filtre "Année" de Mouvements
const currentYear = String(new Date().getFullYear());
const [filter, setFilter] = useState({ type: '', plateforme_ids: [], year: currentYear, month: '' });
const [modalOpen, setModalOpen] = useState(false);
const [editingId, setEditingId] = useState(null);
const [form, setForm] = useState(empty);
const [err, setErr] = useState(null);
const [loading, setLoading] = useState(false);
const [selectedRow, setSelectedRow] = useState(null);
const [drPlatYear, setDrPlatYear] = useState(String(new Date().getFullYear()));
const [drPlatYear, setDrPlatYear] = useState(currentYear);
const [allRemb, setAllRemb] = useState([]);
const [allInv, setAllInv] = useState([]);
@@ -401,6 +409,7 @@ export default function DepotsRetraits() {
const platIds = p.get('plat_ids');
if (platIds) newFilter.plateforme_ids = platIds.split(',').filter(Boolean);
setFilter(newFilter);
setDrPlatYear(newFilter.year); // garde l'onglet Plateformes synchronisé avec l'année du drill-down
navigate('/depots-retraits', { replace: true });
}, []); // eslint-disable-line
const [openMenu, setOpenMenu] = useState(null); // { row, x, y }
@@ -905,9 +914,9 @@ export default function DepotsRetraits() {
<>
<div className="topbar">
<h2><PageIcon name="depots-retraits" />Dépôts / Retraits</h2>
{(filter.type || filter.plateforme_ids.length > 0 || filter.year || filter.month) && (
{(filter.type || filter.plateforme_ids.length > 0 || filter.month) && (
<button className="dr-clear-btn"
onClick={() => setFilter({ type: '', plateforme_ids: [], year: '', month: '' })}>
onClick={() => { setFilter({ type: '', plateforme_ids: [], year: '', month: '' }); setDrPlatYear(''); }}>
Effacer les filtres
</button>
)}
@@ -946,10 +955,10 @@ export default function DepotsRetraits() {
<div style={{ fontSize: '0.8em', color: 'var(--text-muted)', marginTop: 5 }}>{fmtEUR(prevTotals.retraits)} en {prevYear}</div>
</div>
<div
className={`kpi${(filter.type || filter.plateforme_ids.length > 0 || filter.year || filter.month) ? ' dr-kpi-clickable dr-kpi-active dr-kpi-active-neutral' : ''}`}
onClick={() => setFilter({ type: '', plateforme_ids: [], year: '', month: '' })}
title={(filter.type || filter.plateforme_ids.length > 0 || filter.year || filter.month) ? 'Effacer les filtres' : undefined}
style={(filter.type || filter.plateforme_ids.length > 0 || filter.year || filter.month) ? { cursor: 'pointer' } : {}}
className={`kpi${(filter.type || filter.plateforme_ids.length > 0 || filter.month) ? ' dr-kpi-clickable dr-kpi-active dr-kpi-active-neutral' : ''}`}
onClick={() => { setFilter({ type: '', plateforme_ids: [], year: '', month: '' }); setDrPlatYear(''); }}
title={(filter.type || filter.plateforme_ids.length > 0 || filter.month) ? 'Effacer les filtres' : undefined}
style={(filter.type || filter.plateforme_ids.length > 0 || filter.month) ? { cursor: 'pointer' } : {}}
>
<div className="label">Diff. Dépôts vs Retraits</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: '4px 0 0' }}>
@@ -988,7 +997,7 @@ export default function DepotsRetraits() {
{drPlatYear && <span style={{ marginLeft: 8 }}>pour l'année {drPlatYear}</span>}
</h3>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<select value={drPlatYear} onChange={e => setDrPlatYear(e.target.value)}
<select value={drPlatYear} onChange={e => { const v = e.target.value; setDrPlatYear(v); setFilter(f => ({ ...f, year: v })); }}
style={{
fontSize: 'var(--fs-xs)', padding: '4px 8px', height: 30,
borderRadius: 6, border: '1px solid var(--border)',
@@ -1154,10 +1163,20 @@ export default function DepotsRetraits() {
</button>
<ExportDropdown
disabled={rows.length === 0}
onCSV={() => dlBlob(mouvToCSV(rows), 'mouvements.csv', 'text/csv;charset=utf-8')}
onXLS={() => dlBlob(mouvToXLS(rows, multiDetenteur), 'mouvements.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')}
onJSON={() => dlBlob(mouvToJSON(rows), 'mouvements.json', 'application/json')}
onCSV={() => dlBlob(mouvToCSV(rows), `Mouvements Dépôts Retraits ${timestampSuffix()}.csv`, 'text/csv;charset=utf-8')}
onXLS={() => dlBlob(mouvToXLS(rows, multiDetenteur), `Mouvements Dépôts Retraits ${timestampSuffix()}.xlsx`, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')}
onJSON={() => dlBlob(mouvToJSON(rows), `Mouvements Dépôts Retraits ${timestampSuffix()}.json`, 'application/json')}
/>
<button
type="button"
className="icon-btn"
title="Importer des dépôts/retraits"
onClick={() => navigate('/settings?section=imports&module=depots_retraits')}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/>
</svg>
</button>
</div>
</div>
@@ -1217,7 +1236,7 @@ export default function DepotsRetraits() {
</div>
<div style={{ flex: 1, minWidth: 100 }}>
<label>Année</label>
<select value={filter.year} onChange={e => setFilter({ ...filter, year: e.target.value })}>
<select value={filter.year} onChange={e => { const v = e.target.value; setFilter(f => ({ ...f, year: v })); setDrPlatYear(v); }}>
<option value="">Toutes</option>
{years.map(y => <option key={y} value={y}>{y}</option>)}
</select>