refactor: Statistik Zeitraum-Buttons → Von/Bis Datumfelder, Standard = Gesamt
This commit is contained in:
@@ -102,20 +102,19 @@ function KPI({ label, value, color, sub }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bestellungen im gewählten Zeitraum
|
// Bestellungen im gewählten Zeitraum
|
||||||
function OrdersInPeriod({ period, custom }) {
|
function OrdersInPeriod({ fromDate, toDate }) {
|
||||||
const [orders, setOrders] = useState(null);
|
const [orders, setOrders] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { from, to } = periodRange(period, custom);
|
const q = (fromDate || toDate) ? `?from=${fromDate}&to=${toDate}` : '';
|
||||||
const q = from ? `?from=${from}&to=${to}` : '';
|
|
||||||
api(`/tools/statistik/month-orders${q}`).then(setOrders).catch(()=>setOrders([]));
|
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_ORDER = ['warteliste','in_arbeit','fertig','bezahlt','abgeschlossen'];
|
||||||
const STATUS_COLOR = { warteliste:'#ffe66d', in_arbeit:'#4ecdc4', fertig:'#6bcb77', bezahlt:'#c084fc', abgeschlossen:'#4ade80' };
|
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 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
|
// Gruppieren nach Status
|
||||||
const grouped = {};
|
const grouped = {};
|
||||||
@@ -184,8 +183,8 @@ function OrdersInPeriod({ period, custom }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Statistik({ mobile }) {
|
export default function Statistik({ mobile }) {
|
||||||
const [period, setPeriod] = useState('month');
|
const [fromDate, setFromDate] = useState('');
|
||||||
const [custom, setCustom] = useState({ type:'month', month: new Date().toISOString().slice(0,7), year: new Date().getFullYear() });
|
const [toDate, setToDate] = useState('');
|
||||||
const [data, setData] = useState(null);
|
const [data, setData] = useState(null);
|
||||||
const [loading,setLoading] = useState(false);
|
const [loading,setLoading] = useState(false);
|
||||||
const [tab, setTab] = useState('overview');
|
const [tab, setTab] = useState('overview');
|
||||||
@@ -195,16 +194,14 @@ export default function Statistik({ mobile }) {
|
|||||||
|
|
||||||
function load() {
|
function load() {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const { from, to } = periodRange(period, custom);
|
const q = (fromDate || toDate) ? `?from=${fromDate}&to=${toDate}` : '';
|
||||||
const q = from ? `?from=${from}&to=${to}` : '';
|
|
||||||
api('/tools/statistik/overview'+q)
|
api('/tools/statistik/overview'+q)
|
||||||
.then(d => setData(d))
|
.then(d => setData(d))
|
||||||
.catch(()=>{})
|
.catch(()=>{})
|
||||||
.finally(()=>setLoading(false));
|
.finally(()=>setLoading(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Neu laden wenn Zeitraum ändert
|
useEffect(() => { load(); }, [fromDate, toDate]);
|
||||||
useEffect(() => { load(); }, [period, custom.type, custom.month, custom.year]);
|
|
||||||
|
|
||||||
async function addExpense() {
|
async function addExpense() {
|
||||||
if (!expForm.description || !expForm.amount) return;
|
if (!expForm.description || !expForm.amount) return;
|
||||||
@@ -232,46 +229,26 @@ export default function Statistik({ mobile }) {
|
|||||||
📊 3D-Druck Statistik
|
📊 3D-Druck Statistik
|
||||||
</h2>
|
</h2>
|
||||||
{/* Zeitraum */}
|
{/* Zeitraum */}
|
||||||
<div style={{display:'flex',gap:4,flexWrap:'wrap',alignItems:'center'}}>
|
<div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap'}}>
|
||||||
{PERIODS.filter(p=>p.id!=='custom').map(p => (
|
<div style={{display:'flex',alignItems:'center',gap:6}}>
|
||||||
<button key={p.id} onClick={()=>setPeriod(p.id)} style={{
|
<span style={{color:'rgba(255,255,255,0.35)',fontFamily:'monospace',fontSize:11}}>Von</span>
|
||||||
background: period===p.id ? 'rgba(78,205,196,0.15)' : 'rgba(255,255,255,0.04)',
|
<input type="date" value={fromDate} onChange={e=>setFromDate(e.target.value)}
|
||||||
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')}
|
|
||||||
style={{background:'rgba(255,255,255,0.06)',border:'1px solid rgba(255,255,255,0.12)',
|
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'}}>
|
borderRadius:8,padding:'5px 10px',color:'#fff',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>
|
|
||||||
)}
|
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -510,7 +487,7 @@ export default function Statistik({ mobile }) {
|
|||||||
|
|
||||||
{/* ══ BESTELLUNGEN (dieser Monat) ══ */}
|
{/* ══ BESTELLUNGEN (dieser Monat) ══ */}
|
||||||
{tab==='orders' && (
|
{tab==='orders' && (
|
||||||
<OrdersInPeriod period={period} custom={custom}/>
|
<OrdersInPeriod fromDate={fromDate} toDate={toDate}/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user