Dateien nach "frontend/src" hochladen

This commit is contained in:
2026-05-26 01:12:07 +02:00
parent 360deb7257
commit 9bf8415a43
2 changed files with 112 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
import { useState, useEffect, useRef, useCallback } from 'react';
import { api, S } from './lib.js';
import { TOOLS, getGroupedTools } from './toolRegistry.js';
import { useConfirm } from './confirm.jsx';
import { HomeIcon, AppsIcon, AdminIcon, MoreIcon, UserIcon, LogOutIcon, ChevronIcon, UpdateIcon } from './icons.jsx';
const ICONS = ['🔗','🌐','📊','📁','🛠','📧','🗓','💾','🖥','📡','🔒','📖','🎯','⚡','🏠','🔧','📱','🎮','🚀','💡'];
@@ -330,6 +331,7 @@ function BottomNav({ active, setActive, user, onLogout, updateInfo, onUpdateClic
// ── Dashboard Widgets ─────────────────────────────────────────────────────────
function QuickLinks({ toast, mobile }) {
const { confirm, ConfirmDialog } = useConfirm();
const [links, setLinks] = useState([]);
const [editMode, setEdit] = useState(false);
const [showForm, setForm] = useState(false);
@@ -356,12 +358,14 @@ function QuickLinks({ toast, mobile }) {
};
const del = async id => {
if (!await confirm('Link wirklich löschen?')) return;
try { await api(`/dashboard/links/${id}`, { method:'DELETE' }); setLinks(p => p.filter(l => l.id!==id)); toast('Gelöscht'); }
catch(e) { toast(e.message, 'error'); }
};
return (
<div style={{ ...S.card, marginBottom:10 }}>
<ConfirmDialog/>
<div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:10 }}>
<div style={S.head}>SCHNELLZUGRIFF</div>
<div style={{ display:'flex', gap:6 }}>
@@ -539,6 +543,64 @@ function Notepad({ toast }) {
);
}
// ── Bestell-Statistik Widget ─────────────────────────────────────────────────
function BestellStats() {
const [stats, setStats] = useState(null);
const [open, setOpen] = useState(false);
const [loaded, setLoaded] = useState(false);
const load = () => {
if (loaded) return;
api('/dashboard/stats').then(s => { setStats(s); setLoaded(true); }).catch(() => {});
};
const toggle = () => { setOpen(v => !v); if (!open) load(); };
const Row = ({label, val, color='#fff'}) => (
<div style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'7px 0',borderBottom:'1px solid rgba(255,255,255,0.05)'}}>
<span style={{color:'rgba(255,255,255,0.45)',fontFamily:'monospace',fontSize:12}}>{label}</span>
<span style={{color,fontFamily:"'Space Mono',monospace",fontSize:13,fontWeight:700}}>{val}</span>
</div>
);
return (
<div style={{...S.card,marginBottom:10}}>
<button onClick={toggle} style={{width:'100%',background:'transparent',border:'none',
display:'flex',justifyContent:'space-between',alignItems:'center',cursor:'pointer',padding:0}}>
<div style={S.head}>STATISTIK</div>
<span style={{color:'rgba(255,255,255,0.3)',fontSize:11,display:'inline-block',
transform:open?'rotate(90deg)':'rotate(0)',transition:'transform 0.2s'}}></span>
</button>
{open && (
<div style={{marginTop:12}}>
{!stats ? (
<div style={{color:'rgba(255,255,255,0.25)',fontFamily:'monospace',fontSize:12}}>Lädt</div>
) : (
<>
<div style={{marginBottom:12}}>
<div style={{...S.head,marginBottom:6}}>BESTELLUNGEN</div>
<Row label="Gesamt" val={stats.totalOrders}/>
<Row label="Diesen Monat" val={stats.ordersThisMonth} color="#4ecdc4"/>
<Row label="Warteliste" val={stats.byStatus.warteliste||0} color="#ffe66d"/>
<Row label="In Arbeit" val={stats.byStatus.in_arbeit||0} color="#4ecdc4"/>
<Row label="Fertig (unbezahlt)" val={stats.byStatus.fertig||0} color="#6bcb77"/>
<Row label="Bezahlt" val={stats.bezahltOrders} color="#c084fc"/>
</div>
<div>
<div style={{...S.head,marginBottom:6}}>EINNAHMEN</div>
<Row label="Eingenommen (bezahlt)" val={`${stats.totalRevenue.toFixed(2)}`} color="#6bcb77"/>
<Row label="Offen (in Arbeit/Fertig)" val={`${stats.offeneRevenue.toFixed(2)}`} color="#ffe66d"/>
<Row label="Archiv-Einträge" val={stats.totalCalcs} color="rgba(255,255,255,0.5)"/>
</div>
</>
)}
</div>
)}
</div>
);
}
function Dashboard({ toast, mobile }) {
return (
<div style={{ padding: mobile ? '14px 12px 90px' : '36px 44px', maxWidth:1100 }}>
@@ -549,6 +611,7 @@ function Dashboard({ toast, mobile }) {
</p>
</div>
<QuickLinks toast={toast} mobile={mobile} />
<BestellStats/>
<TodoList toast={toast} />
<Notepad toast={toast} />
</div>