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"> <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> <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"> <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> </button>
</div> </div>
@ -33,20 +33,32 @@
</thead> </thead>
<tbody> <tbody>
{% for product in products %} {% 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> <td>
<div class="fw-bold">{{ product.name_en }}</div> <div class="fw-bold">{{ product.name_en }}</div>
<small class="text-muted">{{ product.name_ar }}</small> <small class="text-muted">{{ product.name_ar }}</small>
</td> </td>
<td><code>{{ product.sku }}</code></td> <td><code>{{ product.sku }}</code></td>
<td> <td>
<button class="btn btn-sm btn-outline-primary add-to-queue" <div class="btn-group">
data-id="{{ product.id }}" <button class="btn btn-sm btn-outline-primary add-to-queue"
data-name="{{ product.name_en }}" data-id="{{ product.id }}"
data-sku="{{ product.sku }}" data-name="{{ product.name_en }}" data-name-ar="{{ product.name_ar }}"
data-price="{{ product.price }}"> data-sku="{{ product.sku }}"
<i class="bi bi-plus"></i> data-price="{{ product.price }}"
</button> 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> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -120,8 +132,11 @@
<!-- Live Preview --> <!-- Live Preview -->
<div class="card shadow-sm border-0"> <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> <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>
<div class="card-body text-center bg-light p-5"> <div class="card-body text-center bg-light p-5">
<div id="previewContainer" class="d-inline-block bg-white shadow-sm p-3 border"> <div id="previewContainer" class="d-inline-block bg-white shadow-sm p-3 border">
@ -154,6 +169,8 @@
.print-only { display: none; } .print-only { display: none; }
} }
@media print { @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; } .no-print { display: none !important; }
.print-only { display: block; } .print-only { display: block; }
body { margin: 0; padding: 0; background: white; -webkit-print-color-adjust: exact; } body { margin: 0; padding: 0; background: white; -webkit-print-color-adjust: exact; }
@ -162,6 +179,22 @@
size: A4; size: A4;
margin: 0; 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 { .label-sheet {
display: flex; display: flex;
@ -369,18 +402,19 @@
const labelQueueBody = document.getElementById('labelQueue'); const labelQueueBody = document.getElementById('labelQueue');
const emptyQueue = document.getElementById('emptyQueue'); const emptyQueue = document.getElementById('emptyQueue');
const printArea = document.getElementById('printArea'); const printArea = document.getElementById('printArea');
let lastAddedProduct = null;
// Add to Queue // Add to Queue
document.querySelectorAll('.add-to-queue').forEach(btn => { document.querySelectorAll('.add-to-queue').forEach(btn => {
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
const product = { const product = {
id: btn.dataset.id, id: btn.dataset.id,
name: btn.dataset.name, name: btn.dataset.name, nameAr: btn.dataset.nameAr,
sku: btn.dataset.sku, sku: btn.dataset.sku,
price: btn.dataset.price, price: btn.dataset.price,
qty: 1 qty: 1
}; };
lastAddedProduct = product;
const existing = queue.find(p => p.id === product.id); const existing = queue.find(p => p.id === product.id);
if (existing) { if (existing) {
existing.qty++; existing.qty++;
@ -402,7 +436,7 @@
labelQueueBody.innerHTML = queue.map((p, index) => ` labelQueueBody.innerHTML = queue.map((p, index) => `
<tr> <tr>
<td> <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> <code class="text-muted small">${p.sku}</code>
</td> </td>
<td> <td>
@ -446,14 +480,20 @@
// Preview Logic // Preview Logic
function updatePreview() { function updatePreview() {
if (queue.length === 0) return; let product = null;
const lastProduct = queue[queue.length - 1]; if (queue.length > 0) {
product = queue[queue.length - 1];
} else if (lastAddedProduct) {
product = lastAddedProduct;
}
document.querySelector('.preview-name').innerText = lastProduct.name; if (!product) return;
document.querySelector('.preview-sku').innerText = lastProduct.sku;
document.querySelector('.preview-price').innerText = 'OMR ' + parseFloat(lastProduct.price).toFixed(3);
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", format: "CODE128",
width: 2, width: 2,
height: 40, height: 40,
@ -467,8 +507,88 @@
document.querySelector('.preview-sku').style.display = document.getElementById('showSKU').checked ? '' : 'none'; document.querySelector('.preview-sku').style.display = document.getElementById('showSKU').checked ? '' : 'none';
} }
// Prepare Print Area // Direct Print Logic
function preparePrint() { 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 = ''; printArea.innerHTML = '';
const labelType = document.getElementById('labelType').value; const labelType = document.getElementById('labelType').value;
const showName = document.getElementById('showName').checked; const showName = document.getElementById('showName').checked;
@ -478,7 +598,6 @@
const sheet = document.createElement('div'); const sheet = document.createElement('div');
sheet.className = 'label-sheet'; sheet.className = 'label-sheet';
// Add specific sheet class for grid layouts
if (labelType === 'a4-24') sheet.classList.add('sheet-a4-24'); if (labelType === 'a4-24') sheet.classList.add('sheet-a4-24');
else if (labelType === 'a4-40') sheet.classList.add('sheet-a4-40'); else if (labelType === 'a4-40') sheet.classList.add('sheet-a4-40');
else if (labelType === 'l7651') sheet.classList.add('sheet-l7651'); else if (labelType === 'l7651') sheet.classList.add('sheet-l7651');
@ -492,12 +611,11 @@
let content = ''; let content = '';
if (labelType === 'l7656') { if (labelType === 'l7656') {
// Horizontal layout for very short labels if (showName) content += `<div class="label-text" style="max-width: 40px">${p.nameAr ? p.nameAr + " " : ""}${p.name}</div>`;
if (showName) content += `<div class="label-text" style="max-width: 40px">${p.name}</div>`;
content += `<svg id="barcode-${p.id}-${i}"></svg>`; content += `<svg id="barcode-${p.id}-${i}"></svg>`;
if (showPrice) content += `<div class="label-text label-price">${parseFloat(p.price).toFixed(3)}</div>`; if (showPrice) content += `<div class="label-text label-price">${parseFloat(p.price).toFixed(3)}</div>`;
} else { } 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>`; content += `<svg id="barcode-${p.id}-${i}"></svg>`;
if (showSKU || showPrice) { if (showSKU || showPrice) {
content += `<div class="label-text d-flex justify-content-between">`; content += `<div class="label-text d-flex justify-content-between">`;
@ -514,7 +632,6 @@
printArea.appendChild(sheet); printArea.appendChild(sheet);
// Generate barcodes
queue.forEach(p => { queue.forEach(p => {
for (let i = 0; i < p.qty; i++) { for (let i = 0; i < p.qty; i++) {
const svgId = `barcode-${p.id}-${i}`; const svgId = `barcode-${p.id}-${i}`;