@xiwebdesign/xicms-core 7.25.0 → 7.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -259,7 +259,7 @@ function OrdersTab({ siteId }) {
259
259
  });
260
260
  setEditShippingEuro(centsToEuroInput(order.amount.shippingCents));
261
261
  setEditLines(
262
- order.status === "pending" ? order.items.filter((i) => i.kind !== "donation").map((i) => ({ productId: i.productId ?? "", variantKey: i.variantKey ?? "", qty: i.qty })) : []
262
+ order.status === "pending" ? order.items.filter((i) => i.kind === "product").map((i) => ({ productId: i.productId ?? "", variantKey: i.variantKey ?? "", qty: i.qty })) : []
263
263
  );
264
264
  setEditOpen(true);
265
265
  }
@@ -499,12 +499,34 @@ function OrdersTab({ siteId }) {
499
499
  ")"
500
500
  ] }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Geen verzending (donatie)." }),
501
501
  current.trackingUrl && /* @__PURE__ */ jsx("a", { className: "text-sm text-brand-700 underline", href: current.trackingUrl, target: "_blank", rel: "noreferrer", children: "Track & trace \u2197" })
502
+ ] }),
503
+ current.billing && /* @__PURE__ */ jsxs("div", { children: [
504
+ /* @__PURE__ */ jsx("h4", { className: "mb-1 text-sm font-semibold", children: "Factuuradres" }),
505
+ /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
506
+ current.billing.address,
507
+ /* @__PURE__ */ jsx("br", {}),
508
+ current.billing.zip,
509
+ " ",
510
+ current.billing.city,
511
+ " (",
512
+ current.billing.country,
513
+ ")"
514
+ ] })
502
515
  ] })
503
516
  ] }),
504
517
  current.note && /* @__PURE__ */ jsxs("div", { children: [
505
518
  /* @__PURE__ */ jsx("h4", { className: "mb-1 text-sm font-semibold", children: "Opmerking van de klant" }),
506
519
  /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap text-sm", children: current.note })
507
520
  ] }),
521
+ current.giftWrap && (current.giftWrap.cardText || current.giftWrap.note) && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-amber-200 bg-amber-50 p-3", children: [
522
+ /* @__PURE__ */ jsx("h4", { className: "mb-1 text-sm font-semibold", children: "\u{1F381} Cadeauverpakking" }),
523
+ current.giftWrap.cardText && /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
524
+ /* @__PURE__ */ jsx("strong", { children: "Op het kaartje:" }),
525
+ " ",
526
+ current.giftWrap.cardText
527
+ ] }),
528
+ current.giftWrap.note && /* @__PURE__ */ jsx("p", { className: "mt-1 whitespace-pre-wrap text-sm", children: current.giftWrap.note })
529
+ ] }),
508
530
  /* @__PURE__ */ jsxs("div", { children: [
509
531
  /* @__PURE__ */ jsx("h4", { className: "mb-1 text-sm font-semibold", children: "Interne notitie" }),
510
532
  /* @__PURE__ */ jsx(
@@ -543,6 +565,7 @@ function OrdersTab({ siteId }) {
543
565
  ")"
544
566
  ] }),
545
567
  i.kind === "donation" && /* @__PURE__ */ jsx(Badge, { tone: "amber", children: "donatie" }),
568
+ i.kind === "giftwrap" && /* @__PURE__ */ jsx(Badge, { tone: "amber", children: "cadeau" }),
546
569
  i.personalization && Object.entries(i.personalization).map(([k, v]) => /* @__PURE__ */ jsxs("span", { className: "block text-xs text-slate-600", children: [
547
570
  "\u21B3 ",
548
571
  v.text ?? v.fileName ?? "eigen ontwerp",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/shop/OrdersTab.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { collection, getDocs, limit, onSnapshot, orderBy, query, where } from \"firebase/firestore\";\nimport type { Timestamp } from \"firebase/firestore\";\nimport { getDb } from \"../../firebase/client\";\nimport { formatCents, orderRegelNaam, type Order } from \"../../schema/shop\";\nimport { Badge, Button, Card, Field, Input, Textarea } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Switch } from \"../ui/switch\";\nimport { useToast } from \"../ui/toast\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport { Dialog, DialogContent, DialogClose } from \"../ui/dialog\";\nimport { ORDER_STATUS_LABELS, centsToEuroInput, eurosToCents, shopCallable } from \"./lib\";\n\n/** Minimale productvorm voor de keuzelijst van een handmatige bestelling. */\ntype ProductKeuze = {\n id: string;\n name: string;\n categoryIds?: string[];\n options?: { name: string }[];\n variants?: { key: string }[];\n};\n\ntype StoredOrder = Order & {\n id: string;\n createdAt?: Timestamp;\n paidAt?: Timestamp;\n shippedAt?: Timestamp;\n refundedAt?: Timestamp;\n mail?: { confirmationSentAt?: Timestamp; error?: string };\n /** Runtime-velden die de Functions erbovenop schrijven (niet in OrderSchema). */\n provider?: \"stripe\" | \"mollie\";\n mollie?: { paymentId?: string };\n};\n\nconst FILTERS = [\n { value: \"all\", label: \"Alles\" },\n { value: \"pending\", label: \"Wacht op betaling\" },\n { value: \"paid\", label: \"Betaald\" },\n { value: \"shipped\", label: \"Verzonden\" },\n { value: \"cancelled\", label: \"Geannuleerd\" },\n { value: \"refunded\", label: \"Terugbetaald\" },\n { value: \"donation\", label: \"Donaties\" },\n];\n\nfunction fmtDate(t?: Timestamp): string {\n if (!t?.toDate) return \"—\";\n return t.toDate().toLocaleString(\"nl-NL\", { dateStyle: \"short\", timeStyle: \"short\" });\n}\n\n/** Btw-component uit een incl.-prijs: totaal × tarief / (100 + tarief). */\nfunction vatOf(cents: number, rate: number): number {\n return Math.round((cents * rate) / (100 + rate));\n}\n\nexport function OrdersTab({ siteId }: { siteId: string }) {\n const { toast } = useToast();\n const confirm = useConfirm();\n const [orders, setOrders] = useState<StoredOrder[]>([]);\n const [selected, setSelected] = useState<string | null>(null);\n const [filter, setFilter] = useState(\"all\");\n const [search, setSearch] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [invoice, setInvoice] = useState<{ url: string; number: string } | null>(null);\n const [shipOpen, setShipOpen] = useState(false);\n const [mailOpen, setMailOpen] = useState(false);\n const [mailSubject, setMailSubject] = useState(\"\");\n const [mailBody, setMailBody] = useState(\"\");\n const [mailCopy, setMailCopy] = useState(true);\n const [refundOpen, setRefundOpen] = useState(false);\n const [refundInput, setRefundInput] = useState(\"\");\n const [noteInput, setNoteInput] = useState(\"\");\n const [manualOpen, setManualOpen] = useState(false);\n const [manual, setManual] = useState({ name: \"\", email: \"\", phone: \"\", address: \"\", zip: \"\", city: \"\", shipping: \"\", note: \"\", paid: true, notify: false });\n const [manualLines, setManualLines] = useState<{ productId: string; variantKey: string; qty: number }[]>([]);\n const [producten, setProducten] = useState<ProductKeuze[]>([]);\n const [catNamen, setCatNamen] = useState<Record<string, string>>({});\n\n /** Bestelling bewerken (7.25): klantgegevens/adres altijd; regels + verzendkosten alleen zolang\n * de order nog \"pending\" is (zie editOrder in functions — bedrag wijzigen na betaling gaat\n * via Terugbetalen, niet via dit formulier). */\n const [editOpen, setEditOpen] = useState(false);\n const [editCustomer, setEditCustomer] = useState({ name: \"\", email: \"\", phone: \"\" });\n const [editShipping, setEditShipping] = useState({ address: \"\", zip: \"\", city: \"\" });\n const [editShippingEuro, setEditShippingEuro] = useState(\"\");\n const [editLines, setEditLines] = useState<{ productId: string; variantKey: string; qty: number }[]>([]);\n\n // Producten pas ophalen als een formulier dat ze nodig heeft opengaat (handmatig aanmaken of\n // bewerken): de bestellijst zelf heeft ze niet nodig.\n useEffect(() => {\n if ((!manualOpen && !editOpen) || producten.length > 0) return;\n const db = getDb();\n if (!db) return;\n void getDocs(query(collection(db, \"sites\", siteId, \"products\"), where(\"status\", \"==\", \"active\"))).then((snap) =>\n setProducten(\n snap.docs\n .map((d) => ({ id: d.id, ...(d.data() as Omit<ProductKeuze, \"id\">) }))\n .sort((a, b) => a.name.localeCompare(b.name, \"nl\")),\n ),\n );\n /**\n * Categorieën erbij, want in een winkel waar hetzelfde ontwerp als rompertje, slabbetje én\n * t-shirt bestaat is de productnaam alleen niet genoeg: de lijst toonde vier keer \"Blij blij\"\n * en je kon niet zien welke je aanklikte.\n */\n void getDocs(collection(db, \"sites\", siteId, \"shopCategories\")).then((snap) =>\n setCatNamen(Object.fromEntries(snap.docs.map((d) => [d.id, String((d.data() as { name?: string }).name ?? d.id)]))),\n );\n }, [manualOpen, producten.length, siteId]);\n\n /** Label voor de productkiezer: \"Blij blij — Slabbetje\". */\n const productLabel = (p: ProductKeuze) => {\n const cat = catNamen[p.categoryIds?.[0] ?? \"\"];\n return cat ? `${p.name} — ${cat}` : p.name;\n };\n const [trackingUrl, setTrackingUrl] = useState(\"\");\n const [notify, setNotify] = useState(true);\n\n useEffect(() => {\n const db = getDb();\n if (!db) return;\n return onSnapshot(\n query(collection(db, \"sites\", siteId, \"orders\"), orderBy(\"createdAt\", \"desc\"), limit(300)),\n (snap) => setOrders(snap.docs.map((d) => ({ id: d.id, ...(d.data() as Order) }) as StoredOrder)),\n );\n }, [siteId]);\n\n /** Dashboard-tegels: vandaag / deze week / omzet (betaald + verzonden). */\n const stats = useMemo(() => {\n const now = new Date();\n const startToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();\n const startWeek = startToday - ((now.getDay() + 6) % 7) * 86_400_000;\n const paidish = orders.filter((o) => [\"paid\", \"shipped\"].includes(o.status));\n return {\n today: paidish.filter((o) => (o.createdAt?.toMillis?.() ?? 0) >= startToday).length,\n week: paidish.filter((o) => (o.createdAt?.toMillis?.() ?? 0) >= startWeek).length,\n openPaid: orders.filter((o) => o.status === \"paid\").length,\n revenueCents: paidish.reduce((n, o) => n + o.amount.totalCents, 0),\n };\n }, [orders]);\n\n const visible = useMemo(() => {\n let list = orders;\n if (filter === \"donation\") list = list.filter((o) => o.items.some((i) => i.kind === \"donation\"));\n else if (filter !== \"all\") list = list.filter((o) => o.status === filter);\n const needle = search.trim().toLowerCase();\n if (needle) {\n list = list.filter(\n (o) =>\n o.number.toLowerCase().includes(needle) ||\n o.customer.name.toLowerCase().includes(needle) ||\n o.customer.email.toLowerCase().includes(needle),\n );\n }\n return list;\n }, [orders, filter, search]);\n\n const current = orders.find((o) => o.id === selected) ?? null;\n // Notitieveld volgt de geselecteerde order (en niet andersom: typen mag niet worden overschreven).\n useEffect(() => {\n const o = orders.find((x) => x.id === selected);\n setNoteInput(o?.adminNote ?? \"\");\n }, [selected, orders]);\n\n async function setStatus(order: StoredOrder, status: \"shipped\" | \"cancelled\") {\n setBusy(true);\n try {\n await shopCallable<Record<string, unknown>, { ok: boolean }>(\"updateOrderStatus\")({\n siteId,\n orderId: order.id,\n status,\n notify,\n trackingUrl: status === \"shipped\" && trackingUrl.trim() ? trackingUrl.trim() : undefined,\n });\n toast({\n title: status === \"shipped\" ? \"Gemarkeerd als verzonden\" : \"Bestelling geannuleerd\",\n description: notify ? \"De klant heeft een e-mail ontvangen.\" : undefined,\n tone: \"success\",\n });\n setShipOpen(false);\n setTrackingUrl(\"\");\n } catch (e) {\n toast({ title: \"Status wijzigen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Nog openstaand bedrag (totaal minus wat er al terug is). */\n function openstaand(order: StoredOrder): number {\n return Math.max(0, order.amount.totalCents - (order.refundedCents ?? 0));\n }\n\n async function refund(order: StoredOrder, bedragCents?: number) {\n const rest = openstaand(order);\n const bedrag = bedragCents ?? rest;\n // De provider bij naam noemen: dit beloofde altijd \"via Stripe\", ook op een Mollie-winkel.\n const providerNaam = (order.provider ?? (order.mollie?.paymentId ? \"mollie\" : \"stripe\")) === \"mollie\" ? \"Mollie\" : \"Stripe\";\n const volledig = bedrag >= rest;\n const ok = await confirm({\n title: volledig ? `Bestelling ${order.number} terugbetalen?` : `${formatCents(bedrag)} terugbetalen?`,\n description: volledig\n ? `Het openstaande bedrag (${formatCents(rest)}) wordt via ${providerNaam} teruggestort; de klant krijgt een e-mail.`\n : `Er wordt ${formatCents(bedrag)} van ${formatCents(order.amount.totalCents)} via ${providerNaam} teruggestort. De bestelling blijft verder gewoon staan.`,\n tone: \"danger\",\n confirmLabel: \"Terugbetalen\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string; amountCents?: number }, { ok: boolean }>(\"refundOrder\")({\n siteId,\n orderId: order.id,\n ...(volledig ? {} : { amountCents: bedrag }),\n });\n toast({ title: volledig ? \"Terugbetaling gestart\" : `${formatCents(bedrag)} teruggestort`, tone: \"success\" });\n setRefundOpen(false);\n setRefundInput(\"\");\n } catch (e) {\n toast({ title: \"Terugbetalen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Klant rechtstreeks mailen (huisstijl + kopie naar de winkel + log bij de order). */\n async function mailKlant(order: StoredOrder) {\n if (!mailSubject.trim() || !mailBody.trim()) return;\n setBusy(true);\n try {\n await shopCallable<Record<string, unknown>, { ok: boolean; to: string }>(\"sendCustomerMail\")({\n siteId,\n orderId: order.id,\n subject: mailSubject.trim(),\n body: mailBody.trim(),\n copyToShop: mailCopy,\n });\n toast({ title: \"Bericht verstuurd\", description: order.customer.email, tone: \"success\" });\n setMailOpen(false);\n setMailSubject(\"\");\n setMailBody(\"\");\n } catch (e) {\n toast({ title: \"Versturen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Handmatige bestelling aanmaken (telefonisch/markt/overschrijving). */\n async function createManual() {\n const regels = manualLines.filter((l) => l.productId && l.qty > 0);\n if (!manual.name.trim() || !manual.email.trim() || regels.length === 0) {\n toast({ title: \"Vul naam, e-mail en minstens één product in\", tone: \"error\" });\n return;\n }\n setBusy(true);\n try {\n const res = await shopCallable<Record<string, unknown>, { id: string }>(\"createManualOrder\")({\n siteId,\n items: regels.map((l) => ({ productId: l.productId, variantKey: l.variantKey || undefined, qty: l.qty })),\n customer: { name: manual.name.trim(), email: manual.email.trim(), phone: manual.phone.trim() || undefined },\n shipping: manual.address.trim()\n ? { address: manual.address.trim(), zip: manual.zip.trim(), city: manual.city.trim(), country: \"NL\" }\n : undefined,\n shippingCents: eurosToCents(manual.shipping) ?? 0,\n note: manual.note.trim() || undefined,\n alBetaald: manual.paid,\n notify: manual.notify,\n });\n toast({ title: \"Bestelling aangemaakt\", description: manual.paid ? \"Geboekt als betaald.\" : \"Staat open.\", tone: \"success\" });\n setManualOpen(false);\n setManualLines([]);\n setManual({ name: \"\", email: \"\", phone: \"\", address: \"\", zip: \"\", city: \"\", shipping: \"\", note: \"\", paid: true, notify: false });\n setSelected(res.id);\n } catch (e) {\n toast({ title: \"Aanmaken mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Openstaande bestelling handmatig op betaald zetten (overschrijving ontvangen). */\n async function markPaid(order: StoredOrder) {\n const ok = await confirm({\n title: `Bestelling ${order.number} als betaald boeken?`,\n description: \"Gebruik dit als je het geld buiten de webwinkel om hebt ontvangen (overschrijving, contant, pin). De voorraad wordt afgeboekt en de factuur wordt gemaakt.\",\n confirmLabel: \"Als betaald boeken\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string; notify: boolean }, { ok: boolean }>(\"markOrderPaidManually\")({\n siteId,\n orderId: order.id,\n notify,\n });\n toast({ title: \"Geboekt als betaald\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Interne notitie opslaan (debounced via de knop; klant ziet hem nooit). */\n async function saveNote(order: StoredOrder) {\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string; note: string }, { ok: boolean }>(\"setOrderNote\")({\n siteId,\n orderId: order.id,\n note: noteInput,\n });\n toast({ title: \"Notitie opgeslagen\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Opslaan mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Bewerkformulier vullen met de huidige order — items alleen relevant zolang \"pending\". */\n function openEdit(order: StoredOrder) {\n setEditCustomer({ name: order.customer.name, email: order.customer.email, phone: order.customer.phone ?? \"\" });\n setEditShipping({\n address: order.shipping?.address ?? \"\",\n zip: order.shipping?.zip ?? \"\",\n city: order.shipping?.city ?? \"\",\n });\n setEditShippingEuro(centsToEuroInput(order.amount.shippingCents));\n setEditLines(\n order.status === \"pending\"\n ? order.items.filter((i) => i.kind !== \"donation\").map((i) => ({ productId: i.productId ?? \"\", variantKey: i.variantKey ?? \"\", qty: i.qty }))\n : [],\n );\n setEditOpen(true);\n }\n\n /** Bestelling opslaan — regels/verzendkosten gaan alleen mee als de order nog \"pending\" is. */\n async function saveEdit(order: StoredOrder) {\n if (!editCustomer.name.trim() || !editCustomer.email.trim()) {\n toast({ title: \"Naam en e-mail zijn verplicht\", tone: \"error\" });\n return;\n }\n const magBedragWijzigen = order.status === \"pending\";\n const regels = editLines.filter((l) => l.productId && l.qty > 0);\n if (magBedragWijzigen && regels.length === 0) {\n toast({ title: \"Er moet minstens één product op de bestelling staan\", tone: \"error\" });\n return;\n }\n setBusy(true);\n try {\n await shopCallable<Record<string, unknown>, { ok: boolean }>(\"editOrder\")({\n siteId,\n orderId: order.id,\n customer: {\n name: editCustomer.name.trim(),\n email: editCustomer.email.trim(),\n phone: editCustomer.phone.trim() || undefined,\n },\n // Leeg adresveld = geen wijziging (er is geen route om een adres te wissen — een\n // bestelling met producten heeft er altijd een nodig).\n shipping: editShipping.address.trim()\n ? { address: editShipping.address.trim(), zip: editShipping.zip.trim(), city: editShipping.city.trim(), country: \"NL\" }\n : undefined,\n ...(magBedragWijzigen\n ? {\n items: regels.map((l) => ({ productId: l.productId, variantKey: l.variantKey || undefined, qty: l.qty })),\n shippingCents: eurosToCents(editShippingEuro) ?? 0,\n }\n : {}),\n });\n toast({ title: \"Bestelling bijgewerkt\", tone: \"success\" });\n setEditOpen(false);\n } catch (e) {\n toast({ title: \"Opslaan mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Betaalverzoek: betaallink maken en per mail versturen (zichtbaar bij een openstaande order). */\n async function sendPaymentRequest(order: StoredOrder) {\n const ok = await confirm({\n title: `Betaalverzoek sturen voor ${order.number}?`,\n description: `De klant ontvangt een e-mail met een betaallink voor ${formatCents(order.amount.totalCents)}.`,\n confirmLabel: \"Versturen\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string }, { url: string }>(\"sendPaymentRequest\")({ siteId, orderId: order.id });\n toast({ title: \"Betaalverzoek verstuurd\", description: order.customer.email, tone: \"success\" });\n } catch (e) {\n toast({ title: \"Versturen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Definitief verwijderen — alleen mogelijk voor een geannuleerde order zonder factuurnummer. */\n async function removeOrder(order: StoredOrder) {\n const ok = await confirm({\n title: `Bestelling ${order.number} verwijderen?`,\n description: \"Dit kan niet ongedaan worden gemaakt.\",\n confirmLabel: \"Verwijderen\",\n tone: \"danger\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string }, { ok: boolean }>(\"deleteOrder\")({ siteId, orderId: order.id });\n toast({ title: \"Bestelling verwijderd\", tone: \"success\" });\n setSelected(null);\n } catch (e) {\n toast({ title: \"Verwijderen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n async function resendMail(order: StoredOrder) {\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string }, { ok: boolean }>(\"resendOrderMail\")({ siteId, orderId: order.id });\n toast({ title: \"Bevestigingsmail opnieuw verstuurd\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Mail versturen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n async function signedUrl(order: StoredOrder, path: string): Promise<string | null> {\n try {\n const res = await shopCallable<{ siteId: string; orderId: string; path: string }, { url: string }>(\"getOrderFileUrl\")({\n siteId,\n orderId: order.id,\n path,\n });\n return res.url;\n } catch (e) {\n toast({ title: \"Bestand ophalen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n return null;\n }\n }\n\n async function download(order: StoredOrder, path: string) {\n setBusy(true);\n const url = await signedUrl(order, path);\n setBusy(false);\n if (url) window.open(url, \"_blank\", \"noopener\");\n }\n\n /** Factuur inline tonen in een dialoog (met download/openen-in-tab erin). */\n async function viewInvoice(order: StoredOrder, path: string) {\n setBusy(true);\n const url = await signedUrl(order, path);\n setBusy(false);\n if (url) setInvoice({ url, number: order.number });\n }\n\n function exportCsv() {\n const rows = [\n [\"nummer\", \"datum\", \"status\", \"naam\", \"email\", \"items\", \"subtotaal\", \"korting\", \"verzendkosten\", \"totaal\", \"btw\"],\n ...orders.map((o) => {\n const vat =\n o.items.reduce((n, i) => n + vatOf(i.unitPriceCents * i.qty, i.vatRate ?? 21), 0) +\n (o.amount.shippingCents > 0 ? vatOf(o.amount.shippingCents, 21) : 0);\n return [\n o.number,\n fmtDate(o.createdAt),\n o.status,\n o.customer.name,\n o.customer.email,\n o.items.map((i) => `${i.qty}x ${orderRegelNaam(i)}${i.variantKey ? ` (${i.variantKey})` : \"\"}`).join(\" | \"),\n (o.amount.itemsCents / 100).toFixed(2),\n ((o.amount.discountCents ?? 0) / 100).toFixed(2),\n (o.amount.shippingCents / 100).toFixed(2),\n (o.amount.totalCents / 100).toFixed(2),\n (vat / 100).toFixed(2),\n ];\n }),\n ];\n const csv = rows.map((r) => r.map((c) => `\"${String(c).replaceAll('\"', '\"\"')}\"`).join(\";\")).join(\"\\n\");\n const blob = new Blob([\"\" + csv], { type: \"text/csv;charset=utf-8\" });\n const a = document.createElement(\"a\");\n a.href = URL.createObjectURL(blob);\n a.download = `bestellingen-${siteId}.csv`;\n a.click();\n URL.revokeObjectURL(a.href);\n }\n\n return (\n <div className=\"grid gap-4\">\n {/* Dashboard-tegels */}\n <div className=\"grid grid-cols-2 gap-3 md:grid-cols-4\">\n {[\n { label: \"Vandaag\", value: String(stats.today) },\n { label: \"Deze week\", value: String(stats.week) },\n { label: \"Te verzenden\", value: String(stats.openPaid) },\n { label: \"Omzet (betaald)\", value: formatCents(stats.revenueCents) },\n ].map((s) => (\n <Card key={s.label} className=\"py-3\">\n <p className=\"text-xs text-slate-500\">{s.label}</p>\n <p className=\"text-xl font-bold\">{s.value}</p>\n </Card>\n ))}\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-[340px_1fr]\">\n <Card className=\"h-fit\">\n <div className=\"mb-3 flex items-center justify-between gap-2\">\n <h3 className=\"text-sm font-semibold\">Bestellingen</h3>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={() => setManualOpen(true)}>+ Handmatig</Button>\n <Button size=\"sm\" variant=\"secondary\" onClick={exportCsv} disabled={orders.length === 0}>\n CSV\n </Button>\n </div>\n </div>\n <Input placeholder=\"Zoek op nummer, naam of e-mail…\" value={search} onChange={(e) => setSearch(e.target.value)} className=\"mb-2\" />\n <Select value={filter} onValueChange={setFilter} options={FILTERS} className=\"mb-2\" />\n <ul className=\"grid max-h-[60vh] gap-1 overflow-y-auto\">\n {visible.map((o) => {\n const st = ORDER_STATUS_LABELS[o.status] ?? { label: o.status, tone: \"slate\" as const };\n return (\n <li key={o.id}>\n <button\n onClick={() => {\n setSelected(o.id);\n setShipOpen(false);\n }}\n className={`grid w-full gap-0.5 rounded-lg px-3 py-2 text-left text-sm ${\n o.id === selected ? \"bg-brand-50 text-brand-700\" : \"hover:bg-slate-100\"\n }`}\n >\n <span className=\"flex items-center justify-between gap-2\">\n <span className=\"font-medium\">{o.number}</span>\n <Badge tone={st.tone}>{st.label}</Badge>\n </span>\n <span className=\"flex items-center justify-between gap-2 text-xs text-slate-500\">\n <span className=\"truncate\">{o.customer.name}</span>\n <span>{formatCents(o.amount.totalCents)}</span>\n </span>\n <span className=\"text-xs text-slate-400\">{fmtDate(o.createdAt)}</span>\n </button>\n </li>\n );\n })}\n {visible.length === 0 && <li className=\"px-3 py-2 text-sm text-slate-500\">Geen bestellingen.</li>}\n </ul>\n </Card>\n\n {current ? (\n <Card>\n <div className=\"grid gap-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h3 className=\"text-base font-semibold\">\n {current.number}{\" \"}\n <Badge tone={(ORDER_STATUS_LABELS[current.status] ?? { tone: \"slate\" as const }).tone}>\n {(ORDER_STATUS_LABELS[current.status] ?? { label: current.status }).label}\n </Badge>\n </h3>\n <span className=\"text-sm text-slate-500\">Geplaatst: {fmtDate(current.createdAt)}</span>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Klant</h4>\n <p className=\"text-sm\">\n {current.customer.name}\n <br />\n <button\n type=\"button\"\n className=\"text-brand-700 underline\"\n title=\"Mail deze klant vanuit de winkel (in huisstijl, met een kopie bij de bestelling)\"\n onClick={() => { setMailSubject(`Over je bestelling ${current.number}`); setMailOpen(true); }}\n >\n {current.customer.email}\n </button>\n {current.customer.phone && (\n <>\n <br />\n {current.customer.phone}\n </>\n )}\n </p>\n </div>\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Verzendadres</h4>\n {current.shipping ? (\n <p className=\"text-sm\">\n {current.shipping.address}\n <br />\n {current.shipping.zip} {current.shipping.city} ({current.shipping.country})\n </p>\n ) : (\n <p className=\"text-sm text-slate-500\">Geen verzending (donatie).</p>\n )}\n {current.trackingUrl && (\n <a className=\"text-sm text-brand-700 underline\" href={current.trackingUrl} target=\"_blank\" rel=\"noreferrer\">\n Track & trace ↗\n </a>\n )}\n </div>\n </div>\n\n {current.note && (\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Opmerking van de klant</h4>\n <p className=\"whitespace-pre-wrap text-sm\">{current.note}</p>\n </div>\n )}\n\n {/* Interne notitie: alleen voor de winkelier (\"belt terug over maat\", \"wacht op\n levering leverancier\"). Bewust naast — niet in — de klantopmerking. */}\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Interne notitie</h4>\n <Textarea\n rows={2}\n value={noteInput}\n placeholder=\"Alleen zichtbaar in het beheer…\"\n onChange={(e) => setNoteInput(e.target.value)}\n />\n {noteInput !== (current.adminNote ?? \"\") && (\n <Button size=\"sm\" variant=\"secondary\" className=\"mt-2\" disabled={busy} onClick={() => void saveNote(current)}>\n Notitie opslaan\n </Button>\n )}\n </div>\n\n {/* Wat is er al naar deze klant gestuurd? Zonder dit spoor verdwijnt elke afspraak —\n en sinds 7.25 staan hier ook de AUTOMATISCHE mails (bevestiging, verzonden,\n geannuleerd, terugbetaald, betaalverzoek), inclusief een mislukte poging. */}\n {(current.messages?.length ?? 0) > 0 && (\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Verstuurde berichten</h4>\n <ul className=\"grid gap-2\">\n {[...current.messages!].reverse().map((m, i) => (\n <li key={i} className={`rounded-lg border p-2 text-sm ${m.mislukt ? \"border-red-200 bg-red-50\" : \"border-slate-200\"}`}>\n <p className=\"flex flex-wrap items-center gap-2 font-medium text-slate-800\">\n {m.subject}\n {m.automatisch && <Badge tone={m.mislukt ? \"amber\" : \"slate\"}>{m.mislukt ? \"mislukt\" : \"automatisch\"}</Badge>}\n </p>\n <p className=\"text-xs text-slate-400\">{new Date(m.at).toLocaleString(\"nl-NL\", { dateStyle: \"short\", timeStyle: \"short\" })}</p>\n <p className=\"mt-1 whitespace-pre-wrap text-slate-600\">{m.body}</p>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Regels</h4>\n <table className=\"w-full text-sm\">\n <tbody>\n {current.items.map((i, idx) => (\n <tr key={idx} className=\"border-t border-slate-100 align-top\">\n <td className=\"py-1 pr-2\">\n {i.qty}× {orderRegelNaam(i)}\n {i.variantKey && <span className=\"text-slate-500\"> ({i.variantKey.split(\"|\").join(\" · \")})</span>}\n {i.kind === \"donation\" && <Badge tone=\"amber\">donatie</Badge>}\n {i.personalization &&\n Object.entries(i.personalization).map(([k, v]) => (\n <span key={k} className=\"block text-xs text-slate-600\">\n ↳ {v.text ?? v.fileName ?? \"eigen ontwerp\"}\n {v.imagePath && (\n <button\n type=\"button\"\n className=\"ml-1 text-brand-700 underline\"\n disabled={busy}\n onClick={() => download(current, v.imagePath as string)}\n >\n download\n </button>\n )}\n </span>\n ))}\n </td>\n <td className=\"py-1 text-right\">{formatCents(i.unitPriceCents * i.qty)}</td>\n </tr>\n ))}\n {(current.amount.discountCents ?? 0) > 0 && (\n <tr className=\"border-t border-slate-100 text-slate-500\">\n <td className=\"py-1 pr-2\">Korting{current.discount?.code ? ` (${current.discount.code})` : \"\"}</td>\n <td className=\"py-1 text-right\">−{formatCents(current.amount.discountCents ?? 0)}</td>\n </tr>\n )}\n <tr className=\"border-t border-slate-100 text-slate-500\">\n <td className=\"py-1 pr-2\">Verzendkosten</td>\n <td className=\"py-1 text-right\">\n {current.amount.shippingCents === 0 ? \"gratis\" : formatCents(current.amount.shippingCents)}\n </td>\n </tr>\n <tr className=\"border-t border-slate-200 font-semibold\">\n <td className=\"py-1 pr-2\">Totaal</td>\n <td className=\"py-1 text-right\">{formatCents(current.amount.totalCents)}</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n {current.mail?.error ? (\n <p className=\"rounded-lg bg-amber-50 px-3 py-2 text-sm text-amber-700\">\n Bevestigingsmail mislukt: {current.mail.error}\n </p>\n ) : current.mail?.confirmationSentAt ? (\n /* Geslaagde verzending werd wél vastgelegd maar nergens getoond: je zag alleen\n iets bij een FOUT, en moest dus maar aannemen dat de mail was aangekomen. */\n <p className=\"text-xs text-slate-400\">\n Bevestigingsmail verstuurd op {fmtDate(current.mail.confirmationSentAt)}\n </p>\n ) : null}\n\n {/* Verzenden: track & trace + klant informeren */}\n {shipOpen && current.status === \"paid\" && (\n <div className=\"grid gap-3 rounded-lg border border-slate-200 p-3\">\n <Input\n placeholder=\"Track & trace-link (optioneel, https://…)\"\n value={trackingUrl}\n onChange={(e) => setTrackingUrl(e.target.value)}\n />\n <div className=\"flex items-center gap-4\">\n <Switch checked={notify} onCheckedChange={setNotify} label=\"Klant per e-mail informeren\" />\n <Button size=\"sm\" disabled={busy} onClick={() => setStatus(current, \"shipped\")}>\n Bevestig verzending\n </Button>\n </div>\n </div>\n )}\n\n <div className=\"flex flex-wrap items-center gap-2 border-t border-slate-100 pt-4\">\n {current.status === \"paid\" && !shipOpen && (\n <Button size=\"sm\" onClick={() => setShipOpen(true)}>Markeer als verzonden</Button>\n )}\n {/* Geld buiten de winkel om ontvangen (overschrijving/contant/pin). */}\n {current.status === \"pending\" && (\n <Button size=\"sm\" disabled={busy} onClick={() => void markPaid(current)}>\n Als betaald boeken\n </Button>\n )}\n {/* Betaalverzoek (7.25): een betaallink mailen voor een handmatige order die nog\n niet betaald is, of een online afrekening die de klant nooit afmaakte. */}\n {current.status === \"pending\" && (\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => void sendPaymentRequest(current)}>\n Betaalverzoek sturen\n </Button>\n )}\n {[\"pending\", \"paid\"].includes(current.status) && (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n disabled={busy}\n onClick={async () => {\n const ok = await confirm({\n title: `Bestelling ${current.number} annuleren?`,\n description: notify ? \"De klant ontvangt een e-mail.\" : undefined,\n });\n if (ok) void setStatus(current, \"cancelled\");\n }}\n >\n Annuleer\n </Button>\n )}\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => { setMailSubject(`Over je bestelling ${current.number}`); setMailOpen(true); }}>\n ✉ Klant mailen\n </Button>\n {/* Bewerken (7.25): klantgegevens/adres altijd; regels + verzendkosten alleen\n zolang de order nog \"pending\" is (zie openEdit/saveEdit). */}\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => openEdit(current)}>\n Bewerken\n </Button>\n {(current.status === \"paid\" || current.status === \"shipped\") && (\n <>\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => resendMail(current)}>\n Mail opnieuw versturen\n </Button>\n <Button size=\"sm\" variant=\"danger\" disabled={busy || openstaand(current) === 0} onClick={() => { setRefundInput(centsToEuroInput(openstaand(current))); setRefundOpen(true); }}>\n Terugbetalen\n </Button>\n </>\n )}\n {current.invoicePath && (\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => viewInvoice(current, current.invoicePath as string)}>\n Factuur bekijken\n </Button>\n )}\n {/* Verwijderen (7.25): alleen een geannuleerde bestelling die nooit gefactureerd is\n — anders slaat het een gat in de doorlopende factuurreeks (zie deleteOrder). */}\n {current.status === \"cancelled\" && !current.invoiceNumber && (\n <button\n type=\"button\"\n disabled={busy}\n className=\"rounded px-2 py-1 text-sm text-red-600 hover:underline disabled:opacity-50\"\n onClick={() => void removeOrder(current)}\n >\n Verwijderen\n </button>\n )}\n {current.stripe?.paymentIntentId && (\n <a\n className=\"ml-auto text-sm text-brand-700 underline\"\n href={`https://dashboard.stripe.com/payments/${current.stripe.paymentIntentId}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n Bekijk in Stripe ↗\n </a>\n )}\n </div>\n </div>\n </Card>\n ) : (\n <Card>\n <p className=\"text-sm text-slate-500\">Selecteer een bestelling.</p>\n </Card>\n )}\n </div>\n\n {/* Handmatige bestelling: telefonisch, op de markt, of per bankoverschrijving. */}\n <Dialog open={manualOpen} onOpenChange={setManualOpen}>\n <DialogContent title=\"Bestelling handmatig aanmaken\" width=\"min(92vw, 44rem)\">\n <div className=\"grid gap-3\">\n <p className=\"text-sm text-slate-500\">\n Voor een bestelling die buiten de webwinkel om binnenkwam. Prijzen en btw komen uit je\n productenlijst, dus de omzet en de voorraad blijven kloppen.\n </p>\n <div className=\"grid gap-3 md:grid-cols-3\">\n <Field label=\"Naam\"><Input value={manual.name} onChange={(e) => setManual((p) => ({ ...p, name: e.target.value }))} /></Field>\n <Field label=\"E-mail\"><Input value={manual.email} onChange={(e) => setManual((p) => ({ ...p, email: e.target.value }))} /></Field>\n <Field label=\"Telefoon (optioneel)\"><Input value={manual.phone} onChange={(e) => setManual((p) => ({ ...p, phone: e.target.value }))} /></Field>\n </div>\n\n <div>\n <p className=\"mb-1 text-sm font-medium\">Producten</p>\n <div className=\"grid gap-2\">\n {manualLines.map((l, i) => {\n const prod = producten.find((p) => p.id === l.productId);\n const varianten = (prod?.options?.length ?? 0) > 0 ? (prod?.variants ?? []) : [];\n return (\n <div key={i} className=\"grid grid-cols-[1fr_150px_70px_auto] items-center gap-2\">\n <Select\n value={l.productId}\n onValueChange={(v) => setManualLines((p) => p.map((x, j) => (j === i ? { ...x, productId: v, variantKey: \"\" } : x)))}\n placeholder=\"Kies product…\"\n options={producten.map((p) => ({ value: p.id, label: productLabel(p) }))}\n />\n {varianten.length > 0 ? (\n <Select\n value={l.variantKey}\n onValueChange={(v) => setManualLines((p) => p.map((x, j) => (j === i ? { ...x, variantKey: v } : x)))}\n placeholder=\"Uitvoering…\"\n options={varianten.map((v) => ({ value: v.key, label: v.key.split(\"|\").join(\", \") }))}\n />\n ) : (\n <span className=\"text-xs text-slate-400\">—</span>\n )}\n <Input\n type=\"number\"\n value={String(l.qty)}\n onChange={(e) => setManualLines((p) => p.map((x, j) => (j === i ? { ...x, qty: Math.max(1, Number(e.target.value) || 1) } : x)))}\n />\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setManualLines((p) => p.filter((_, j) => j !== i))}>✕</Button>\n </div>\n );\n })}\n <Button size=\"sm\" variant=\"secondary\" onClick={() => setManualLines((p) => [...p, { productId: \"\", variantKey: \"\", qty: 1 }])}>\n + Regel\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-3 md:grid-cols-4\">\n <Field label=\"Adres\"><Input value={manual.address} onChange={(e) => setManual((p) => ({ ...p, address: e.target.value }))} /></Field>\n <Field label=\"Postcode\"><Input value={manual.zip} onChange={(e) => setManual((p) => ({ ...p, zip: e.target.value }))} /></Field>\n <Field label=\"Plaats\"><Input value={manual.city} onChange={(e) => setManual((p) => ({ ...p, city: e.target.value }))} /></Field>\n <Field label=\"Verzendkosten (€)\"><Input value={manual.shipping} onChange={(e) => setManual((p) => ({ ...p, shipping: e.target.value }))} placeholder=\"0,00\" /></Field>\n </div>\n <Field label=\"Notitie (optioneel)\">\n <Input value={manual.note} onChange={(e) => setManual((p) => ({ ...p, note: e.target.value }))} placeholder=\"bv. telefonisch besteld, contant betaald\" />\n </Field>\n <div className=\"flex flex-wrap gap-4\">\n <Switch checked={manual.paid} onCheckedChange={(v) => setManual((p) => ({ ...p, paid: v }))} label=\"Al betaald (voorraad afboeken + factuur maken)\" />\n <Switch checked={manual.notify} onCheckedChange={(v) => setManual((p) => ({ ...p, notify: v }))} label=\"Bevestigingsmail naar de klant\" />\n </div>\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild><Button variant=\"secondary\">Annuleren</Button></DialogClose>\n <Button disabled={busy} onClick={() => void createManual()}>{busy ? \"Bezig…\" : \"Bestelling aanmaken\"}</Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Bestelling bewerken (7.25). Regels/verzendkosten alleen zichtbaar zolang de bestelling\n nog \"pending\" is — na betaling staat er een factuur op het bedrag, dus dan pas je het\n NIET meer aan met dit formulier (zie de toelichting in editOrder). */}\n <Dialog open={editOpen} onOpenChange={setEditOpen}>\n <DialogContent title={current ? `Bestelling ${current.number} bewerken` : \"Bestelling bewerken\"} width=\"min(92vw, 44rem)\">\n {current && (\n <div className=\"grid gap-3\">\n <div className=\"grid gap-3 md:grid-cols-3\">\n <Field label=\"Naam\"><Input value={editCustomer.name} onChange={(e) => setEditCustomer((p) => ({ ...p, name: e.target.value }))} /></Field>\n <Field label=\"E-mail\"><Input value={editCustomer.email} onChange={(e) => setEditCustomer((p) => ({ ...p, email: e.target.value }))} /></Field>\n <Field label=\"Telefoon (optioneel)\"><Input value={editCustomer.phone} onChange={(e) => setEditCustomer((p) => ({ ...p, phone: e.target.value }))} /></Field>\n </div>\n <div className=\"grid gap-3 md:grid-cols-3\">\n <Field label=\"Adres\"><Input value={editShipping.address} onChange={(e) => setEditShipping((p) => ({ ...p, address: e.target.value }))} /></Field>\n <Field label=\"Postcode\"><Input value={editShipping.zip} onChange={(e) => setEditShipping((p) => ({ ...p, zip: e.target.value }))} /></Field>\n <Field label=\"Plaats\"><Input value={editShipping.city} onChange={(e) => setEditShipping((p) => ({ ...p, city: e.target.value }))} /></Field>\n </div>\n\n {current.status === \"pending\" ? (\n <>\n <div>\n <p className=\"mb-1 text-sm font-medium\">Producten</p>\n <div className=\"grid gap-2\">\n {editLines.map((l, i) => {\n const prod = producten.find((p) => p.id === l.productId);\n const varianten = (prod?.options?.length ?? 0) > 0 ? (prod?.variants ?? []) : [];\n return (\n <div key={i} className=\"grid grid-cols-[1fr_150px_70px_auto] items-center gap-2\">\n <Select\n value={l.productId}\n onValueChange={(v) => setEditLines((p) => p.map((x, j) => (j === i ? { ...x, productId: v, variantKey: \"\" } : x)))}\n placeholder=\"Kies product…\"\n options={producten.map((p) => ({ value: p.id, label: productLabel(p) }))}\n />\n {varianten.length > 0 ? (\n <Select\n value={l.variantKey}\n onValueChange={(v) => setEditLines((p) => p.map((x, j) => (j === i ? { ...x, variantKey: v } : x)))}\n placeholder=\"Uitvoering…\"\n options={varianten.map((v) => ({ value: v.key, label: v.key.split(\"|\").join(\", \") }))}\n />\n ) : (\n <span className=\"text-xs text-slate-400\">—</span>\n )}\n <Input\n type=\"number\"\n value={String(l.qty)}\n onChange={(e) => setEditLines((p) => p.map((x, j) => (j === i ? { ...x, qty: Math.max(1, Number(e.target.value) || 1) } : x)))}\n />\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setEditLines((p) => p.filter((_, j) => j !== i))}>✕</Button>\n </div>\n );\n })}\n <Button size=\"sm\" variant=\"secondary\" onClick={() => setEditLines((p) => [...p, { productId: \"\", variantKey: \"\", qty: 1 }])}>\n + Regel\n </Button>\n </div>\n </div>\n <Field label=\"Verzendkosten (€)\"><Input value={editShippingEuro} onChange={(e) => setEditShippingEuro(e.target.value)} placeholder=\"0,00\" className=\"w-36\" /></Field>\n </>\n ) : (\n <p className=\"text-xs text-slate-500\">\n Deze bestelling is al {ORDER_STATUS_LABELS[current.status]?.label.toLowerCase() ?? current.status}: de regels en verzendkosten\n staan vast (er hoort een factuur op dit bedrag). Gebruik Terugbetalen om het bedrag aan te passen.\n </p>\n )}\n\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild><Button variant=\"secondary\">Annuleren</Button></DialogClose>\n <Button disabled={busy} onClick={() => void saveEdit(current)}>{busy ? \"Bezig…\" : \"Opslaan\"}</Button>\n </div>\n </div>\n )}\n </DialogContent>\n </Dialog>\n\n {/* Klant mailen — huisstijl, kopie naar de winkel, en het bericht komt bij de order te staan. */}\n <Dialog open={mailOpen} onOpenChange={setMailOpen}>\n <DialogContent title={current ? `Mail ${current.customer.name}` : \"Klant mailen\"} width=\"min(92vw, 34rem)\">\n <div className=\"grid gap-3\">\n <p className=\"text-sm text-slate-500\">\n Gaat naar <strong>{current?.customer.email}</strong> in de huisstijl van je site. Antwoorden\n komen binnen op je notificatie-adres.\n </p>\n <Field label=\"Onderwerp\">\n <Input value={mailSubject} onChange={(e) => setMailSubject(e.target.value)} />\n </Field>\n <Field label=\"Bericht\">\n <Textarea rows={7} value={mailBody} onChange={(e) => setMailBody(e.target.value)} placeholder=\"Beste …\" />\n </Field>\n <Switch checked={mailCopy} onCheckedChange={setMailCopy} label=\"Kopie naar mijzelf\" />\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild>\n <Button variant=\"secondary\">Annuleren</Button>\n </DialogClose>\n <Button disabled={busy || !mailSubject.trim() || !mailBody.trim()} onClick={() => current && void mailKlant(current)}>\n {busy ? \"Bezig…\" : \"Versturen\"}\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Terugbetalen — geheel of gedeeltelijk. */}\n <Dialog open={refundOpen} onOpenChange={setRefundOpen}>\n <DialogContent title={current ? `Terugbetalen — ${current.number}` : \"Terugbetalen\"} width=\"min(92vw, 26rem)\">\n <div className=\"grid gap-3\">\n <p className=\"text-sm text-slate-500\">\n Openstaand: <strong>{current ? formatCents(openstaand(current)) : \"—\"}</strong>\n {current && (current.refundedCents ?? 0) > 0 && (\n <> (er is al {formatCents(current.refundedCents as number)} terugbetaald)</>\n )}\n </p>\n <Field label=\"Bedrag (€)\" hint=\"Laat het volledige bedrag staan voor een hele terugbetaling\">\n <Input value={refundInput} onChange={(e) => setRefundInput(e.target.value)} className=\"w-36\" />\n </Field>\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild>\n <Button variant=\"secondary\">Annuleren</Button>\n </DialogClose>\n <Button\n variant=\"danger\"\n disabled={busy}\n onClick={() => {\n if (!current) return;\n const cents = eurosToCents(refundInput);\n if (cents === null || cents <= 0) {\n toast({ title: \"Vul een geldig bedrag in\", tone: \"error\" });\n return;\n }\n void refund(current, Math.min(cents, openstaand(current)));\n }}\n >\n {busy ? \"Bezig…\" : \"Terugbetalen\"}\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n <Dialog open={!!invoice} onOpenChange={(o) => !o && setInvoice(null)}>\n {invoice && (\n <DialogContent title={`Factuur ${invoice.number}`} width=\"min(92vw, 48rem)\">\n <iframe\n title={`Factuur ${invoice.number}`}\n src={invoice.url}\n className=\"h-[70vh] w-full rounded-lg border border-slate-200 bg-white\"\n />\n <div className=\"mt-3 flex items-center gap-2\">\n <a href={invoice.url} target=\"_blank\" rel=\"noreferrer\" download={`factuur-${invoice.number}.pdf`}>\n <Button size=\"sm\" variant=\"secondary\">Downloaden</Button>\n </a>\n <a href={invoice.url} target=\"_blank\" rel=\"noreferrer\" className=\"text-sm text-brand-700 underline\">\n Openen in nieuw tabblad ↗\n </a>\n <DialogClose asChild>\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-auto\">Sluiten</Button>\n </DialogClose>\n </div>\n </DialogContent>\n )}\n </Dialog>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/admin/shop/OrdersTab.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { collection, getDocs, limit, onSnapshot, orderBy, query, where } from \"firebase/firestore\";\nimport type { Timestamp } from \"firebase/firestore\";\nimport { getDb } from \"../../firebase/client\";\nimport { formatCents, orderRegelNaam, type Order } from \"../../schema/shop\";\nimport { Badge, Button, Card, Field, Input, Textarea } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Switch } from \"../ui/switch\";\nimport { useToast } from \"../ui/toast\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport { Dialog, DialogContent, DialogClose } from \"../ui/dialog\";\nimport { ORDER_STATUS_LABELS, centsToEuroInput, eurosToCents, shopCallable } from \"./lib\";\n\n/** Minimale productvorm voor de keuzelijst van een handmatige bestelling. */\ntype ProductKeuze = {\n id: string;\n name: string;\n categoryIds?: string[];\n options?: { name: string }[];\n variants?: { key: string }[];\n};\n\ntype StoredOrder = Order & {\n id: string;\n createdAt?: Timestamp;\n paidAt?: Timestamp;\n shippedAt?: Timestamp;\n refundedAt?: Timestamp;\n mail?: { confirmationSentAt?: Timestamp; error?: string };\n /** Runtime-velden die de Functions erbovenop schrijven (niet in OrderSchema). */\n provider?: \"stripe\" | \"mollie\";\n mollie?: { paymentId?: string };\n};\n\nconst FILTERS = [\n { value: \"all\", label: \"Alles\" },\n { value: \"pending\", label: \"Wacht op betaling\" },\n { value: \"paid\", label: \"Betaald\" },\n { value: \"shipped\", label: \"Verzonden\" },\n { value: \"cancelled\", label: \"Geannuleerd\" },\n { value: \"refunded\", label: \"Terugbetaald\" },\n { value: \"donation\", label: \"Donaties\" },\n];\n\nfunction fmtDate(t?: Timestamp): string {\n if (!t?.toDate) return \"—\";\n return t.toDate().toLocaleString(\"nl-NL\", { dateStyle: \"short\", timeStyle: \"short\" });\n}\n\n/** Btw-component uit een incl.-prijs: totaal × tarief / (100 + tarief). */\nfunction vatOf(cents: number, rate: number): number {\n return Math.round((cents * rate) / (100 + rate));\n}\n\nexport function OrdersTab({ siteId }: { siteId: string }) {\n const { toast } = useToast();\n const confirm = useConfirm();\n const [orders, setOrders] = useState<StoredOrder[]>([]);\n const [selected, setSelected] = useState<string | null>(null);\n const [filter, setFilter] = useState(\"all\");\n const [search, setSearch] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [invoice, setInvoice] = useState<{ url: string; number: string } | null>(null);\n const [shipOpen, setShipOpen] = useState(false);\n const [mailOpen, setMailOpen] = useState(false);\n const [mailSubject, setMailSubject] = useState(\"\");\n const [mailBody, setMailBody] = useState(\"\");\n const [mailCopy, setMailCopy] = useState(true);\n const [refundOpen, setRefundOpen] = useState(false);\n const [refundInput, setRefundInput] = useState(\"\");\n const [noteInput, setNoteInput] = useState(\"\");\n const [manualOpen, setManualOpen] = useState(false);\n const [manual, setManual] = useState({ name: \"\", email: \"\", phone: \"\", address: \"\", zip: \"\", city: \"\", shipping: \"\", note: \"\", paid: true, notify: false });\n const [manualLines, setManualLines] = useState<{ productId: string; variantKey: string; qty: number }[]>([]);\n const [producten, setProducten] = useState<ProductKeuze[]>([]);\n const [catNamen, setCatNamen] = useState<Record<string, string>>({});\n\n /** Bestelling bewerken (7.25): klantgegevens/adres altijd; regels + verzendkosten alleen zolang\n * de order nog \"pending\" is (zie editOrder in functions — bedrag wijzigen na betaling gaat\n * via Terugbetalen, niet via dit formulier). */\n const [editOpen, setEditOpen] = useState(false);\n const [editCustomer, setEditCustomer] = useState({ name: \"\", email: \"\", phone: \"\" });\n const [editShipping, setEditShipping] = useState({ address: \"\", zip: \"\", city: \"\" });\n const [editShippingEuro, setEditShippingEuro] = useState(\"\");\n const [editLines, setEditLines] = useState<{ productId: string; variantKey: string; qty: number }[]>([]);\n\n // Producten pas ophalen als een formulier dat ze nodig heeft opengaat (handmatig aanmaken of\n // bewerken): de bestellijst zelf heeft ze niet nodig.\n useEffect(() => {\n if ((!manualOpen && !editOpen) || producten.length > 0) return;\n const db = getDb();\n if (!db) return;\n void getDocs(query(collection(db, \"sites\", siteId, \"products\"), where(\"status\", \"==\", \"active\"))).then((snap) =>\n setProducten(\n snap.docs\n .map((d) => ({ id: d.id, ...(d.data() as Omit<ProductKeuze, \"id\">) }))\n .sort((a, b) => a.name.localeCompare(b.name, \"nl\")),\n ),\n );\n /**\n * Categorieën erbij, want in een winkel waar hetzelfde ontwerp als rompertje, slabbetje én\n * t-shirt bestaat is de productnaam alleen niet genoeg: de lijst toonde vier keer \"Blij blij\"\n * en je kon niet zien welke je aanklikte.\n */\n void getDocs(collection(db, \"sites\", siteId, \"shopCategories\")).then((snap) =>\n setCatNamen(Object.fromEntries(snap.docs.map((d) => [d.id, String((d.data() as { name?: string }).name ?? d.id)]))),\n );\n }, [manualOpen, producten.length, siteId]);\n\n /** Label voor de productkiezer: \"Blij blij — Slabbetje\". */\n const productLabel = (p: ProductKeuze) => {\n const cat = catNamen[p.categoryIds?.[0] ?? \"\"];\n return cat ? `${p.name} — ${cat}` : p.name;\n };\n const [trackingUrl, setTrackingUrl] = useState(\"\");\n const [notify, setNotify] = useState(true);\n\n useEffect(() => {\n const db = getDb();\n if (!db) return;\n return onSnapshot(\n query(collection(db, \"sites\", siteId, \"orders\"), orderBy(\"createdAt\", \"desc\"), limit(300)),\n (snap) => setOrders(snap.docs.map((d) => ({ id: d.id, ...(d.data() as Order) }) as StoredOrder)),\n );\n }, [siteId]);\n\n /** Dashboard-tegels: vandaag / deze week / omzet (betaald + verzonden). */\n const stats = useMemo(() => {\n const now = new Date();\n const startToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();\n const startWeek = startToday - ((now.getDay() + 6) % 7) * 86_400_000;\n const paidish = orders.filter((o) => [\"paid\", \"shipped\"].includes(o.status));\n return {\n today: paidish.filter((o) => (o.createdAt?.toMillis?.() ?? 0) >= startToday).length,\n week: paidish.filter((o) => (o.createdAt?.toMillis?.() ?? 0) >= startWeek).length,\n openPaid: orders.filter((o) => o.status === \"paid\").length,\n revenueCents: paidish.reduce((n, o) => n + o.amount.totalCents, 0),\n };\n }, [orders]);\n\n const visible = useMemo(() => {\n let list = orders;\n if (filter === \"donation\") list = list.filter((o) => o.items.some((i) => i.kind === \"donation\"));\n else if (filter !== \"all\") list = list.filter((o) => o.status === filter);\n const needle = search.trim().toLowerCase();\n if (needle) {\n list = list.filter(\n (o) =>\n o.number.toLowerCase().includes(needle) ||\n o.customer.name.toLowerCase().includes(needle) ||\n o.customer.email.toLowerCase().includes(needle),\n );\n }\n return list;\n }, [orders, filter, search]);\n\n const current = orders.find((o) => o.id === selected) ?? null;\n // Notitieveld volgt de geselecteerde order (en niet andersom: typen mag niet worden overschreven).\n useEffect(() => {\n const o = orders.find((x) => x.id === selected);\n setNoteInput(o?.adminNote ?? \"\");\n }, [selected, orders]);\n\n async function setStatus(order: StoredOrder, status: \"shipped\" | \"cancelled\") {\n setBusy(true);\n try {\n await shopCallable<Record<string, unknown>, { ok: boolean }>(\"updateOrderStatus\")({\n siteId,\n orderId: order.id,\n status,\n notify,\n trackingUrl: status === \"shipped\" && trackingUrl.trim() ? trackingUrl.trim() : undefined,\n });\n toast({\n title: status === \"shipped\" ? \"Gemarkeerd als verzonden\" : \"Bestelling geannuleerd\",\n description: notify ? \"De klant heeft een e-mail ontvangen.\" : undefined,\n tone: \"success\",\n });\n setShipOpen(false);\n setTrackingUrl(\"\");\n } catch (e) {\n toast({ title: \"Status wijzigen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Nog openstaand bedrag (totaal minus wat er al terug is). */\n function openstaand(order: StoredOrder): number {\n return Math.max(0, order.amount.totalCents - (order.refundedCents ?? 0));\n }\n\n async function refund(order: StoredOrder, bedragCents?: number) {\n const rest = openstaand(order);\n const bedrag = bedragCents ?? rest;\n // De provider bij naam noemen: dit beloofde altijd \"via Stripe\", ook op een Mollie-winkel.\n const providerNaam = (order.provider ?? (order.mollie?.paymentId ? \"mollie\" : \"stripe\")) === \"mollie\" ? \"Mollie\" : \"Stripe\";\n const volledig = bedrag >= rest;\n const ok = await confirm({\n title: volledig ? `Bestelling ${order.number} terugbetalen?` : `${formatCents(bedrag)} terugbetalen?`,\n description: volledig\n ? `Het openstaande bedrag (${formatCents(rest)}) wordt via ${providerNaam} teruggestort; de klant krijgt een e-mail.`\n : `Er wordt ${formatCents(bedrag)} van ${formatCents(order.amount.totalCents)} via ${providerNaam} teruggestort. De bestelling blijft verder gewoon staan.`,\n tone: \"danger\",\n confirmLabel: \"Terugbetalen\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string; amountCents?: number }, { ok: boolean }>(\"refundOrder\")({\n siteId,\n orderId: order.id,\n ...(volledig ? {} : { amountCents: bedrag }),\n });\n toast({ title: volledig ? \"Terugbetaling gestart\" : `${formatCents(bedrag)} teruggestort`, tone: \"success\" });\n setRefundOpen(false);\n setRefundInput(\"\");\n } catch (e) {\n toast({ title: \"Terugbetalen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Klant rechtstreeks mailen (huisstijl + kopie naar de winkel + log bij de order). */\n async function mailKlant(order: StoredOrder) {\n if (!mailSubject.trim() || !mailBody.trim()) return;\n setBusy(true);\n try {\n await shopCallable<Record<string, unknown>, { ok: boolean; to: string }>(\"sendCustomerMail\")({\n siteId,\n orderId: order.id,\n subject: mailSubject.trim(),\n body: mailBody.trim(),\n copyToShop: mailCopy,\n });\n toast({ title: \"Bericht verstuurd\", description: order.customer.email, tone: \"success\" });\n setMailOpen(false);\n setMailSubject(\"\");\n setMailBody(\"\");\n } catch (e) {\n toast({ title: \"Versturen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Handmatige bestelling aanmaken (telefonisch/markt/overschrijving). */\n async function createManual() {\n const regels = manualLines.filter((l) => l.productId && l.qty > 0);\n if (!manual.name.trim() || !manual.email.trim() || regels.length === 0) {\n toast({ title: \"Vul naam, e-mail en minstens één product in\", tone: \"error\" });\n return;\n }\n setBusy(true);\n try {\n const res = await shopCallable<Record<string, unknown>, { id: string }>(\"createManualOrder\")({\n siteId,\n items: regels.map((l) => ({ productId: l.productId, variantKey: l.variantKey || undefined, qty: l.qty })),\n customer: { name: manual.name.trim(), email: manual.email.trim(), phone: manual.phone.trim() || undefined },\n shipping: manual.address.trim()\n ? { address: manual.address.trim(), zip: manual.zip.trim(), city: manual.city.trim(), country: \"NL\" }\n : undefined,\n shippingCents: eurosToCents(manual.shipping) ?? 0,\n note: manual.note.trim() || undefined,\n alBetaald: manual.paid,\n notify: manual.notify,\n });\n toast({ title: \"Bestelling aangemaakt\", description: manual.paid ? \"Geboekt als betaald.\" : \"Staat open.\", tone: \"success\" });\n setManualOpen(false);\n setManualLines([]);\n setManual({ name: \"\", email: \"\", phone: \"\", address: \"\", zip: \"\", city: \"\", shipping: \"\", note: \"\", paid: true, notify: false });\n setSelected(res.id);\n } catch (e) {\n toast({ title: \"Aanmaken mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Openstaande bestelling handmatig op betaald zetten (overschrijving ontvangen). */\n async function markPaid(order: StoredOrder) {\n const ok = await confirm({\n title: `Bestelling ${order.number} als betaald boeken?`,\n description: \"Gebruik dit als je het geld buiten de webwinkel om hebt ontvangen (overschrijving, contant, pin). De voorraad wordt afgeboekt en de factuur wordt gemaakt.\",\n confirmLabel: \"Als betaald boeken\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string; notify: boolean }, { ok: boolean }>(\"markOrderPaidManually\")({\n siteId,\n orderId: order.id,\n notify,\n });\n toast({ title: \"Geboekt als betaald\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Interne notitie opslaan (debounced via de knop; klant ziet hem nooit). */\n async function saveNote(order: StoredOrder) {\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string; note: string }, { ok: boolean }>(\"setOrderNote\")({\n siteId,\n orderId: order.id,\n note: noteInput,\n });\n toast({ title: \"Notitie opgeslagen\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Opslaan mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Bewerkformulier vullen met de huidige order — items alleen relevant zolang \"pending\". */\n function openEdit(order: StoredOrder) {\n setEditCustomer({ name: order.customer.name, email: order.customer.email, phone: order.customer.phone ?? \"\" });\n setEditShipping({\n address: order.shipping?.address ?? \"\",\n zip: order.shipping?.zip ?? \"\",\n city: order.shipping?.city ?? \"\",\n });\n setEditShippingEuro(centsToEuroInput(order.amount.shippingCents));\n setEditLines(\n order.status === \"pending\"\n ? order.items.filter((i) => i.kind === \"product\").map((i) => ({ productId: i.productId ?? \"\", variantKey: i.variantKey ?? \"\", qty: i.qty }))\n : [],\n );\n setEditOpen(true);\n }\n\n /** Bestelling opslaan — regels/verzendkosten gaan alleen mee als de order nog \"pending\" is. */\n async function saveEdit(order: StoredOrder) {\n if (!editCustomer.name.trim() || !editCustomer.email.trim()) {\n toast({ title: \"Naam en e-mail zijn verplicht\", tone: \"error\" });\n return;\n }\n const magBedragWijzigen = order.status === \"pending\";\n const regels = editLines.filter((l) => l.productId && l.qty > 0);\n if (magBedragWijzigen && regels.length === 0) {\n toast({ title: \"Er moet minstens één product op de bestelling staan\", tone: \"error\" });\n return;\n }\n setBusy(true);\n try {\n await shopCallable<Record<string, unknown>, { ok: boolean }>(\"editOrder\")({\n siteId,\n orderId: order.id,\n customer: {\n name: editCustomer.name.trim(),\n email: editCustomer.email.trim(),\n phone: editCustomer.phone.trim() || undefined,\n },\n // Leeg adresveld = geen wijziging (er is geen route om een adres te wissen — een\n // bestelling met producten heeft er altijd een nodig).\n shipping: editShipping.address.trim()\n ? { address: editShipping.address.trim(), zip: editShipping.zip.trim(), city: editShipping.city.trim(), country: \"NL\" }\n : undefined,\n ...(magBedragWijzigen\n ? {\n items: regels.map((l) => ({ productId: l.productId, variantKey: l.variantKey || undefined, qty: l.qty })),\n shippingCents: eurosToCents(editShippingEuro) ?? 0,\n }\n : {}),\n });\n toast({ title: \"Bestelling bijgewerkt\", tone: \"success\" });\n setEditOpen(false);\n } catch (e) {\n toast({ title: \"Opslaan mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Betaalverzoek: betaallink maken en per mail versturen (zichtbaar bij een openstaande order). */\n async function sendPaymentRequest(order: StoredOrder) {\n const ok = await confirm({\n title: `Betaalverzoek sturen voor ${order.number}?`,\n description: `De klant ontvangt een e-mail met een betaallink voor ${formatCents(order.amount.totalCents)}.`,\n confirmLabel: \"Versturen\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string }, { url: string }>(\"sendPaymentRequest\")({ siteId, orderId: order.id });\n toast({ title: \"Betaalverzoek verstuurd\", description: order.customer.email, tone: \"success\" });\n } catch (e) {\n toast({ title: \"Versturen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Definitief verwijderen — alleen mogelijk voor een geannuleerde order zonder factuurnummer. */\n async function removeOrder(order: StoredOrder) {\n const ok = await confirm({\n title: `Bestelling ${order.number} verwijderen?`,\n description: \"Dit kan niet ongedaan worden gemaakt.\",\n confirmLabel: \"Verwijderen\",\n tone: \"danger\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string }, { ok: boolean }>(\"deleteOrder\")({ siteId, orderId: order.id });\n toast({ title: \"Bestelling verwijderd\", tone: \"success\" });\n setSelected(null);\n } catch (e) {\n toast({ title: \"Verwijderen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n async function resendMail(order: StoredOrder) {\n setBusy(true);\n try {\n await shopCallable<{ siteId: string; orderId: string }, { ok: boolean }>(\"resendOrderMail\")({ siteId, orderId: order.id });\n toast({ title: \"Bevestigingsmail opnieuw verstuurd\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Mail versturen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n async function signedUrl(order: StoredOrder, path: string): Promise<string | null> {\n try {\n const res = await shopCallable<{ siteId: string; orderId: string; path: string }, { url: string }>(\"getOrderFileUrl\")({\n siteId,\n orderId: order.id,\n path,\n });\n return res.url;\n } catch (e) {\n toast({ title: \"Bestand ophalen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n return null;\n }\n }\n\n async function download(order: StoredOrder, path: string) {\n setBusy(true);\n const url = await signedUrl(order, path);\n setBusy(false);\n if (url) window.open(url, \"_blank\", \"noopener\");\n }\n\n /** Factuur inline tonen in een dialoog (met download/openen-in-tab erin). */\n async function viewInvoice(order: StoredOrder, path: string) {\n setBusy(true);\n const url = await signedUrl(order, path);\n setBusy(false);\n if (url) setInvoice({ url, number: order.number });\n }\n\n function exportCsv() {\n const rows = [\n [\"nummer\", \"datum\", \"status\", \"naam\", \"email\", \"items\", \"subtotaal\", \"korting\", \"verzendkosten\", \"totaal\", \"btw\"],\n ...orders.map((o) => {\n const vat =\n o.items.reduce((n, i) => n + vatOf(i.unitPriceCents * i.qty, i.vatRate ?? 21), 0) +\n (o.amount.shippingCents > 0 ? vatOf(o.amount.shippingCents, 21) : 0);\n return [\n o.number,\n fmtDate(o.createdAt),\n o.status,\n o.customer.name,\n o.customer.email,\n o.items.map((i) => `${i.qty}x ${orderRegelNaam(i)}${i.variantKey ? ` (${i.variantKey})` : \"\"}`).join(\" | \"),\n (o.amount.itemsCents / 100).toFixed(2),\n ((o.amount.discountCents ?? 0) / 100).toFixed(2),\n (o.amount.shippingCents / 100).toFixed(2),\n (o.amount.totalCents / 100).toFixed(2),\n (vat / 100).toFixed(2),\n ];\n }),\n ];\n const csv = rows.map((r) => r.map((c) => `\"${String(c).replaceAll('\"', '\"\"')}\"`).join(\";\")).join(\"\\n\");\n const blob = new Blob([\"\" + csv], { type: \"text/csv;charset=utf-8\" });\n const a = document.createElement(\"a\");\n a.href = URL.createObjectURL(blob);\n a.download = `bestellingen-${siteId}.csv`;\n a.click();\n URL.revokeObjectURL(a.href);\n }\n\n return (\n <div className=\"grid gap-4\">\n {/* Dashboard-tegels */}\n <div className=\"grid grid-cols-2 gap-3 md:grid-cols-4\">\n {[\n { label: \"Vandaag\", value: String(stats.today) },\n { label: \"Deze week\", value: String(stats.week) },\n { label: \"Te verzenden\", value: String(stats.openPaid) },\n { label: \"Omzet (betaald)\", value: formatCents(stats.revenueCents) },\n ].map((s) => (\n <Card key={s.label} className=\"py-3\">\n <p className=\"text-xs text-slate-500\">{s.label}</p>\n <p className=\"text-xl font-bold\">{s.value}</p>\n </Card>\n ))}\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-[340px_1fr]\">\n <Card className=\"h-fit\">\n <div className=\"mb-3 flex items-center justify-between gap-2\">\n <h3 className=\"text-sm font-semibold\">Bestellingen</h3>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={() => setManualOpen(true)}>+ Handmatig</Button>\n <Button size=\"sm\" variant=\"secondary\" onClick={exportCsv} disabled={orders.length === 0}>\n CSV\n </Button>\n </div>\n </div>\n <Input placeholder=\"Zoek op nummer, naam of e-mail…\" value={search} onChange={(e) => setSearch(e.target.value)} className=\"mb-2\" />\n <Select value={filter} onValueChange={setFilter} options={FILTERS} className=\"mb-2\" />\n <ul className=\"grid max-h-[60vh] gap-1 overflow-y-auto\">\n {visible.map((o) => {\n const st = ORDER_STATUS_LABELS[o.status] ?? { label: o.status, tone: \"slate\" as const };\n return (\n <li key={o.id}>\n <button\n onClick={() => {\n setSelected(o.id);\n setShipOpen(false);\n }}\n className={`grid w-full gap-0.5 rounded-lg px-3 py-2 text-left text-sm ${\n o.id === selected ? \"bg-brand-50 text-brand-700\" : \"hover:bg-slate-100\"\n }`}\n >\n <span className=\"flex items-center justify-between gap-2\">\n <span className=\"font-medium\">{o.number}</span>\n <Badge tone={st.tone}>{st.label}</Badge>\n </span>\n <span className=\"flex items-center justify-between gap-2 text-xs text-slate-500\">\n <span className=\"truncate\">{o.customer.name}</span>\n <span>{formatCents(o.amount.totalCents)}</span>\n </span>\n <span className=\"text-xs text-slate-400\">{fmtDate(o.createdAt)}</span>\n </button>\n </li>\n );\n })}\n {visible.length === 0 && <li className=\"px-3 py-2 text-sm text-slate-500\">Geen bestellingen.</li>}\n </ul>\n </Card>\n\n {current ? (\n <Card>\n <div className=\"grid gap-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h3 className=\"text-base font-semibold\">\n {current.number}{\" \"}\n <Badge tone={(ORDER_STATUS_LABELS[current.status] ?? { tone: \"slate\" as const }).tone}>\n {(ORDER_STATUS_LABELS[current.status] ?? { label: current.status }).label}\n </Badge>\n </h3>\n <span className=\"text-sm text-slate-500\">Geplaatst: {fmtDate(current.createdAt)}</span>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Klant</h4>\n <p className=\"text-sm\">\n {current.customer.name}\n <br />\n <button\n type=\"button\"\n className=\"text-brand-700 underline\"\n title=\"Mail deze klant vanuit de winkel (in huisstijl, met een kopie bij de bestelling)\"\n onClick={() => { setMailSubject(`Over je bestelling ${current.number}`); setMailOpen(true); }}\n >\n {current.customer.email}\n </button>\n {current.customer.phone && (\n <>\n <br />\n {current.customer.phone}\n </>\n )}\n </p>\n </div>\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Verzendadres</h4>\n {current.shipping ? (\n <p className=\"text-sm\">\n {current.shipping.address}\n <br />\n {current.shipping.zip} {current.shipping.city} ({current.shipping.country})\n </p>\n ) : (\n <p className=\"text-sm text-slate-500\">Geen verzending (donatie).</p>\n )}\n {current.trackingUrl && (\n <a className=\"text-sm text-brand-700 underline\" href={current.trackingUrl} target=\"_blank\" rel=\"noreferrer\">\n Track & trace ↗\n </a>\n )}\n </div>\n {/* Alleen tonen als het factuuradres écht afwijkt — anders is het ruis onder een\n verzendadres dat toch al klopt. */}\n {current.billing && (\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Factuuradres</h4>\n <p className=\"text-sm\">\n {current.billing.address}\n <br />\n {current.billing.zip} {current.billing.city} ({current.billing.country})\n </p>\n </div>\n )}\n </div>\n\n {current.note && (\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Opmerking van de klant</h4>\n <p className=\"whitespace-pre-wrap text-sm\">{current.note}</p>\n </div>\n )}\n\n {current.giftWrap && (current.giftWrap.cardText || current.giftWrap.note) && (\n <div className=\"rounded-lg border border-amber-200 bg-amber-50 p-3\">\n <h4 className=\"mb-1 text-sm font-semibold\">🎁 Cadeauverpakking</h4>\n {current.giftWrap.cardText && (\n <p className=\"text-sm\">\n <strong>Op het kaartje:</strong> {current.giftWrap.cardText}\n </p>\n )}\n {current.giftWrap.note && <p className=\"mt-1 whitespace-pre-wrap text-sm\">{current.giftWrap.note}</p>}\n </div>\n )}\n\n {/* Interne notitie: alleen voor de winkelier (\"belt terug over maat\", \"wacht op\n levering leverancier\"). Bewust naast — niet in — de klantopmerking. */}\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Interne notitie</h4>\n <Textarea\n rows={2}\n value={noteInput}\n placeholder=\"Alleen zichtbaar in het beheer…\"\n onChange={(e) => setNoteInput(e.target.value)}\n />\n {noteInput !== (current.adminNote ?? \"\") && (\n <Button size=\"sm\" variant=\"secondary\" className=\"mt-2\" disabled={busy} onClick={() => void saveNote(current)}>\n Notitie opslaan\n </Button>\n )}\n </div>\n\n {/* Wat is er al naar deze klant gestuurd? Zonder dit spoor verdwijnt elke afspraak —\n en sinds 7.25 staan hier ook de AUTOMATISCHE mails (bevestiging, verzonden,\n geannuleerd, terugbetaald, betaalverzoek), inclusief een mislukte poging. */}\n {(current.messages?.length ?? 0) > 0 && (\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Verstuurde berichten</h4>\n <ul className=\"grid gap-2\">\n {[...current.messages!].reverse().map((m, i) => (\n <li key={i} className={`rounded-lg border p-2 text-sm ${m.mislukt ? \"border-red-200 bg-red-50\" : \"border-slate-200\"}`}>\n <p className=\"flex flex-wrap items-center gap-2 font-medium text-slate-800\">\n {m.subject}\n {m.automatisch && <Badge tone={m.mislukt ? \"amber\" : \"slate\"}>{m.mislukt ? \"mislukt\" : \"automatisch\"}</Badge>}\n </p>\n <p className=\"text-xs text-slate-400\">{new Date(m.at).toLocaleString(\"nl-NL\", { dateStyle: \"short\", timeStyle: \"short\" })}</p>\n <p className=\"mt-1 whitespace-pre-wrap text-slate-600\">{m.body}</p>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n <div>\n <h4 className=\"mb-1 text-sm font-semibold\">Regels</h4>\n <table className=\"w-full text-sm\">\n <tbody>\n {current.items.map((i, idx) => (\n <tr key={idx} className=\"border-t border-slate-100 align-top\">\n <td className=\"py-1 pr-2\">\n {i.qty}× {orderRegelNaam(i)}\n {i.variantKey && <span className=\"text-slate-500\"> ({i.variantKey.split(\"|\").join(\" · \")})</span>}\n {i.kind === \"donation\" && <Badge tone=\"amber\">donatie</Badge>}\n {i.kind === \"giftwrap\" && <Badge tone=\"amber\">cadeau</Badge>}\n {i.personalization &&\n Object.entries(i.personalization).map(([k, v]) => (\n <span key={k} className=\"block text-xs text-slate-600\">\n ↳ {v.text ?? v.fileName ?? \"eigen ontwerp\"}\n {v.imagePath && (\n <button\n type=\"button\"\n className=\"ml-1 text-brand-700 underline\"\n disabled={busy}\n onClick={() => download(current, v.imagePath as string)}\n >\n download\n </button>\n )}\n </span>\n ))}\n </td>\n <td className=\"py-1 text-right\">{formatCents(i.unitPriceCents * i.qty)}</td>\n </tr>\n ))}\n {(current.amount.discountCents ?? 0) > 0 && (\n <tr className=\"border-t border-slate-100 text-slate-500\">\n <td className=\"py-1 pr-2\">Korting{current.discount?.code ? ` (${current.discount.code})` : \"\"}</td>\n <td className=\"py-1 text-right\">−{formatCents(current.amount.discountCents ?? 0)}</td>\n </tr>\n )}\n <tr className=\"border-t border-slate-100 text-slate-500\">\n <td className=\"py-1 pr-2\">Verzendkosten</td>\n <td className=\"py-1 text-right\">\n {current.amount.shippingCents === 0 ? \"gratis\" : formatCents(current.amount.shippingCents)}\n </td>\n </tr>\n <tr className=\"border-t border-slate-200 font-semibold\">\n <td className=\"py-1 pr-2\">Totaal</td>\n <td className=\"py-1 text-right\">{formatCents(current.amount.totalCents)}</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n {current.mail?.error ? (\n <p className=\"rounded-lg bg-amber-50 px-3 py-2 text-sm text-amber-700\">\n Bevestigingsmail mislukt: {current.mail.error}\n </p>\n ) : current.mail?.confirmationSentAt ? (\n /* Geslaagde verzending werd wél vastgelegd maar nergens getoond: je zag alleen\n iets bij een FOUT, en moest dus maar aannemen dat de mail was aangekomen. */\n <p className=\"text-xs text-slate-400\">\n Bevestigingsmail verstuurd op {fmtDate(current.mail.confirmationSentAt)}\n </p>\n ) : null}\n\n {/* Verzenden: track & trace + klant informeren */}\n {shipOpen && current.status === \"paid\" && (\n <div className=\"grid gap-3 rounded-lg border border-slate-200 p-3\">\n <Input\n placeholder=\"Track & trace-link (optioneel, https://…)\"\n value={trackingUrl}\n onChange={(e) => setTrackingUrl(e.target.value)}\n />\n <div className=\"flex items-center gap-4\">\n <Switch checked={notify} onCheckedChange={setNotify} label=\"Klant per e-mail informeren\" />\n <Button size=\"sm\" disabled={busy} onClick={() => setStatus(current, \"shipped\")}>\n Bevestig verzending\n </Button>\n </div>\n </div>\n )}\n\n <div className=\"flex flex-wrap items-center gap-2 border-t border-slate-100 pt-4\">\n {current.status === \"paid\" && !shipOpen && (\n <Button size=\"sm\" onClick={() => setShipOpen(true)}>Markeer als verzonden</Button>\n )}\n {/* Geld buiten de winkel om ontvangen (overschrijving/contant/pin). */}\n {current.status === \"pending\" && (\n <Button size=\"sm\" disabled={busy} onClick={() => void markPaid(current)}>\n Als betaald boeken\n </Button>\n )}\n {/* Betaalverzoek (7.25): een betaallink mailen voor een handmatige order die nog\n niet betaald is, of een online afrekening die de klant nooit afmaakte. */}\n {current.status === \"pending\" && (\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => void sendPaymentRequest(current)}>\n Betaalverzoek sturen\n </Button>\n )}\n {[\"pending\", \"paid\"].includes(current.status) && (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n disabled={busy}\n onClick={async () => {\n const ok = await confirm({\n title: `Bestelling ${current.number} annuleren?`,\n description: notify ? \"De klant ontvangt een e-mail.\" : undefined,\n });\n if (ok) void setStatus(current, \"cancelled\");\n }}\n >\n Annuleer\n </Button>\n )}\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => { setMailSubject(`Over je bestelling ${current.number}`); setMailOpen(true); }}>\n ✉ Klant mailen\n </Button>\n {/* Bewerken (7.25): klantgegevens/adres altijd; regels + verzendkosten alleen\n zolang de order nog \"pending\" is (zie openEdit/saveEdit). */}\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => openEdit(current)}>\n Bewerken\n </Button>\n {(current.status === \"paid\" || current.status === \"shipped\") && (\n <>\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => resendMail(current)}>\n Mail opnieuw versturen\n </Button>\n <Button size=\"sm\" variant=\"danger\" disabled={busy || openstaand(current) === 0} onClick={() => { setRefundInput(centsToEuroInput(openstaand(current))); setRefundOpen(true); }}>\n Terugbetalen\n </Button>\n </>\n )}\n {current.invoicePath && (\n <Button size=\"sm\" variant=\"secondary\" disabled={busy} onClick={() => viewInvoice(current, current.invoicePath as string)}>\n Factuur bekijken\n </Button>\n )}\n {/* Verwijderen (7.25): alleen een geannuleerde bestelling die nooit gefactureerd is\n — anders slaat het een gat in de doorlopende factuurreeks (zie deleteOrder). */}\n {current.status === \"cancelled\" && !current.invoiceNumber && (\n <button\n type=\"button\"\n disabled={busy}\n className=\"rounded px-2 py-1 text-sm text-red-600 hover:underline disabled:opacity-50\"\n onClick={() => void removeOrder(current)}\n >\n Verwijderen\n </button>\n )}\n {current.stripe?.paymentIntentId && (\n <a\n className=\"ml-auto text-sm text-brand-700 underline\"\n href={`https://dashboard.stripe.com/payments/${current.stripe.paymentIntentId}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n Bekijk in Stripe ↗\n </a>\n )}\n </div>\n </div>\n </Card>\n ) : (\n <Card>\n <p className=\"text-sm text-slate-500\">Selecteer een bestelling.</p>\n </Card>\n )}\n </div>\n\n {/* Handmatige bestelling: telefonisch, op de markt, of per bankoverschrijving. */}\n <Dialog open={manualOpen} onOpenChange={setManualOpen}>\n <DialogContent title=\"Bestelling handmatig aanmaken\" width=\"min(92vw, 44rem)\">\n <div className=\"grid gap-3\">\n <p className=\"text-sm text-slate-500\">\n Voor een bestelling die buiten de webwinkel om binnenkwam. Prijzen en btw komen uit je\n productenlijst, dus de omzet en de voorraad blijven kloppen.\n </p>\n <div className=\"grid gap-3 md:grid-cols-3\">\n <Field label=\"Naam\"><Input value={manual.name} onChange={(e) => setManual((p) => ({ ...p, name: e.target.value }))} /></Field>\n <Field label=\"E-mail\"><Input value={manual.email} onChange={(e) => setManual((p) => ({ ...p, email: e.target.value }))} /></Field>\n <Field label=\"Telefoon (optioneel)\"><Input value={manual.phone} onChange={(e) => setManual((p) => ({ ...p, phone: e.target.value }))} /></Field>\n </div>\n\n <div>\n <p className=\"mb-1 text-sm font-medium\">Producten</p>\n <div className=\"grid gap-2\">\n {manualLines.map((l, i) => {\n const prod = producten.find((p) => p.id === l.productId);\n const varianten = (prod?.options?.length ?? 0) > 0 ? (prod?.variants ?? []) : [];\n return (\n <div key={i} className=\"grid grid-cols-[1fr_150px_70px_auto] items-center gap-2\">\n <Select\n value={l.productId}\n onValueChange={(v) => setManualLines((p) => p.map((x, j) => (j === i ? { ...x, productId: v, variantKey: \"\" } : x)))}\n placeholder=\"Kies product…\"\n options={producten.map((p) => ({ value: p.id, label: productLabel(p) }))}\n />\n {varianten.length > 0 ? (\n <Select\n value={l.variantKey}\n onValueChange={(v) => setManualLines((p) => p.map((x, j) => (j === i ? { ...x, variantKey: v } : x)))}\n placeholder=\"Uitvoering…\"\n options={varianten.map((v) => ({ value: v.key, label: v.key.split(\"|\").join(\", \") }))}\n />\n ) : (\n <span className=\"text-xs text-slate-400\">—</span>\n )}\n <Input\n type=\"number\"\n value={String(l.qty)}\n onChange={(e) => setManualLines((p) => p.map((x, j) => (j === i ? { ...x, qty: Math.max(1, Number(e.target.value) || 1) } : x)))}\n />\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setManualLines((p) => p.filter((_, j) => j !== i))}>✕</Button>\n </div>\n );\n })}\n <Button size=\"sm\" variant=\"secondary\" onClick={() => setManualLines((p) => [...p, { productId: \"\", variantKey: \"\", qty: 1 }])}>\n + Regel\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-3 md:grid-cols-4\">\n <Field label=\"Adres\"><Input value={manual.address} onChange={(e) => setManual((p) => ({ ...p, address: e.target.value }))} /></Field>\n <Field label=\"Postcode\"><Input value={manual.zip} onChange={(e) => setManual((p) => ({ ...p, zip: e.target.value }))} /></Field>\n <Field label=\"Plaats\"><Input value={manual.city} onChange={(e) => setManual((p) => ({ ...p, city: e.target.value }))} /></Field>\n <Field label=\"Verzendkosten (€)\"><Input value={manual.shipping} onChange={(e) => setManual((p) => ({ ...p, shipping: e.target.value }))} placeholder=\"0,00\" /></Field>\n </div>\n <Field label=\"Notitie (optioneel)\">\n <Input value={manual.note} onChange={(e) => setManual((p) => ({ ...p, note: e.target.value }))} placeholder=\"bv. telefonisch besteld, contant betaald\" />\n </Field>\n <div className=\"flex flex-wrap gap-4\">\n <Switch checked={manual.paid} onCheckedChange={(v) => setManual((p) => ({ ...p, paid: v }))} label=\"Al betaald (voorraad afboeken + factuur maken)\" />\n <Switch checked={manual.notify} onCheckedChange={(v) => setManual((p) => ({ ...p, notify: v }))} label=\"Bevestigingsmail naar de klant\" />\n </div>\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild><Button variant=\"secondary\">Annuleren</Button></DialogClose>\n <Button disabled={busy} onClick={() => void createManual()}>{busy ? \"Bezig…\" : \"Bestelling aanmaken\"}</Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Bestelling bewerken (7.25). Regels/verzendkosten alleen zichtbaar zolang de bestelling\n nog \"pending\" is — na betaling staat er een factuur op het bedrag, dus dan pas je het\n NIET meer aan met dit formulier (zie de toelichting in editOrder). */}\n <Dialog open={editOpen} onOpenChange={setEditOpen}>\n <DialogContent title={current ? `Bestelling ${current.number} bewerken` : \"Bestelling bewerken\"} width=\"min(92vw, 44rem)\">\n {current && (\n <div className=\"grid gap-3\">\n <div className=\"grid gap-3 md:grid-cols-3\">\n <Field label=\"Naam\"><Input value={editCustomer.name} onChange={(e) => setEditCustomer((p) => ({ ...p, name: e.target.value }))} /></Field>\n <Field label=\"E-mail\"><Input value={editCustomer.email} onChange={(e) => setEditCustomer((p) => ({ ...p, email: e.target.value }))} /></Field>\n <Field label=\"Telefoon (optioneel)\"><Input value={editCustomer.phone} onChange={(e) => setEditCustomer((p) => ({ ...p, phone: e.target.value }))} /></Field>\n </div>\n <div className=\"grid gap-3 md:grid-cols-3\">\n <Field label=\"Adres\"><Input value={editShipping.address} onChange={(e) => setEditShipping((p) => ({ ...p, address: e.target.value }))} /></Field>\n <Field label=\"Postcode\"><Input value={editShipping.zip} onChange={(e) => setEditShipping((p) => ({ ...p, zip: e.target.value }))} /></Field>\n <Field label=\"Plaats\"><Input value={editShipping.city} onChange={(e) => setEditShipping((p) => ({ ...p, city: e.target.value }))} /></Field>\n </div>\n\n {current.status === \"pending\" ? (\n <>\n <div>\n <p className=\"mb-1 text-sm font-medium\">Producten</p>\n <div className=\"grid gap-2\">\n {editLines.map((l, i) => {\n const prod = producten.find((p) => p.id === l.productId);\n const varianten = (prod?.options?.length ?? 0) > 0 ? (prod?.variants ?? []) : [];\n return (\n <div key={i} className=\"grid grid-cols-[1fr_150px_70px_auto] items-center gap-2\">\n <Select\n value={l.productId}\n onValueChange={(v) => setEditLines((p) => p.map((x, j) => (j === i ? { ...x, productId: v, variantKey: \"\" } : x)))}\n placeholder=\"Kies product…\"\n options={producten.map((p) => ({ value: p.id, label: productLabel(p) }))}\n />\n {varianten.length > 0 ? (\n <Select\n value={l.variantKey}\n onValueChange={(v) => setEditLines((p) => p.map((x, j) => (j === i ? { ...x, variantKey: v } : x)))}\n placeholder=\"Uitvoering…\"\n options={varianten.map((v) => ({ value: v.key, label: v.key.split(\"|\").join(\", \") }))}\n />\n ) : (\n <span className=\"text-xs text-slate-400\">—</span>\n )}\n <Input\n type=\"number\"\n value={String(l.qty)}\n onChange={(e) => setEditLines((p) => p.map((x, j) => (j === i ? { ...x, qty: Math.max(1, Number(e.target.value) || 1) } : x)))}\n />\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setEditLines((p) => p.filter((_, j) => j !== i))}>✕</Button>\n </div>\n );\n })}\n <Button size=\"sm\" variant=\"secondary\" onClick={() => setEditLines((p) => [...p, { productId: \"\", variantKey: \"\", qty: 1 }])}>\n + Regel\n </Button>\n </div>\n </div>\n <Field label=\"Verzendkosten (€)\"><Input value={editShippingEuro} onChange={(e) => setEditShippingEuro(e.target.value)} placeholder=\"0,00\" className=\"w-36\" /></Field>\n </>\n ) : (\n <p className=\"text-xs text-slate-500\">\n Deze bestelling is al {ORDER_STATUS_LABELS[current.status]?.label.toLowerCase() ?? current.status}: de regels en verzendkosten\n staan vast (er hoort een factuur op dit bedrag). Gebruik Terugbetalen om het bedrag aan te passen.\n </p>\n )}\n\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild><Button variant=\"secondary\">Annuleren</Button></DialogClose>\n <Button disabled={busy} onClick={() => void saveEdit(current)}>{busy ? \"Bezig…\" : \"Opslaan\"}</Button>\n </div>\n </div>\n )}\n </DialogContent>\n </Dialog>\n\n {/* Klant mailen — huisstijl, kopie naar de winkel, en het bericht komt bij de order te staan. */}\n <Dialog open={mailOpen} onOpenChange={setMailOpen}>\n <DialogContent title={current ? `Mail ${current.customer.name}` : \"Klant mailen\"} width=\"min(92vw, 34rem)\">\n <div className=\"grid gap-3\">\n <p className=\"text-sm text-slate-500\">\n Gaat naar <strong>{current?.customer.email}</strong> in de huisstijl van je site. Antwoorden\n komen binnen op je notificatie-adres.\n </p>\n <Field label=\"Onderwerp\">\n <Input value={mailSubject} onChange={(e) => setMailSubject(e.target.value)} />\n </Field>\n <Field label=\"Bericht\">\n <Textarea rows={7} value={mailBody} onChange={(e) => setMailBody(e.target.value)} placeholder=\"Beste …\" />\n </Field>\n <Switch checked={mailCopy} onCheckedChange={setMailCopy} label=\"Kopie naar mijzelf\" />\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild>\n <Button variant=\"secondary\">Annuleren</Button>\n </DialogClose>\n <Button disabled={busy || !mailSubject.trim() || !mailBody.trim()} onClick={() => current && void mailKlant(current)}>\n {busy ? \"Bezig…\" : \"Versturen\"}\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Terugbetalen — geheel of gedeeltelijk. */}\n <Dialog open={refundOpen} onOpenChange={setRefundOpen}>\n <DialogContent title={current ? `Terugbetalen — ${current.number}` : \"Terugbetalen\"} width=\"min(92vw, 26rem)\">\n <div className=\"grid gap-3\">\n <p className=\"text-sm text-slate-500\">\n Openstaand: <strong>{current ? formatCents(openstaand(current)) : \"—\"}</strong>\n {current && (current.refundedCents ?? 0) > 0 && (\n <> (er is al {formatCents(current.refundedCents as number)} terugbetaald)</>\n )}\n </p>\n <Field label=\"Bedrag (€)\" hint=\"Laat het volledige bedrag staan voor een hele terugbetaling\">\n <Input value={refundInput} onChange={(e) => setRefundInput(e.target.value)} className=\"w-36\" />\n </Field>\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild>\n <Button variant=\"secondary\">Annuleren</Button>\n </DialogClose>\n <Button\n variant=\"danger\"\n disabled={busy}\n onClick={() => {\n if (!current) return;\n const cents = eurosToCents(refundInput);\n if (cents === null || cents <= 0) {\n toast({ title: \"Vul een geldig bedrag in\", tone: \"error\" });\n return;\n }\n void refund(current, Math.min(cents, openstaand(current)));\n }}\n >\n {busy ? \"Bezig…\" : \"Terugbetalen\"}\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n\n <Dialog open={!!invoice} onOpenChange={(o) => !o && setInvoice(null)}>\n {invoice && (\n <DialogContent title={`Factuur ${invoice.number}`} width=\"min(92vw, 48rem)\">\n <iframe\n title={`Factuur ${invoice.number}`}\n src={invoice.url}\n className=\"h-[70vh] w-full rounded-lg border border-slate-200 bg-white\"\n />\n <div className=\"mt-3 flex items-center gap-2\">\n <a href={invoice.url} target=\"_blank\" rel=\"noreferrer\" download={`factuur-${invoice.number}.pdf`}>\n <Button size=\"sm\" variant=\"secondary\">Downloaden</Button>\n </a>\n <a href={invoice.url} target=\"_blank\" rel=\"noreferrer\" className=\"text-sm text-brand-700 underline\">\n Openen in nieuw tabblad ↗\n </a>\n <DialogClose asChild>\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-auto\">Sluiten</Button>\n </DialogClose>\n </div>\n </DialogContent>\n )}\n </Dialog>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -5,6 +5,7 @@ import { doc, getDoc } from "firebase/firestore";
5
5
  import { getDb, getFirebaseApp } from "../../firebase/client.js";
6
6
  import { callable } from "../../firebase/functionsClient.js";
7
7
  import { Button, Card, Field, Input } from "../ui/primitives.js";
8
+ import { Switch } from "../ui/switch.js";
8
9
  import { useToast } from "../ui/toast.js";
9
10
  import { centsToEuroInput, eurosToCents } from "./lib.js";
10
11
  function ShopSettingsTab({ siteId }) {
@@ -12,6 +13,7 @@ function ShopSettingsTab({ siteId }) {
12
13
  const [cfg, setCfg] = useState(null);
13
14
  const [shipInput, setShipInput] = useState("");
14
15
  const [freeInput, setFreeInput] = useState("");
16
+ const [giftWrapInput, setGiftWrapInput] = useState("");
15
17
  const [busy, setBusy] = useState(false);
16
18
  const [zones, setZones] = useState([]);
17
19
  useEffect(() => {
@@ -24,6 +26,7 @@ function ShopSettingsTab({ siteId }) {
24
26
  setCfg(c);
25
27
  setShipInput(centsToEuroInput(c.shippingFlatCents ?? 495));
26
28
  setFreeInput(c.shippingFreeFromCents ? centsToEuroInput(c.shippingFreeFromCents) : "");
29
+ setGiftWrapInput(centsToEuroInput(c.giftWrapPriceCents ?? 0));
27
30
  setZones(
28
31
  (c.shippingZones ?? []).map((z) => ({
29
32
  naam: z.naam,
@@ -43,6 +46,7 @@ function ShopSettingsTab({ siteId }) {
43
46
  ...cfg,
44
47
  shippingFlatCents: eurosToCents(shipInput) ?? 495,
45
48
  shippingFreeFromCents: freeInput.trim() === "" ? 0 : eurosToCents(freeInput) ?? 0,
49
+ giftWrapPriceCents: eurosToCents(giftWrapInput) ?? 0,
46
50
  shippingZones: zones.filter((z) => z.naam.trim()).map((z) => ({
47
51
  naam: z.naam.trim(),
48
52
  // "BE, DE" → ["BE","DE"]; leeg = de "overige landen"-zone.
@@ -101,6 +105,20 @@ function ShopSettingsTab({ siteId }) {
101
105
  ] })
102
106
  ] })
103
107
  ] }),
108
+ /* @__PURE__ */ jsxs(Card, { children: [
109
+ /* @__PURE__ */ jsx("h3", { className: "mb-3 text-sm font-semibold", children: "Cadeauverpakking" }),
110
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-4", children: [
111
+ /* @__PURE__ */ jsx(
112
+ Switch,
113
+ {
114
+ checked: cfg.giftWrapEnabled ?? false,
115
+ onCheckedChange: (v) => setCfg((p) => ({ ...p, giftWrapEnabled: v })),
116
+ label: "Cadeauverpakking aanbieden bij het afrekenen"
117
+ }
118
+ ),
119
+ cfg.giftWrapEnabled && /* @__PURE__ */ jsx(Field, { label: "Meerprijs (\u20AC)", hint: "Komt als aparte regel op de bestelling en de factuur; de klant kan een kaartjestekst + opmerking meegeven", children: /* @__PURE__ */ jsx(Input, { value: giftWrapInput, onChange: (e) => setGiftWrapInput(e.target.value), placeholder: "3,95", className: "w-32" }) })
120
+ ] })
121
+ ] }),
104
122
  /* @__PURE__ */ jsxs(Card, { children: [
105
123
  /* @__PURE__ */ jsx("h3", { className: "mb-1 text-sm font-semibold", children: "Bedrijfsgegevens (factuur)" }),
106
124
  /* @__PURE__ */ jsx("p", { className: "mb-3 text-xs text-slate-500", children: "Deze gegevens komen op de factuur-PDF die klanten bij hun bestelling krijgen." }),