2026-04-05 11:51:30 +00:00

155 lines
6.9 KiB
JavaScript

document.addEventListener('DOMContentLoaded', () => {
const body = document.body;
const savedTheme = localStorage.getItem('store-theme');
if (savedTheme === 'dark' || savedTheme === 'light') {
body.dataset.theme = savedTheme;
}
const themeToggle = document.querySelector('[data-theme-toggle]');
const helpToggle = document.querySelector('[data-help-toggle]');
const helpClose = document.querySelector('[data-help-close]');
const helpDrawer = document.querySelector('[data-help-drawer]');
themeToggle?.addEventListener('click', () => {
const nextTheme = body.dataset.theme === 'dark' ? 'light' : 'dark';
body.dataset.theme = nextTheme;
localStorage.setItem('store-theme', nextTheme);
});
const toggleHelp = (open) => {
if (!helpDrawer) return;
helpDrawer.classList.toggle('is-open', open);
helpDrawer.setAttribute('aria-hidden', open ? 'false' : 'true');
};
helpToggle?.addEventListener('click', () => toggleHelp(true));
helpClose?.addEventListener('click', () => toggleHelp(false));
helpDrawer?.addEventListener('click', (event) => {
if (event.target === helpDrawer) {
toggleHelp(false);
}
});
document.querySelectorAll('[data-auto-hide]').forEach((alert) => {
setTimeout(() => {
alert.style.transition = 'opacity .3s ease';
alert.style.opacity = '0';
setTimeout(() => alert.remove(), 320);
}, 3200);
});
const formatSyp = (value) => `${new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value || 0)} ل.س`;
const rateInput = document.querySelector('[data-rate-input]');
const ratePreview = document.querySelector('[data-rate-preview]');
const equipmentUsd = document.querySelector('[data-equipment-usd]');
const equipmentPreview = document.querySelector('[data-equipment-preview]');
const invoiceEquipment = document.querySelector('[data-invoice-equipment]');
const invoiceQty = document.querySelector('[data-invoice-qty]');
const invoiceStock = document.querySelector('[data-invoice-stock]');
const invoiceTotal = document.querySelector('[data-invoice-total]');
const currentRate = () => {
const parsed = parseFloat(rateInput?.value || body.dataset.currentRate || '0');
return Number.isFinite(parsed) ? parsed : 0;
};
const updateRatePreview = () => {
if (ratePreview) ratePreview.textContent = formatSyp(currentRate());
};
const updateEquipmentPreview = () => {
if (!equipmentPreview) return;
const usd = parseFloat(equipmentUsd?.value || '0');
equipmentPreview.textContent = usd > 0 && currentRate() > 0 ? formatSyp(usd * currentRate()) : '—';
};
const updateInvoicePreview = () => {
if (!invoiceTotal) return;
const option = invoiceEquipment?.selectedOptions?.[0];
const price = parseFloat(option?.dataset.price || '0');
const stock = parseInt(option?.dataset.stock || '0', 10);
const qty = parseInt(invoiceQty?.value || '0', 10);
if (invoiceStock) {
invoiceStock.textContent = option && option.value ? `${stock} قطعة` : '—';
}
if (!option || !option.value || price <= 0 || qty <= 0 || currentRate() <= 0) {
invoiceTotal.textContent = '—';
return;
}
invoiceTotal.textContent = formatSyp(price * qty * currentRate());
};
rateInput?.addEventListener('input', () => {
body.dataset.currentRate = rateInput.value;
updateRatePreview();
updateEquipmentPreview();
updateInvoicePreview();
});
equipmentUsd?.addEventListener('input', updateEquipmentPreview);
invoiceEquipment?.addEventListener('change', updateInvoicePreview);
invoiceQty?.addEventListener('input', updateInvoicePreview);
updateRatePreview();
updateEquipmentPreview();
updateInvoicePreview();
const printableInvoice = document.querySelector('[data-printable-invoice]');
const printButton = document.querySelector('[data-print-invoice]');
const exportSelectedButton = document.querySelector('[data-export-selected-pdf]');
const exportInvoicesButton = document.querySelector('[data-export-invoices]');
const invoicesTable = document.querySelector('[data-invoices-table]');
const openPrintWindow = (title, html) => {
const win = window.open('', '_blank', 'width=900,height=700');
if (!win) return;
win.document.write(`<!doctype html><html lang="ar" dir="rtl"><head><meta charset="utf-8"><title>${title}</title><style>
body{font-family:Segoe UI,Tahoma,Arial,sans-serif;padding:24px;background:#fff;color:#111827}
.sheet{max-width:720px;margin:0 auto;border:1px solid #d7dfeb;border-radius:24px;padding:24px}
.sheet *{direction:rtl;text-align:right}
.invoice-row,.invoice-item,.invoice-note{margin-bottom:10px;padding:12px 14px;border:1px solid #d7dfeb;border-radius:14px;background:#f8fafc}
</style></head><body><div class="sheet">${html}</div><script>window.onload=function(){window.print();setTimeout(function(){window.close();},150);};</script></body></html>`);
win.document.close();
};
printButton?.addEventListener('click', () => {
if (!printableInvoice) return;
openPrintWindow('فاتورة', printableInvoice.innerHTML);
});
const hasPdf = () => window.jspdf && window.jspdf.jsPDF;
exportSelectedButton?.addEventListener('click', () => {
if (!hasPdf() || !printableInvoice) return;
const { jsPDF } = window.jspdf;
const doc = new jsPDF({ unit: 'pt', format: 'a4' });
doc.setFontSize(18);
doc.text('Selected Invoice', 40, 50);
const lines = printableInvoice.innerText.split('\n').map((line) => line.trim()).filter(Boolean);
let y = 90;
lines.forEach((line) => {
const chunks = doc.splitTextToSize(line, 500);
doc.text(chunks, 40, y);
y += chunks.length * 18 + 8;
});
doc.save('selected-invoice.pdf');
});
exportInvoicesButton?.addEventListener('click', () => {
if (!hasPdf() || !invoicesTable) return;
const { jsPDF } = window.jspdf;
const doc = new jsPDF({ orientation: 'landscape', unit: 'pt', format: 'a4' });
doc.setFontSize(16);
doc.text('Invoices Register', 40, 40);
const rows = Array.from(invoicesTable.querySelectorAll('tbody tr')).map((tr) =>
Array.from(tr.querySelectorAll('td')).map((td) => td.innerText.replace(/\s+/g, ' ').trim())
).filter((row) => row.length === 5);
doc.autoTable({
head: [['Invoice', 'Customer', 'Total USD', 'Total SYP', 'Created At']],
body: rows,
startY: 60,
styles: { fontSize: 10 },
headStyles: { fillColor: [15, 118, 110] }
});
doc.save('invoices-register.pdf');
});
});