editing barcode module
This commit is contained in:
parent
00d9114ba0
commit
e473add476
@ -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}`;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user