155 lines
6.9 KiB
JavaScript
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');
|
|
});
|
|
});
|