Files
hd-commerce/src/pages/admin/bestellungen/[id].astro
T
till aec179db36 v2: Session-Login & Rollen, Premium-Admin, Visual-Block-Builder, KI-/MCP-API
- Auth-Umbau: Session-Login (signiertes HMAC-Cookie, scrypt-Hashing) statt Basic-Auth;
  users-/audit-Tabellen, Initial-Owner aus ENV, Rate-Limit, konfigurierbarer ADMIN_PATH
  (Middleware-Rewrite), Rollen-Gate (owner/redaktion/versand), Nutzerverwaltung, Audit-Log,
  Login/Logout/Konto-Seiten.
- Premium-Pass: Command-Palette (Cmd-K), Toasts, Account-Menue, aufgewertetes Dashboard
  (KPI-Trend+Sparkline, Aktivitaets-Feed, Schnellaktionen), schoene Empty-States.
- Block-Builder: pages.blocks, Vollbild-Editor (Liste/Live-Vorschau/Settings, Desktop/Mobil),
  10 Block-Typen, Storefront-BlockRenderer auf /seite/[slug], Save-Endpoint.
- KI-Editierbarkeit: token-gesicherte /api/admin/* (CRUD), Manifest /api/admin + /ai-admin.txt,
  MCP-Server unter mcp/ (14 Tools).
- Docs: README + .env.example + mcp/README aktualisiert.
2026-06-17 12:46:31 +00:00

63 lines
3.5 KiB
Plaintext

---
import Admin from '../../../layouts/Admin.astro';
import { adminBase, currentUser } from '../../../lib/auth.js';
const base = adminBase();
import { getOrderById, updateOrderStatus, formatPrice, recordAudit } from '../../../lib/store.js';
const { id } = Astro.params;
let flash = '';
if (Astro.request.method === 'POST') {
const form = await Astro.request.formData();
const status = form.get('status');
if (status) { updateOrderStatus(id, String(status)); recordAudit({ user: currentUser(Astro.request)?.email, action: 'update', entity: 'order', entity_id: String(id) }); flash = 'Status aktualisiert.'; }
}
const order = getOrderById(id);
if (!order) return Astro.redirect(base + '/bestellungen');
const statusMap = { fulfilled: ['green', 'Erfüllt'], pending: ['amber', 'Offen'], cancelled: ['gray', 'Storniert'], refunded: ['red', 'Erstattet'] };
const fmtDate = (s) => new Date(s).toLocaleString('de-DE', { day: '2-digit', month: 'long', year: 'numeric', hour: '2-digit', minute: '2-digit' });
const statuses = [['pending', 'Offen'], ['fulfilled', 'Erfüllt'], ['cancelled', 'Storniert'], ['refunded', 'Erstattet']];
---
<Admin title={`Bestellung ${order.number}`} active="bestellungen" crumbs={[{ label: 'Bestellungen', href: base + '/bestellungen' }, { label: order.number }]}>
<div class="s-stack">
{flash && <div class="s-flash">✓ {flash}</div>}
<div class="s-two-col">
<div class="s-card">
<div class="s-card-head">Artikel</div>
<div class="s-table-wrap">
<table class="s-table">
<thead><tr><th>Produkt</th><th>Variante</th><th class="num">Menge</th><th class="num">Einzelpreis</th><th class="num">Summe</th></tr></thead>
<tbody>
{order.items.map((i) => (
<tr><td><b>{i.name}</b></td><td class="s-muted">{i.size || '—'}</td><td class="num">{i.qty}</td><td class="num">{formatPrice(i.priceCents)}</td><td class="num">{formatPrice(i.priceCents * i.qty)}</td></tr>
))}
</tbody>
</table>
</div>
<div class="s-card-pad" style="display:flex;justify-content:space-between;font-weight:700;font-size:16px;border-top:1px solid var(--s-border)"><span>Gesamt</span><span>{formatPrice(order.total_cents)}</span></div>
</div>
<div class="s-stack">
<div class="s-card s-card-pad">
<div class="s-section-title">Status</div>
<div style="margin:8px 0 14px"><span class={`s-badge ${(statusMap[order.status]||['gray',order.status])[0]}`}>{(statusMap[order.status]||['',order.status])[1]}</span></div>
<form method="POST">
<select class="s-select" name="status" style="margin-bottom:10px">
{statuses.map(([v, l]) => (<option value={v} selected={order.status === v}>{l}</option>))}
</select>
<button class="s-btn s-btn-primary" type="submit" style="width:100%">Status speichern</button>
</form>
</div>
<div class="s-card s-card-pad">
<div class="s-section-title">Kunde</div>
<p style="margin:8px 0 4px"><b>{order.customer_name || '—'}</b></p>
<p class="s-muted" style="margin:0 0 8px">{order.email}</p>
<div class="s-section-title" style="margin-top:12px">Lieferadresse</div>
<p class="s-muted" style="margin:6px 0 0">{order.address || '—'}</p>
<div class="s-section-title" style="margin-top:12px">Bestellt am</div>
<p class="s-muted" style="margin:6px 0 0">{fmtDate(order.created_at)}</p>
</div>
</div>
</div>
</div>
</Admin>