editing barcode module

This commit is contained in:
Flatlogic Bot 2026-02-03 10:01:55 +00:00
parent 00d9114ba0
commit e473add476

View File

@ -6,7 +6,7 @@
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="h4 mb-0"><i class="bi bi-upc-scan me-2"></i>Barcode Label Printing</h2>
<button onclick="window.print()" class="btn btn-primary">
<i class="bi bi-printer me-2"></i>Print Labels
<i class="bi bi-printer me-2"></i>Print Label Queue
</button>
</div>
@ -33,20 +33,32 @@
</thead>
<tbody>
{% for product in products %}
<tr class="product-row" data-name="{{ product.name_en }}" data-sku="{{ product.sku }}">
<tr class="product-row" data-name="{{ product.name_en }}" data-name-ar="{{ product.name_ar }}" data-sku="{{ product.sku }}">
<td>
<div class="fw-bold">{{ product.name_en }}</div>
<small class="text-muted">{{ product.name_ar }}</small>
</td>
<td><code>{{ product.sku }}</code></td>
<td>
<button class="btn btn-sm btn-outline-primary add-to-queue"
data-id="{{ product.id }}"
data-name="{{ product.name_en }}"
data-sku="{{ product.sku }}"
data-price="{{ product.price }}">
<i class="bi bi-plus"></i>
</button>
<div class="btn-group">
<button class="btn btn-sm btn-outline-primary add-to-queue"
data-id="{{ product.id }}"
data-name="{{ product.name_en }}" data-name-ar="{{ product.name_ar }}"
data-sku="{{ product.sku }}"
data-price="{{ product.price }}"
title="Add to queue">
<i class="bi bi-plus"></i>
</button>
<button class="btn btn-sm btn-outline-success direct-print-btn"
onclick="directPrintFromRow(this)"
data-id="{{ product.id }}"
data-name="{{ product.name_en }}" data-name-ar="{{ product.name_ar }}"
data-sku="{{ product.sku }}"
data-price="{{ product.price }}"
title="Direct Print Single Label">
<i class="bi bi-printer"></i>
</button>
</div>
</td>
</tr>
{% endfor %}
@ -120,8 +132,11 @@
<!-- Live Preview -->
<div class="card shadow-sm border-0">
<div class="card-header bg-white py-3">
<div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">3. Live Preview (Single Label)</h5>
<button class="btn btn-sm btn-success" onclick="printSingleFromPreview()">
<i class="bi bi-printer me-1"></i>Print This Label
</button>
</div>
<div class="card-body text-center bg-light p-5">
<div id="previewContainer" class="d-inline-block bg-white shadow-sm p-3 border">
@ -154,6 +169,8 @@
.print-only { display: none; }
}
@media print {
#sidebar, .top-navbar, .navbar, footer { display: none !important; }
#content, main { margin: 0 !important; padding: 0 !important; width: 100% !important; }
.no-print { display: none !important; }
.print-only { display: block; }
body { margin: 0; padding: 0; background: white; -webkit-print-color-adjust: exact; }
@ -163,6 +180,22 @@
margin: 0;
}
/* Direct Print Mode: Remove A4 constraints */
body.direct-print-mode @page {
size: auto;
margin: 0;
}
body.direct-print-mode .label-sheet {
width: auto;
margin: 0;
padding: 0;
}
body.direct-print-mode .label-item {
border: none !important;
margin: 0 !important;
page-break-after: always;
}
.label-sheet {
display: flex;
flex-wrap: wrap;
@ -369,18 +402,19 @@
const labelQueueBody = document.getElementById('labelQueue');
const emptyQueue = document.getElementById('emptyQueue');
const printArea = document.getElementById('printArea');
let lastAddedProduct = null;
// Add to Queue
document.querySelectorAll('.add-to-queue').forEach(btn => {
btn.addEventListener('click', () => {
const product = {
id: btn.dataset.id,
name: btn.dataset.name,
name: btn.dataset.name, nameAr: btn.dataset.nameAr,
sku: btn.dataset.sku,
price: btn.dataset.price,
qty: 1
};
lastAddedProduct = product;
const existing = queue.find(p => p.id === product.id);
if (existing) {
existing.qty++;
@ -402,7 +436,7 @@
labelQueueBody.innerHTML = queue.map((p, index) => `
<tr>
<td>
<div class="fw-bold small">${p.name}</div>
<div class="fw-bold small">${p.nameAr ? p.nameAr + " | " : ""}${p.name}</div>
<code class="text-muted small">${p.sku}</code>
</td>
<td>
@ -446,14 +480,20 @@
// Preview Logic
function updatePreview() {
if (queue.length === 0) return;
const lastProduct = queue[queue.length - 1];
let product = null;
if (queue.length > 0) {
product = queue[queue.length - 1];
} else if (lastAddedProduct) {
product = lastAddedProduct;
}
document.querySelector('.preview-name').innerText = lastProduct.name;
document.querySelector('.preview-sku').innerText = lastProduct.sku;
document.querySelector('.preview-price').innerText = 'OMR ' + parseFloat(lastProduct.price).toFixed(3);
if (!product) return;
JsBarcode("#previewBarcode", lastProduct.sku, {
document.querySelector('.preview-name').innerHTML = (product.nameAr ? `<div class='text-end'>${product.nameAr}</div>` : '') + `<div>${product.name}</div>`;
document.querySelector('.preview-sku').innerText = product.sku;
document.querySelector('.preview-price').innerText = 'OMR ' + parseFloat(product.price).toFixed(3);
JsBarcode("#previewBarcode", product.sku, {
format: "CODE128",
width: 2,
height: 40,
@ -467,8 +507,88 @@
document.querySelector('.preview-sku').style.display = document.getElementById('showSKU').checked ? '' : 'none';
}
// Prepare Print Area
function preparePrint() {
// Direct Print Logic
function directPrintFromRow(btn) {
const product = {
id: btn.dataset.id,
name: btn.dataset.name, nameAr: btn.dataset.nameAr,
sku: btn.dataset.sku,
price: btn.dataset.price,
qty: 1
};
performDirectPrint(product);
}
function printSingleFromPreview() {
let product = null;
if (queue.length > 0) {
product = queue[queue.length - 1];
} else if (lastAddedProduct) {
product = lastAddedProduct;
}
if (product) performDirectPrint(product);
}
function performDirectPrint(product) {
document.body.classList.add('direct-print-mode');
printArea.innerHTML = '';
const labelType = document.getElementById('labelType').value;
const showName = document.getElementById('showName').checked;
const showPrice = document.getElementById('showPrice').checked;
const showSKU = document.getElementById('showSKU').checked;
const sheet = document.createElement('div');
sheet.className = 'label-sheet';
const label = document.createElement('div');
label.className = `label-item label-${labelType}`;
let content = '';
if (labelType === 'l7656') {
if (showName) content += `<div class="label-text" style="max-width: 40px">${product.nameAr ? product.nameAr + " " : ""}${product.name}</div>`;
content += `<svg id="direct-barcode"></svg>`;
if (showPrice) content += `<div class="label-text label-price">${parseFloat(product.price).toFixed(3)}</div>`;
} else {
if (showName) { if (product.nameAr) content += `<div class="label-text">${product.nameAr}</div>`; content += `<div class="label-text">${product.name}</div>`; }
content += `<svg id="direct-barcode"></svg>`;
if (showSKU || showPrice) {
content += `<div class="label-text d-flex justify-content-between">`;
if (showSKU) content += `<span>${product.sku}</span>`;
if (showPrice) content += `<span class="label-price">OMR ${parseFloat(product.price).toFixed(3)}</span>`;
content += `</div>`;
}
}
label.innerHTML = content;
sheet.appendChild(label);
printArea.appendChild(sheet);
let bWidth = 1.5;
let bHeight = 30;
if (labelType === 'l7651') { bWidth = 1.0; bHeight = 20; }
else if (labelType === 'l7656') { bWidth = 0.8; bHeight = 8; }
else if (labelType === 'a4-40') { bWidth = 1.2; bHeight = 25; }
else if (labelType === 'price-tag') { bWidth = 1.0; bHeight = 15; }
JsBarcode("#direct-barcode", product.sku, {
format: "CODE128",
width: bWidth,
height: bHeight,
displayValue: false,
margin: 0
});
setTimeout(() => {
window.print();
document.body.classList.remove('direct-print-mode');
preparePrint(); // Restore full queue print area
}, 100);
}
// Prepare Print Area (Full Queue)
function preparePrint() {
if (document.body.classList.contains('direct-print-mode')) return;
printArea.innerHTML = '';
const labelType = document.getElementById('labelType').value;
const showName = document.getElementById('showName').checked;
@ -478,7 +598,6 @@
const sheet = document.createElement('div');
sheet.className = 'label-sheet';
// Add specific sheet class for grid layouts
if (labelType === 'a4-24') sheet.classList.add('sheet-a4-24');
else if (labelType === 'a4-40') sheet.classList.add('sheet-a4-40');
else if (labelType === 'l7651') sheet.classList.add('sheet-l7651');
@ -492,12 +611,11 @@
let content = '';
if (labelType === 'l7656') {
// Horizontal layout for very short labels
if (showName) content += `<div class="label-text" style="max-width: 40px">${p.name}</div>`;
if (showName) content += `<div class="label-text" style="max-width: 40px">${p.nameAr ? p.nameAr + " " : ""}${p.name}</div>`;
content += `<svg id="barcode-${p.id}-${i}"></svg>`;
if (showPrice) content += `<div class="label-text label-price">${parseFloat(p.price).toFixed(3)}</div>`;
} else {
if (showName) content += `<div class="label-text">${p.name}</div>`;
if (showName) { if (p.nameAr) content += `<div class="label-text">${p.nameAr}</div>`; content += `<div class="label-text">${p.name}</div>`; }
content += `<svg id="barcode-${p.id}-${i}"></svg>`;
if (showSKU || showPrice) {
content += `<div class="label-text d-flex justify-content-between">`;
@ -514,7 +632,6 @@
printArea.appendChild(sheet);
// Generate barcodes
queue.forEach(p => {
for (let i = 0; i < p.qty; i++) {
const svgId = `barcode-${p.id}-${i}`;