// Transactions page — full list with filters, search, sort, group-by-day function TxnsPage() { const { setDrawerTxn, dataVersion } = useApp(); const [q, setQ] = useState(''); const [catFilter, setCatFilter] = useState('all'); const [sourceFilter, setSourceFilter] = useState('all'); const [sort, setSort] = useState('date-desc'); // Default to current month index (the most recent in D.months[]) const [monthIdx, setMonthIdx] = useState(() => Math.max(0, (D.months?.length || 1) - 1)); // When data refreshes (e.g. after a scrape), keep monthIdx in range and // jump to the most recent month so the user sees freshly-pulled data. useEffect(() => { const len = D.months?.length || 0; if (len === 0) return; if (monthIdx >= len) setMonthIdx(len - 1); }, [dataVersion]); const months = D.months || []; const activeMonth = months[monthIdx] || D.current; const txns = useMemo(() => { let arr = (activeMonth?.txns || []).slice(); if (q) { const lq = q.toLowerCase(); arr = arr.filter(t => t.description.toLowerCase().includes(lq) || t.category.includes(q)); } if (catFilter !== 'all') arr = arr.filter(t => t.category === catFilter); if (sourceFilter !== 'all') arr = arr.filter(t => t.source === sourceFilter); if (sort === 'date-desc') arr.sort((a,b) => b.date.localeCompare(a.date)); if (sort === 'date-asc') arr.sort((a,b) => a.date.localeCompare(b.date)); if (sort === 'amount-desc') arr.sort((a,b) => a.amount - b.amount); if (sort === 'amount-asc') arr.sort((a,b) => b.amount - a.amount); return arr; }, [q, catFilter, sourceFilter, sort, monthIdx, dataVersion]); const grouped = useMemo(() => { const g = {}; txns.forEach(t => { (g[t.date] ||= []).push(t); }); return Object.entries(g); }, [txns]); const totalShown = txns.filter(t => t.amount < 0).reduce((s,t) => s + (-t.amount), 0); return (

עסקאות

{activeMonth?.label || ''} · {txns.length} עסקאות · סך {fmtILS(totalShown)}
{/* Month picker — horizontal scroll of all loaded months */}
{months.map((m, i) => { const active = i === monthIdx; const isEmpty = (m.txns?.length || 0) === 0; return ( ); })}
{/* Filter bar */}
setQ(e.target.value)} placeholder="חיפוש לפי שם, סכום, קטגוריה…" style={{ width: '100%', padding: '8px 32px 8px 12px', border: '0.5px solid var(--rule)', borderRadius: 9, background: 'var(--bg-deep)', fontSize: 13, outline: 'none' }} />
({value:c, label:c}))]} />
{grouped.length === 0 && } {grouped.map(([date, items]) => { const dayTotal = items.filter(t => t.amount < 0).reduce((s,t) => s + (-t.amount), 0); return (
{fmtDate(date)} {items.length} · {fmtILS(-dayTotal)}
{items.map(t => { const c = D.categories[t.category] || {}; return (
setDrawerTxn(t)} style={{ display: 'grid', gridTemplateColumns: '40px 1fr 130px 80px 100px', gap: 14, alignItems: 'center', padding: '10px 22px', borderBottom: '0.5px solid var(--rule)', cursor: 'pointer', }} onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-deep)'} onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
{c.icon}
{t.anomaly && !} {t.description}
{t.recurring && '↻ קבוע · '}{t.id}
{t.category}
{t.source}
0 ? 'var(--positive)' : 'var(--ink)' }}> {fmtILS(t.amount)}
); })}
); })}
); } function FilterSelect({ value, onChange, options }) { return ( ); } window.TxnsPage = TxnsPage;