refactor: Statistik Zeitraum-Buttons → Von/Bis Datumfelder, Standard = Gesamt

This commit is contained in:
2026-06-18 20:32:16 +02:00
parent d19822e5dc
commit a6d47887d6

View File

@@ -102,20 +102,19 @@ function KPI({ label, value, color, sub }) {
}
// Bestellungen im gewählten Zeitraum
function OrdersInPeriod({ period, custom }) {
function OrdersInPeriod({ fromDate, toDate }) {
const [orders, setOrders] = useState(null);
useEffect(() => {
const { from, to } = periodRange(period, custom);
const q = from ? `?from=${from}&to=${to}` : '';
const q = (fromDate || toDate) ? `?from=${fromDate}&to=${toDate}` : '';
api(`/tools/statistik/month-orders${q}`).then(setOrders).catch(()=>setOrders([]));
}, [period, custom]);
}, [fromDate, toDate]);
const STATUS_ORDER = ['warteliste','in_arbeit','fertig','bezahlt','abgeschlossen'];
const STATUS_COLOR = { warteliste:'#ffe66d', in_arbeit:'#4ecdc4', fertig:'#6bcb77', bezahlt:'#c084fc', abgeschlossen:'#4ade80' };
const STATUS_LABEL = { warteliste:'Warteliste', in_arbeit:'In Arbeit', fertig:'Fertig', bezahlt:'Bezahlt', abgeschlossen:'Abgeschlossen' };
const periodLabel = period==='week'?'DIESER WOCHE':period==='month'?'DIESEM MONAT':period==='year'?'DIESEM JAHR':period==='all'?'GESAMT':'IM ZEITRAUM';
const periodLabel = (fromDate || toDate) ? 'IM ZEITRAUM' : 'GESAMT';
// Gruppieren nach Status
const grouped = {};
@@ -184,8 +183,8 @@ function OrdersInPeriod({ period, custom }) {
}
export default function Statistik({ mobile }) {
const [period, setPeriod] = useState('month');
const [custom, setCustom] = useState({ type:'month', month: new Date().toISOString().slice(0,7), year: new Date().getFullYear() });
const [fromDate, setFromDate] = useState('');
const [toDate, setToDate] = useState('');
const [data, setData] = useState(null);
const [loading,setLoading] = useState(false);
const [tab, setTab] = useState('overview');
@@ -195,16 +194,14 @@ export default function Statistik({ mobile }) {
function load() {
setLoading(true);
const { from, to } = periodRange(period, custom);
const q = from ? `?from=${from}&to=${to}` : '';
const q = (fromDate || toDate) ? `?from=${fromDate}&to=${toDate}` : '';
api('/tools/statistik/overview'+q)
.then(d => setData(d))
.catch(()=>{})
.finally(()=>setLoading(false));
}
// Neu laden wenn Zeitraum ändert
useEffect(() => { load(); }, [period, custom.type, custom.month, custom.year]);
useEffect(() => { load(); }, [fromDate, toDate]);
async function addExpense() {
if (!expForm.description || !expForm.amount) return;
@@ -232,46 +229,26 @@ export default function Statistik({ mobile }) {
📊 3D-Druck Statistik
</h2>
{/* Zeitraum */}
<div style={{display:'flex',gap:4,flexWrap:'wrap',alignItems:'center'}}>
{PERIODS.filter(p=>p.id!=='custom').map(p => (
<button key={p.id} onClick={()=>setPeriod(p.id)} style={{
background: period===p.id ? 'rgba(78,205,196,0.15)' : 'rgba(255,255,255,0.04)',
border: `1px solid ${period===p.id ? 'rgba(78,205,196,0.5)' : 'rgba(255,255,255,0.1)'}`,
borderRadius:8, padding:'5px 12px',
color: period===p.id ? '#4ecdc4' : 'rgba(255,255,255,0.4)',
fontFamily:'monospace', fontSize:11, cursor:'pointer',
}}>{p.label}</button>
))}
{/* Eigener Zeitraum */}
<div style={{display:'flex',gap:4,alignItems:'center'}}>
<select value={custom.type} onChange={e=>setCustom(p=>({...p,type:e.target.value}))}
onClick={()=>setPeriod('custom')}
<div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap'}}>
<div style={{display:'flex',alignItems:'center',gap:6}}>
<span style={{color:'rgba(255,255,255,0.35)',fontFamily:'monospace',fontSize:11}}>Von</span>
<input type="date" value={fromDate} onChange={e=>setFromDate(e.target.value)}
style={{background:'rgba(255,255,255,0.06)',border:'1px solid rgba(255,255,255,0.12)',
borderRadius:8,padding:'5px 8px',color:'rgba(255,255,255,0.6)',fontFamily:'monospace',fontSize:11,cursor:'pointer'}}>
<option value="month">Monat</option>
<option value="year">Jahr</option>
</select>
{custom.type==='month' && (
<select value={custom.month}
onChange={e=>{setCustom(p=>({...p,month:e.target.value}));setPeriod('custom');}}
style={{background: period==='custom'?'rgba(78,205,196,0.1)':'rgba(255,255,255,0.06)',
border:`1px solid ${period==='custom'?'rgba(78,205,196,0.4)':'rgba(255,255,255,0.12)'}`,
borderRadius:8,padding:'5px 8px',color:period==='custom'?'#4ecdc4':'rgba(255,255,255,0.6)',
fontFamily:'monospace',fontSize:11,cursor:'pointer'}}>
{getMonthOptions().map(o=><option key={o.val} value={o.val}>{o.label}</option>)}
</select>
)}
{custom.type==='year' && (
<select value={custom.year}
onChange={e=>{setCustom(p=>({...p,year:Number(e.target.value)}));setPeriod('custom');}}
style={{background: period==='custom'?'rgba(78,205,196,0.1)':'rgba(255,255,255,0.06)',
border:`1px solid ${period==='custom'?'rgba(78,205,196,0.4)':'rgba(255,255,255,0.12)'}`,
borderRadius:8,padding:'5px 8px',color:period==='custom'?'#4ecdc4':'rgba(255,255,255,0.6)',
fontFamily:'monospace',fontSize:11,cursor:'pointer'}}>
{getYearOptions().map(y=><option key={y} value={y}>{y}</option>)}
</select>
)}
borderRadius:8,padding:'5px 10px',color:'#fff',fontFamily:'monospace',fontSize:11,cursor:'pointer'}}/>
</div>
<div style={{display:'flex',alignItems:'center',gap:6}}>
<span style={{color:'rgba(255,255,255,0.35)',fontFamily:'monospace',fontSize:11}}>Bis</span>
<input type="date" value={toDate} onChange={e=>setToDate(e.target.value)}
style={{background:'rgba(255,255,255,0.06)',border:'1px solid rgba(255,255,255,0.12)',
borderRadius:8,padding:'5px 10px',color:'#fff',fontFamily:'monospace',fontSize:11,cursor:'pointer'}}/>
</div>
{(fromDate || toDate) && (
<button onClick={()=>{setFromDate('');setToDate('');}}
style={{background:'rgba(255,255,255,0.04)',border:'1px solid rgba(255,255,255,0.1)',
borderRadius:8,padding:'5px 10px',color:'rgba(255,255,255,0.4)',fontFamily:'monospace',fontSize:11,cursor:'pointer'}}>
Zurücksetzen
</button>
)}
</div>
</div>
@@ -510,7 +487,7 @@ export default function Statistik({ mobile }) {
{/* ══ BESTELLUNGEN (dieser Monat) ══ */}
{tab==='orders' && (
<OrdersInPeriod period={period} custom={custom}/>
<OrdersInPeriod fromDate={fromDate} toDate={toDate}/>
)}
</div>
);