// ADMIN PANEL — mobile ready function AdminPage({ lang, session, setPage, showToast }) { const [tab, setTab] = React.useState('stats'); const [products, setProducts] = React.useState(Store.getProducts()); const [categories, setCategories] = React.useState(Store.getCategories()); const [orders, setOrders] = React.useState(Store.getOrders()); const [users, setUsers] = React.useState(Store.getUsers()); const [editProduct, setEditProduct] = React.useState(null); const [editCat, setEditCat] = React.useState(null); const [newCat, setNewCat] = React.useState({ id: '', label: '' }); if (!session || session.role !== 'admin') return (
Acesso negado
); const t = lang === 'pt' ? { title: 'Painel Admin', products: 'Produtos', orders: 'Encomendas', users: 'Utilizadores', cats: 'Categorias', stats: 'Estatísticas', save: 'Guardar', cancel: 'Cancelar', addProduct: 'Novo Produto', available: 'Disponível', unavailable: 'Esgotado', name: 'Nome', price: 'Preço (€)', desc: 'Descrição', cat: 'Categoria', featured: 'Destaque', statuses: { pending: 'Pendente', processing: 'Em Preparação', delivered: 'Entregue', cancelled: 'Cancelado' } } : { title: 'Admin Panel', products: 'Products', orders: 'Orders', users: 'Users', cats: 'Categories', stats: 'Statistics', save: 'Save', cancel: 'Cancel', addProduct: 'New Product', available: 'Available', unavailable: 'Sold Out', name: 'Name', price: 'Price (€)', desc: 'Description', cat: 'Category', featured: 'Featured', statuses: { pending: 'Pending', processing: 'Processing', delivered: 'Delivered', cancelled: 'Cancelled' } }; const statusColors = { pending: '#d4993a', processing: '#4a90d9', delivered: '#4a9a30', cancelled: '#c84040' }; const saveProduct = (p) => { const updated = p.id ? products.map(x => x.id === p.id ? p : x) : [...products, { ...p, id: Store.nextId(products) }]; Store.saveProducts(updated); setProducts(updated); setEditProduct(null); showToast(lang==='pt'?'Produto guardado!':'Product saved!'); }; const deleteProduct = (id) => { const updated = products.filter(p => p.id !== id); Store.saveProducts(updated); setProducts(updated); showToast(lang==='pt'?'Produto eliminado.':'Product deleted.', 'info'); }; const toggleAvailable = (id) => { const updated = products.map(p => p.id === id ? { ...p, available: !p.available } : p); Store.saveProducts(updated); setProducts(updated); }; const updateOrderStatus = (id, status) => { const updated = orders.map(o => o.id === id ? { ...o, status } : o); Store.saveOrders(updated); setOrders(updated); showToast(lang==='pt'?'Estado atualizado!':'Status updated!'); }; const saveCat = (cat) => { const updated = editCat ? categories.map(c => c.id === cat.id ? cat : c) : [...categories, cat]; Store.saveCategories(updated); setCategories(updated); setEditCat(null); setNewCat({ id: '', label: '' }); }; const totalRevenue = orders.filter(o => o.status !== 'cancelled').reduce((s, o) => s + o.total, 0); const statCards = [ { icon: '💰', label: lang==='pt'?'Receita':'Revenue', value: `${totalRevenue.toFixed(2)}€` }, { icon: '📦', label: lang==='pt'?'Encomendas':'Orders', value: orders.length }, { icon: '⏳', label: lang==='pt'?'Pendentes':'Pending', value: orders.filter(o=>o.status==='pending').length }, { icon: '👥', label: lang==='pt'?'Clientes':'Customers', value: users.filter(u=>u.role!=='admin').length }, ]; const lbl = { display: 'block', fontFamily: 'Lato, sans-serif', color: 'var(--muted)', fontSize: 10, letterSpacing: 2, textTransform: 'uppercase', marginBottom: 5 }; const fld = { ...inputStyle, marginBottom: 13 }; const thStyle = { padding: '13px 14px', textAlign: 'left', fontFamily: 'Lato, sans-serif', color: 'var(--gold)', fontSize: 10, letterSpacing: 2, textTransform: 'uppercase', fontWeight: 600 }; const tdStyle = { padding: '11px 14px', fontFamily: 'Lato, sans-serif', fontSize: 13 }; return (
{/* Sidebar */} {/* Main content */}
{/* STATS */} {tab === 'stats' && (

{t.stats}

{statCards.map(s => (
{s.icon}
{s.value}
{s.label}
))}

{lang==='pt'?'Últimas Encomendas':'Recent Orders'}

{orders.length === 0 &&
{lang==='pt'?'Sem encomendas ainda.':'No orders yet.'}
} {[...orders].reverse().slice(0,5).map(o => (
#{o.id} — {o.userName} {t.statuses[o.status]} {o.total.toFixed(2)}€
))}
)} {/* PRODUCTS */} {tab === 'products' && (

{t.products}

setEditProduct({ name:'', category: categories[0]?.id||'', price:'', description:'', available:true, featured:false, image:'nata' })}> + {t.addProduct}
{[t.name, t.cat, t.price, t.available, t.featured, ''].map(h => ( ))} {products.map(p => ( ))}
{h}
{p.name} {p.category} {parseFloat(p.price).toFixed(2)}€ {p.featured ? '★' : '☆'}
setEditProduct({ ...p })}>✎
)} {/* ORDERS */} {tab === 'orders' && (

{t.orders}

{orders.length === 0 ? (
{lang==='pt'?'Sem encomendas.':'No orders yet.'}
) : (
{[...orders].reverse().map(o => (
Encomenda #{o.id} {new Date(o.createdAt).toLocaleString('pt-PT')}
{[ [lang==='pt'?'Cliente':'Customer', `${o.userName}\n${o.phone}`], [lang==='pt'?'Morada':'Address', o.address], ['Total', `${o.total.toFixed(2)}€ · ${o.payMethod}`], ].map(([k,v]) => (
{k}
{v}
))}
{o.items.map(i => ( {i.name} ×{i.qty} ))}
))}
)}
)} {/* USERS */} {tab === 'users' && (

{t.users}

{['ID', lang==='pt'?'Nome':'Name', 'Email', 'Role', lang==='pt'?'Registo':'Registered'].map(h => ( ))} {users.map(u => ( ))}
{h}
{u.id} {u.name} {u.email} {u.role} {u.createdAt}
)} {/* CATEGORIES */} {tab === 'cats' && (

{t.cats}

{categories.map(c => ( ))}
ID {lang==='pt'?'Nome':'Name'}
{c.id} {c.label}
setEditCat({ ...c })}>✎

{editCat ? (lang==='pt'?'Editar':'Edit') : (lang==='pt'?'Nova Categoria':'New Category')}

editCat?setEditCat(c=>({...c,id:e.target.value})):setNewCat(c=>({...c,id:e.target.value}))} />
editCat?setEditCat(c=>({...c,label:e.target.value})):setNewCat(c=>({...c,label:e.target.value}))} />
saveCat(editCat||newCat)}>{t.save} {editCat && setEditCat(null)}>{t.cancel}}
)}
{/* Product edit modal */} {editProduct && ( setEditProduct(null)} wide> setEditProduct(null)} lang={lang} t={t} /> )}
); } function ProductEditForm({ product, categories, onSave, onCancel, lang, t }) { const [form, setForm] = React.useState({ ...product }); const set = (k, v) => setForm(f => ({ ...f, [k]: v })); const lbl = { display: 'block', fontFamily: 'Lato, sans-serif', color: 'var(--muted)', fontSize: 10, letterSpacing: 2, textTransform: 'uppercase', marginBottom: 5 }; const fld = { ...inputStyle, marginBottom: 13 }; const imageOptions = ['nata','bolo','rissol','coxinha','choco','custom','chamuca','tematico','empada','feijao']; return (
set('name', e.target.value)} /> set('price', parseFloat(e.target.value)||0)} inputMode="decimal" />