Improve FG scan page UX and integrate scan-to-boxes with QZ Tray printing
- Redesigned scan card layout: 500px width with horizontal label-input layout - Reduced spacing and optimized for no scrolling (700px max-height) - Added auto-advance between fields when valid data is entered - Integrated scan-to-boxes popup with warehouse box assignment - Added QZ Tray printing to Quick Box Creation button - Box labels now print automatically after creation in scan workflow - Fixed warehouse blueprint URL prefix registration (/warehouse) - Updated manage_boxes to return JSON for AJAX requests - Improved error message grid layout to maintain form alignment
This commit is contained in:
@@ -3,12 +3,15 @@
|
||||
{% block title %}Finish Good Scan{% endblock %}
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/scan.css') }}">
|
||||
<!-- QZ Tray for printing -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/qz-tray@2.2.0/qz-tray.min.js"></script>
|
||||
<style>
|
||||
.error-message {
|
||||
color: #ff4444;
|
||||
font-size: 0.9em;
|
||||
margin-top: 5px;
|
||||
display: none;
|
||||
grid-column: 2 / -1;
|
||||
}
|
||||
.error-message.show {
|
||||
display: block;
|
||||
@@ -275,6 +278,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
} else {
|
||||
operatorErrorMessage.classList.remove('show');
|
||||
this.setCustomValidity('');
|
||||
|
||||
// Auto-advance when field is complete and valid
|
||||
if (value.length === 4 && value.startsWith('OP')) {
|
||||
cpCodeInput.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -312,6 +320,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
} else {
|
||||
cpErrorMessage.classList.remove('show');
|
||||
this.setCustomValidity('');
|
||||
|
||||
// Auto-advance when field is complete and valid
|
||||
if (value.length === 15 && value.startsWith('CP')) {
|
||||
oc1CodeInput.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -369,6 +382,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
} else {
|
||||
oc1ErrorMessage.classList.remove('show');
|
||||
this.setCustomValidity('');
|
||||
|
||||
// Auto-advance when field is complete and valid
|
||||
if (value.length === 4 && value.startsWith('OC')) {
|
||||
oc2CodeInput.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -423,6 +441,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
} else {
|
||||
oc2ErrorMessage.classList.remove('show');
|
||||
this.setCustomValidity('');
|
||||
|
||||
// Auto-advance when field is complete and valid
|
||||
if (value.length === 4 && value.startsWith('OC')) {
|
||||
defectCodeInput.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -550,6 +573,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
localStorage.setItem('fg_scan_last_defect', defectCodeInput.value);
|
||||
|
||||
// Check if scan-to-boxes is enabled and defect code is 000
|
||||
console.log('Auto-submit check:', {
|
||||
scanToBoxesEnabled: scanToBoxesEnabled,
|
||||
defectCode: this.value,
|
||||
shouldShowModal: scanToBoxesEnabled && this.value === '000'
|
||||
});
|
||||
|
||||
if (scanToBoxesEnabled && this.value === '000') {
|
||||
console.log('Auto-submit: Scan-to-boxes enabled, calling submitScanWithBoxAssignment');
|
||||
submitScanWithBoxAssignment();
|
||||
@@ -647,6 +676,15 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
alert('✅ Saved Quality Operator code cleared! Please re-enter your operator code.');
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize QZ Tray for printing box labels
|
||||
if (window.qz) {
|
||||
window.qz.websocket.connect().then(() => {
|
||||
console.log('QZ Tray connected for box label printing');
|
||||
}).catch(err => {
|
||||
console.warn('QZ Tray not available:', err);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -656,6 +694,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
// Quick box creation button
|
||||
document.getElementById('quick-box-create-btn').addEventListener('click', async function() {
|
||||
try {
|
||||
this.disabled = true;
|
||||
this.textContent = 'Creating...';
|
||||
|
||||
// Step 1: Create box in database
|
||||
const createResponse = await fetch('/warehouse/manage_boxes', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -670,14 +712,56 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const result = await createResponse.json();
|
||||
|
||||
if (result.success && result.box_number) {
|
||||
await assignCpToBox(result.box_number);
|
||||
showNotification(`✅ Box ${result.box_number} created and CP assigned!`, 'success');
|
||||
closeBoxModal();
|
||||
const boxNumber = result.box_number;
|
||||
|
||||
// Step 2: Print the box label using QZ Tray
|
||||
try {
|
||||
// Check QZ Tray connection
|
||||
if (!window.qz || !window.qz.websocket.isActive()) {
|
||||
throw new Error('QZ Tray not connected. Please ensure QZ Tray is running.');
|
||||
}
|
||||
|
||||
// Get available printers
|
||||
const printers = await window.qz.printers.find();
|
||||
if (printers.length === 0) {
|
||||
throw new Error('No printers found');
|
||||
}
|
||||
|
||||
// Use first available printer
|
||||
const printer = printers[0];
|
||||
|
||||
// Create ZPL code for box label
|
||||
const zpl = `^XA
|
||||
^FO50,50^A0N,40,40^FDBox: ${boxNumber}^FS
|
||||
^FO50,120^BY2,3,80^BCN,80,Y,N,N^FD${boxNumber}^FS
|
||||
^XZ`;
|
||||
|
||||
const config = window.qz.configs.create(printer);
|
||||
await window.qz.print(config, [zpl]);
|
||||
|
||||
showNotification(`✅ Box ${boxNumber} created and label printed!`, 'success');
|
||||
|
||||
// Step 3: Keep modal open and focus on scan input
|
||||
document.getElementById('scan-box-input').value = '';
|
||||
document.getElementById('scan-box-input').focus();
|
||||
document.getElementById('scan-box-input').placeholder = 'Scan the printed label now...';
|
||||
|
||||
} catch (printError) {
|
||||
console.error('Print error:', printError);
|
||||
showNotification(`⚠️ Box ${boxNumber} created but print failed: ${printError.message}`, 'warning');
|
||||
// Still keep modal open for manual entry
|
||||
document.getElementById('scan-box-input').focus();
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to create box');
|
||||
}
|
||||
} catch (error) {
|
||||
showNotification('❌ Error creating box: ' + error.message, 'error');
|
||||
} finally {
|
||||
// Re-enable button
|
||||
this.disabled = false;
|
||||
this.textContent = 'Quick Box Label Creation';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user