'); body.push(''); w.document.open(); w.document.write; /** ================= Filters (unchanged) ================= */ const [filterStatus, setFilterStatus] = useState('All'); const [searchQuery, setSearchQuery] = useState(''); const filteredInvoices = useMemo(() => { const q = (searchQuery || '').toLowerCase().trim(); return (invoices || []) .filter((inv) => (filterStatus === 'All' ? true : String(inv.status) === filterStatus)) .filter((inv) => { if (!q) return true; const s = (v) => String(v !== null && v !== void 0 ? v : '').toLowerCase(); return (s(inv.businessName).includes(q) || s(inv.contactPerson).includes(q) || s(inv.invoiceNumber).includes(q) || s(inv.notes).includes(q) || s(inv.status).includes(q)); }); }, [invoices, filterStatus, searchQuery]); /** ================= Payment Link ================= */ function generatePaymentLink(inv) { return __awaiter(this, void 0, void 0, function* () { try { const did = getCookie('connected_did'); if (!did) { setSnackMsg('⚠️ Payment Kit not connected — connect it in your Dashboard to generate links.'); setSnackOpen(true); return; } // 🧩 normalize item list whether it's array or string let invoiceItems = []; if (Array.isArray(inv.items)) { invoiceItems = inv.items; } else if (typeof inv.items === 'string') { // parse string like "B-Boy Sticker (1 × $5), Caddy Sticker (2 × $5)" invoiceItems = inv.items.split(',').map((x) => { const m = x.match(/(.*)\((\d+)\s*×\s*\$?([\d.]+)\)/); return { name: m ? m[1].trim() : x.trim(), qty: m ? Number(m[2]) : 1, price: m ? Number(m[3]) : 0, }; }); } const lineItems = invoiceItems .map((it) => { var _a; const normalizedName = String((it === null || it === void 0 ? void 0 : it.name) || '').trim().toLowerCase(); // find matching pricingKey from nameToPricingKey const matchedKey = Object.keys(nameToPricingKey).find((k) => k.toLowerCase().trim() === normalizedName) || normalizedName.replace(/\s+/g, '').replace(/[^a-z0-9]/gi, ''); // get entry from priceTable const group = (priceTable === null || priceTable === void 0 ? void 0 : priceTable[nameToPricingKey[it.name]]) || (priceTable === null || priceTable === void 0 ? void 0 : priceTable[matchedKey]); if (!group) return null; const sizeKey = group['OneSize'] ? 'OneSize' : Object.keys(group)[0]; // prefer stored invoice currency over current selection const activeCurrency = inv.currency || currency; const entry = (_a = group === null || group === void 0 ? void 0 : group[sizeKey]) === null || _a === void 0 ? void 0 : _a[activeCurrency]; const priceId = entry === null || entry === void 0 ? void 0 : entry.priceId; return priceId ? { price_id: priceId, quantity: Number(it.qty || 1) } : null; }) .filter(Boolean); if (!lineItems.length) { alert('No valid priceIds found for this invoice. Ensure item names match your products.json.'); console.log('DEBUG: invoiceItems', invoiceItems); console.log('DEBUG: priceTable keys', Object.keys(priceTable)); console.log('DEBUG: nameToPricingKey', nameToPricingKey); return; } setLinkLoading(true); yield fetch('/payment-kit/', { credentials: 'include', cache: 'no-store' }); let csrf = getCsrf(); if (!csrf) { yield fetch(`/api/session?t=${Date.now()}`, { credentials: 'include', cache: 'no-store' }); csrf = getCsrf(); } const res = yield fetch('/payment-kit/api/checkout-sessions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-csrf-token': csrf, }, credentials: 'include', body: JSON.stringify({ create_mine: true, mode: 'payment', line_items: lineItems, success_url: `${window.location.origin}?success=true`, cancel_url: `${window.location.origin}?cancel=true`, metadata: { source: 'InvoiceManager', invoiceNumber: inv.invoiceNumber || '', customer: inv.businessName || '', total: inv.total || '', currency, }, }), }); const out = yield res.json(); if (!(out === null || out === void 0 ? void 0 : out.url)) throw new Error('Failed to generate payment link'); window.location.assign(out.url); // ✅ mobile-safe redirect setSnackMsg('Redirecting to payment page…'); setSnackOpen(true); } catch (err) { alert(err.message || 'Payment link error'); } finally { setLinkLoading(false); } }); } /** ================= Render (UI untouched) ================= */ return (React.createElement(Box, { sx: { p: { xs: 2, md: 4 }, bgcolor: isDark ? '#111' : '#f5f5f5', position: 'relative' } }, React.createElement(Chip, { label: loggedIn ? 'Logged In' : 'Not Connected', color: loggedIn ? 'success' : 'warning', size: "small", onClick: handleBadgeClick, sx: { position: 'absolute', top: 12, right: 12, opacity: 0, // 👈 invisible pointerEvents: 'none', // 👈 can't click or tab to it zIndex: -1, // 👈 behind everything } }), React.createElement(Paper, { sx: { p: 4, mb: 4, backgroundColor: isDark ? '#1e1e1e' : '#fff', color: isDark ? '#eee' : '#333', borderRadius: 2, } }, React.createElement(Typography, { variant: "h4", sx: { mb: 3, textAlign: 'center', fontWeight: 'bold', color: '#1976d2' } }, title), React.createElement(Stack, { spacing: 2, component: "form", onSubmit: handleCreateOrUpdate }, loadingCustomers ? (React.createElement(CircularProgress, { sx: { mx: 'auto' } })) : (React.createElement(Select, { value: selectedCustomerId, onChange: (e) => setSelectedCustomerId(e.target.value), displayEmpty: true, fullWidth: true, sx: inputStyle }, React.createElement(MenuItem, { value: "" }, "Select Customer"), customers.map((c) => (React.createElement(MenuItem, { key: c.id, value: c.id }, c.businessName, " ", c.contactPerson ? `(${c.contactPerson})` : ''))))), React.createElement(Grid, { container: true, spacing: 2 }, React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(Select, { value: status, onChange: (e) => setStatus(e.target.value), fullWidth: true, sx: inputStyle }, React.createElement(MenuItem, { value: "Draft" }, "Draft"), React.createElement(MenuItem, { value: "Sent" }, "Sent"), React.createElement(MenuItem, { value: "Paid" }, "Paid"), React.createElement(MenuItem, { value: "Void" }, "Void"))), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(TextField, Object.assign({ label: "Due Date", type: "date", value: toInputDate(dueDate), onChange: (e) => setDueDate(e.target.value), fullWidth: true }, datePadProps, { sx: inputStyle })))), React.createElement(Grid, { container: true, spacing: 2, sx: { alignItems: 'center' } }, React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(TextField, { label: "Currency", select: true, value: currency, onChange: (e) => !editingInvoice && setCurrency(e.target.value), fullWidth: true, disabled: !!editingInvoice, sx: inputStyle }, React.createElement(MenuItem, { value: "USD" }, "USD"), React.createElement(MenuItem, { value: "USDC" }, "USDC"), React.createElement(MenuItem, { value: "ABT" }, "ABT"))), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(FormControlLabel, { control: React.createElement(Switch, { checked: useStandard, onChange: (e) => setUseStandard(e.target.checked), color: "primary" }), label: React.createElement(Typography, { variant: "subtitle2", sx: { fontWeight: 600, color: isDark ? '#ccc' : '#444', letterSpacing: '0.03em', } }, useStandard ? 'Using Catalog Products' : 'Manual Entry Mode') }))), React.createElement(Box, null, React.createElement(Typography, { variant: "h6", sx: { mb: 1.5, color: isDark ? '#ddd' : '#444' } }, "Line Items"), React.createElement(Stack, { spacing: 2 }, items.map((row, idx) => (React.createElement(Paper, { key: idx, sx: { p: 2, backgroundColor: isDark ? '#222' : '#fafafa', borderRadius: 2 } }, React.createElement(Grid, { container: true, spacing: 1.5 }, React.createElement(Grid, { item: true, xs: 12, sm: 6 }, useStandard ? (React.createElement(Select, { value: row.name || '', onChange: (e) => { const displayName = e.target.value; const pricingKey = nameToPricingKey[displayName] || displayName; // fallback: key equals display name onSelectStandardItem(idx, pricingKey, displayName); }, fullWidth: true, displayEmpty: true, sx: inputStyle }, React.createElement(MenuItem, { value: "" }, "Select Product"), productsFlat.map((p) => { // show current-currency amount using OneSize (or first size) const sizes = (priceTable === null || priceTable === void 0 ? void 0 : priceTable[p.pricingKey]) ? Object.keys(priceTable[p.pricingKey]) : ['OneSize']; const sizeKey = sizes.includes('OneSize') ? 'OneSize' : sizes[0]; const entry = getPricingEntry(p.pricingKey, sizeKey, currency); const amt = entry === null || entry === void 0 ? void 0 : entry.amount; return (React.createElement(MenuItem, { key: `${p.pricingKey}-${p.name}`, value: p.name }, p.name, amt != null ? ` ($${amt})` : '')); }))) : (React.createElement(TextField, { label: "Item Name", value: row.name, onChange: (e) => setItemField(idx, 'name', e.target.value), fullWidth: true, sx: inputStyle }))), React.createElement(Grid, { item: true, xs: 6, sm: 2 }, React.createElement(TextField, { label: "Qty", type: "number", value: row.qty, onChange: (e) => setItemField(idx, 'qty', e.target.value), fullWidth: true, sx: inputStyle })), React.createElement(Grid, { item: true, xs: 6, sm: 2 }, React.createElement(TextField, { label: "Unit Price", type: "number", value: row.price, onChange: (e) => setItemField(idx, 'price', e.target.value), fullWidth: true, sx: inputStyle })), React.createElement(Grid, { item: true, xs: 12, sm: 2 }, React.createElement(TextField, { label: "Line Total", value: (Number(row.qty || 0) * Number(row.price || 0)).toFixed(2), fullWidth: true, InputProps: { readOnly: true }, sx: inputStyle }))), React.createElement(Stack, { direction: "row", spacing: 1.5, justifyContent: "flex-end", sx: { mt: 2 } }, React.createElement(Button, { variant: "outlined", color: "error", onClick: () => removeItem(idx), disabled: items.length <= 1 }, "Remove"), React.createElement(Button, { variant: "contained", onClick: addItem }, "Add Item"))))))), React.createElement(Grid, { container: true, spacing: 2 }, React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(TextField, { label: "Discount ($)", type: "number", value: discount, onChange: (e) => setDiscount(e.target.value), fullWidth: true, sx: inputStyle })), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(TextField, { label: "Tax ($)", type: "number", value: tax, onChange: (e) => setTax(e.target.value), fullWidth: true, sx: inputStyle }))), React.createElement(TextField, { label: "Notes", value: notes, onChange: (e) => setNotes(e.target.value), fullWidth: true, multiline: true, rows: 3, sx: inputStyle }), React.createElement(Paper, { sx: { p: 2, backgroundColor: isDark ? '#222' : '#fafafa', borderRadius: 2 } }, React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Typography, null, "Subtotal"), React.createElement(Typography, null, "$", subtotal.toFixed(2))), React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Typography, null, "Discount"), React.createElement(Typography, null, "-$", Number(discount || 0).toFixed(2))), React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Typography, null, "Tax"), React.createElement(Typography, null, "$", Number(tax || 0).toFixed(2))), React.createElement(Divider, { sx: { my: 1 } }), React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Typography, { fontWeight: "bold" }, "Total"), React.createElement(Typography, { fontWeight: "bold" }, "$", total.toFixed(2)))), React.createElement(Stack, { direction: { xs: 'column', sm: 'row' }, spacing: 2, sx: { mt: 1 } }, React.createElement(Button, { type: "submit", variant: "contained", fullWidth: true }, editingInvoice ? 'Update Invoice' : 'Create Invoice'), React.createElement(Button, { variant: "outlined", onClick: resetForm, fullWidth: true }, "Clear")))), React.createElement(Paper, { sx: { p: 3, backgroundColor: isDark ? '#1e1e1e' : '#fff', borderRadius: 2 } }, React.createElement(Typography, { variant: "h5", sx: { textAlign: 'center', mb: 2, color: '#1976d2', fontWeight: 'bold' } }, "Invoice Dashboard"), React.createElement(TextField, { label: "Search Invoices (name, number, status)", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), fullWidth: true, size: "small", sx: Object.assign({ mb: 2 }, inputStyle) }), React.createElement(Stack, { direction: "row", spacing: 1.5, justifyContent: "center", flexWrap: "wrap", mb: 1.5 }, ['All', 'Draft', 'Sent', 'Paid', 'Void'].map((s) => (React.createElement(Chip, { key: s, label: s, onClick: () => setFilterStatus(s), sx: { cursor: 'pointer', backgroundColor: filterStatus === s ? '#1976d2' : '#e0e0e0', color: filterStatus === s ? '#fff' : '#333', } })))), loadingInvoices ? (React.createElement(CircularProgress, { sx: { display: 'block', mx: 'auto' } })) : (React.createElement(Stack, { spacing: 2 }, filteredInvoices.map((inv) => (React.createElement(Box, { key: inv.id, sx: { p: 2, backgroundColor: isDark ? '#222' : '#fafafa', borderRadius: 2 } }, React.createElement(Typography, { variant: "h6", sx: { fontWeight: 'bold' } }, inv.businessName), React.createElement(Typography, { variant: "body2" }, "Invoice #: ", inv.invoiceNumber), React.createElement(Typography, { variant: "body2" }, "Status: ", inv.status), React.createElement(Typography, { variant: "body2" }, "Created: ", displayDate(inv.createdDate)), React.createElement(Typography, { variant: "body2" }, "Due: ", displayDate(inv.dueDate)), React.createElement(Typography, { variant: "body2" }, "Total: $", Number(inv.total || 0).toFixed(2)), React.createElement(Stack, { direction: { xs: 'column', sm: 'row' }, spacing: 1.5, sx: { mt: 1, flexWrap: 'wrap' } }, React.createElement(Button, { variant: "outlined", onClick: () => loadInvoiceToEdit(inv) }, "Edit"), React.createElement(Button, { variant: "contained", onClick: () => downloadPDF(inv) }, "Download PDF"), React.createElement(Button, { variant: "outlined", onClick: () => openView(inv) }, "View"), React.createElement(Button, { variant: "outlined", onClick: () => printInvoice(inv) }, "Print"), paymentLink && (React.createElement(Button, { variant: "outlined", color: "success", onClick: () => generatePaymentLink(inv), disabled: linkLoading }, linkLoading ? React.createElement(CircularProgress, { size: 16 }) : 'Payment Link')), React.createElement(Button, { variant: "outlined", color: "error", onClick: () => deleteInvoice(inv.id) }, "Delete")))))))), React.createElement(Dialog, { open: viewOpen, onClose: closeView, fullWidth: true, maxWidth: "md" }, React.createElement(DialogTitle, null, "View Invoice", React.createElement(IconButton, { onClick: closeView, sx: { position: 'absolute', right: 8, top: 8 } }, "\u00D7")), React.createElement(DialogContent, { dividers: true }, !viewInvoice ? (React.createElement(Typography, null, "Loading\u2026")) : (React.createElement(Box, { sx: { maxWidth: 800, mx: 'auto' } }, icon && (React.createElement(Box, { sx: { textAlign: 'center', mb: 1.5 } }, React.createElement("img", { src: icon, alt: "Logo", style: { maxWidth: 160, maxHeight: 80 } }))), React.createElement(Typography, { variant: "h5", align: "center", sx: { mb: 2, fontWeight: 700 } }, "Invoice"), React.createElement(Grid, { container: true, spacing: 1.5, sx: { mb: 1 } }, React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(Paper, { sx: { p: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Invoice #"), React.createElement(Typography, null, viewInvoice.invoiceNumber || '—'))), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(Paper, { sx: { p: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Status"), React.createElement(Typography, null, viewInvoice.status || '—'))), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(Paper, { sx: { p: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Business"), React.createElement(Typography, null, viewInvoice.businessName || '—'))), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(Paper, { sx: { p: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Contact"), React.createElement(Typography, null, viewInvoice.contactPerson || '—'))), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(Paper, { sx: { p: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Created"), React.createElement(Typography, null, displayDate(viewInvoice.createdDate) || '—'))), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(Paper, { sx: { p: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Due"), React.createElement(Typography, null, displayDate(viewInvoice.dueDate) || '—'))), React.createElement(Grid, { item: true, xs: 12, sm: 6 }, React.createElement(Paper, { sx: { p: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Currency"), React.createElement(Typography, null, viewInvoice.currency || 'USD')))), React.createElement(Paper, { sx: { p: 1.5, mb: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Items"), React.createElement(Typography, { sx: { whiteSpace: 'pre-wrap' } }, String(viewInvoice.items || ''))), React.createElement(Paper, { sx: { p: 1.5, mb: 1.5 } }, React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Typography, null, "Subtotal"), React.createElement(Typography, null, "$", Number(viewInvoice.subtotal || 0).toFixed(2))), React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Typography, null, "Discount"), React.createElement(Typography, null, "-$", Number(viewInvoice.discount || 0).toFixed(2))), React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Typography, null, "Tax"), React.createElement(Typography, null, "$", Number(viewInvoice.tax || 0).toFixed(2))), React.createElement(Divider, { sx: { my: 1 } }), React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Typography, { fontWeight: "bold" }, "Total"), React.createElement(Typography, { fontWeight: "bold" }, "$", Number(viewInvoice.total || 0).toFixed(2)))), viewInvoice.notes && (React.createElement(Paper, { sx: { p: 1.5, mb: 1.5 } }, React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Notes"), React.createElement(Typography, { sx: { whiteSpace: 'pre-wrap' } }, String(viewInvoice.notes)))), signature && (React.createElement(Box, { sx: { mt: 3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center', gap: 1 } }, React.createElement("img", { src: signature, alt: "Signature", style: { maxWidth: 200, maxHeight: 60 } }), React.createElement(Typography, { variant: "caption", color: "text.secondary" }, "Authorized Signature")))))), React.createElement(DialogActions, null, viewInvoice && (React.createElement(React.Fragment, null, React.createElement(Button, { onClick: () => printInvoice(viewInvoice) }, "Print"), React.createElement(Button, { variant: "contained", onClick: () => downloadPDF(viewInvoice) }, "Download PDF"))), React.createElement(Button, { onClick: closeView }, "Close"))), React.createElement(Snackbar, { open: snackOpen, autoHideDuration: 2200, onClose: () => setSnackOpen(false), anchorOrigin: { vertical: 'bottom', horizontal: 'center' } }, React.createElement(Alert, { severity: "success", sx: { width: '100%' } }, snackMsg)))); }; } // handle possible module.exports if (module.exports && module.exports !== moduleExports) { // if module.exports is used, use it first return typeof module.exports === 'object' ? module.exports : { default: module.exports }; } // ensure a default export if (!('default' in exports) && Object.keys(exports).length === 0) { // module has no exports, return null to indicate invalid return null; } return exports; };