Initial V1 Backup
This commit is contained in:
582
templates/count_location.html
Normal file
582
templates/count_location.html
Normal file
@@ -0,0 +1,582 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Counting {{ location.location_name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="count-location-container">
|
||||
<div class="location-header">
|
||||
<div class="location-info">
|
||||
<div class="location-label">Counting Location</div>
|
||||
<h1 class="location-name">{{ location.location_name }}</h1>
|
||||
<div class="location-stats">
|
||||
<span class="stat-pill">Expected: {{ location.expected_lots_master }}</span>
|
||||
<span class="stat-pill">Found: <span id="foundCount">{{ location.lots_found }}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scan-card scan-card-active">
|
||||
<div class="scan-header">
|
||||
<h2 class="scan-title">Scan Lot Barcode</h2>
|
||||
</div>
|
||||
|
||||
<form id="lotScanForm" class="scan-form">
|
||||
<div class="scan-input-group">
|
||||
<input type="text"
|
||||
name="lot_number"
|
||||
id="lotInput"
|
||||
inputmode="none"
|
||||
class="scan-input"
|
||||
placeholder="Scan Lot Number"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
spellcheck="false"
|
||||
autofocus>
|
||||
<button type="submit" style="display: none;" aria-hidden="true"></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="duplicateModal" class="modal">
|
||||
<div class="modal-content modal-duplicate">
|
||||
<div class="duplicate-lot-number" id="duplicateLotNumber"></div>
|
||||
<h3 class="duplicate-title">Already Scanned</h3>
|
||||
<p class="duplicate-message">Do you wish to Resubmit?</p>
|
||||
<div class="modal-actions">
|
||||
<button type="button" class="btn btn-secondary btn-lg" onclick="cancelDuplicate()">No</button>
|
||||
<button type="button" class="btn btn-primary btn-lg" onclick="confirmDuplicate()">Yes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="weightModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h3 class="modal-title">Enter Weight</h3>
|
||||
<div class="modal-lot-info">
|
||||
<div id="modalLotNumber" class="modal-lot-number"></div>
|
||||
<div id="modalItemDesc" class="modal-item-desc"></div>
|
||||
</div>
|
||||
<form id="weightForm" class="weight-form">
|
||||
<input
|
||||
type="number"
|
||||
id="weightInput"
|
||||
class="weight-input"
|
||||
placeholder="0.0"
|
||||
step="0.01"
|
||||
min="0"
|
||||
inputmode="decimal"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
required
|
||||
>
|
||||
<div class="modal-actions">
|
||||
<button type="button" class="btn btn-secondary" onclick="cancelWeight()">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scans-section">
|
||||
<div class="scans-header">
|
||||
<h3 class="scans-title">Scanned Lots (<span id="scanListCount">{{ scans|length }}</span>)</h3>
|
||||
</div>
|
||||
|
||||
<div id="scansList" class="scans-grid">
|
||||
{% for scan in scans %}
|
||||
|
||||
{# LOGIC FIX: Determine CSS class based on weight difference #}
|
||||
{% set row_class = scan.master_status %}
|
||||
|
||||
{% if scan.duplicate_status and scan.duplicate_status != '00' %}
|
||||
{% set row_class = 'duplicate-' + scan.duplicate_status %}
|
||||
{% elif scan.master_status == 'match' and scan.master_expected_weight and (scan.actual_weight - scan.master_expected_weight)|abs >= 0.01 %}
|
||||
{# If it is a match but weight is off, force class to weight_discrepancy #}
|
||||
{% set row_class = 'weight_discrepancy' %}
|
||||
{% endif %}
|
||||
|
||||
<div class="scan-row scan-row-{{ row_class }}"
|
||||
data-entry-id="{{ scan.entry_id }}"
|
||||
onclick="openScanDetail({{ scan.entry_id }})">
|
||||
<div class="scan-row-lot">{{ scan.lot_number }}</div>
|
||||
<div class="scan-row-item">{{ scan.item or 'N/A' }}</div>
|
||||
<div class="scan-row-weight">{{ scan.actual_weight }} lbs</div>
|
||||
<div class="scan-row-status">
|
||||
{% if scan.duplicate_status == '01' or scan.duplicate_status == '04' %}
|
||||
<span class="status-dot status-dot-blue"></span> Duplicate
|
||||
{% elif scan.duplicate_status == '03' %}
|
||||
<span class="status-dot status-dot-orange"></span> Dup (Other Loc)
|
||||
{% elif row_class == 'weight_discrepancy' %}
|
||||
<span class="status-dot status-dot-orange"></span> Weight Off
|
||||
{% elif scan.master_status == 'match' %}
|
||||
<span class="status-dot status-dot-green"></span> Match
|
||||
{% elif scan.master_status == 'wrong_location' %}
|
||||
<span class="status-dot status-dot-yellow"></span> Wrong Loc
|
||||
{% elif scan.master_status == 'ghost_lot' %}
|
||||
<span class="status-dot status-dot-purple"></span> Ghost
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if session_type == 'cycle_count' and expected_lots %}
|
||||
<div class="expected-section" id="expectedSection">
|
||||
<div class="scans-header">
|
||||
<h3 class="scans-title expected-title">Expected Items (<span id="expectedCount">{{ expected_lots|length }}</span>)</h3>
|
||||
</div>
|
||||
<div class="scans-grid" id="expectedList">
|
||||
{% for lot in expected_lots %}
|
||||
<div class="scan-row expected-row"
|
||||
id="expected-{{ lot.lot_number }}"
|
||||
onclick="scanExpectedLot('{{ lot.lot_number }}')">
|
||||
<div class="scan-row-lot">{{ lot.lot_number }}</div>
|
||||
<div class="scan-row-item">{{ lot.item }}</div>
|
||||
<div class="scan-row-weight">{{ lot.total_weight }} lbs</div>
|
||||
<div class="scan-row-status">
|
||||
<span class="status-dot status-dot-gray"></span> Pending
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div id="scanDetailModal" class="modal">
|
||||
<div class="modal-content modal-large">
|
||||
<div class="modal-header-bar">
|
||||
<h3 class="modal-title">Scan Details</h3>
|
||||
<button type="button" class="btn-close-modal" onclick="closeScanDetail()">✕</button>
|
||||
</div>
|
||||
|
||||
<div id="scanDetailContent" class="scan-detail-content">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="finish-section">
|
||||
<div class="action-buttons-row">
|
||||
<a href="{{ url_for('my_counts', session_id=session_id) }}" class="btn btn-secondary btn-block btn-lg">
|
||||
← Back to My Counts
|
||||
</a>
|
||||
<button id="finishBtn" class="btn btn-success btn-block btn-lg" onclick="finishLocation()">
|
||||
✓ Finish Location
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let currentLotNumber = '';
|
||||
let isDuplicateConfirmed = false;
|
||||
let isProcessing = false;
|
||||
|
||||
// Lot scan handler
|
||||
document.getElementById('lotScanForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
if (isProcessing) return;
|
||||
|
||||
const scannedValue = document.getElementById('lotInput').value.trim();
|
||||
if (!scannedValue) return;
|
||||
|
||||
isProcessing = true;
|
||||
currentLotNumber = scannedValue;
|
||||
document.getElementById('lotInput').value = '';
|
||||
|
||||
checkDuplicate();
|
||||
});
|
||||
|
||||
function checkDuplicate() {
|
||||
fetch('{{ url_for("scan_lot", session_id=session_id, location_count_id=location.location_count_id) }}', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
lot_number: currentLotNumber,
|
||||
weight: 0,
|
||||
check_only: true
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.needs_confirmation) {
|
||||
document.getElementById('duplicateLotNumber').textContent = currentLotNumber;
|
||||
document.getElementById('duplicateModal').style.display = 'flex';
|
||||
} else {
|
||||
showWeightModal();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error checking duplicate:', error);
|
||||
showWeightModal();
|
||||
});
|
||||
}
|
||||
|
||||
function confirmDuplicate() {
|
||||
isDuplicateConfirmed = true;
|
||||
document.getElementById('duplicateModal').style.display = 'none';
|
||||
showWeightModal();
|
||||
}
|
||||
|
||||
function cancelDuplicate() {
|
||||
document.getElementById('duplicateModal').style.display = 'none';
|
||||
document.getElementById('lotInput').focus();
|
||||
isDuplicateConfirmed = false;
|
||||
isProcessing = false;
|
||||
}
|
||||
|
||||
function showWeightModal() {
|
||||
if (!currentLotNumber) {
|
||||
alert('Error: Lot number lost. Please scan again.');
|
||||
document.getElementById('lotInput').focus();
|
||||
return;
|
||||
}
|
||||
document.getElementById('modalLotNumber').textContent = currentLotNumber;
|
||||
document.getElementById('modalItemDesc').textContent = 'Loading...';
|
||||
document.getElementById('weightModal').style.display = 'flex';
|
||||
document.getElementById('weightInput').value = '';
|
||||
document.getElementById('weightInput').focus();
|
||||
}
|
||||
|
||||
// Weight form handler
|
||||
document.getElementById('weightForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const weight = document.getElementById('weightInput').value;
|
||||
if (!weight || weight <= 0) {
|
||||
alert('Please enter a valid weight');
|
||||
return;
|
||||
}
|
||||
submitScan(weight);
|
||||
});
|
||||
|
||||
function submitScan(weight) {
|
||||
if (!currentLotNumber) {
|
||||
alert('Error: Lot number lost. Please scan again.');
|
||||
document.getElementById('weightModal').style.display = 'none';
|
||||
document.getElementById('lotInput').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('{{ url_for("scan_lot", session_id=session_id, location_count_id=location.location_count_id) }}', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
lot_number: currentLotNumber.trim(),
|
||||
weight: parseFloat(weight),
|
||||
confirm_duplicate: isDuplicateConfirmed
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
document.getElementById('weightModal').style.display = 'none';
|
||||
isDuplicateConfirmed = false;
|
||||
|
||||
if (data.updated_entry_ids && data.updated_entry_ids.length > 0) {
|
||||
updateExistingScansStatus(data.updated_entry_ids, data.duplicate_status);
|
||||
}
|
||||
|
||||
addScanToList(data, weight);
|
||||
|
||||
// NEW: Instacart Logic - Remove from Expected List if it exists
|
||||
const expectedRow = document.getElementById('expected-' + currentLotNumber);
|
||||
if (expectedRow) {
|
||||
expectedRow.remove();
|
||||
|
||||
// Update Expected count
|
||||
const countSpan = document.getElementById('expectedCount');
|
||||
if (countSpan) {
|
||||
let currentCount = parseInt(countSpan.textContent);
|
||||
if (currentCount > 0) {
|
||||
countSpan.textContent = currentCount - 1;
|
||||
}
|
||||
// Hide section if empty
|
||||
if (currentCount - 1 <= 0) {
|
||||
const section = document.getElementById('expectedSection');
|
||||
if (section) section.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentLotNumber = '';
|
||||
isProcessing = false;
|
||||
document.getElementById('lotInput').focus();
|
||||
} else {
|
||||
alert(data.message || 'Error saving scan');
|
||||
isProcessing = false;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error saving scan');
|
||||
console.error(error);
|
||||
isProcessing = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Function to handle clicking an Expected Lot
|
||||
function scanExpectedLot(lotNumber) {
|
||||
if (isProcessing) return;
|
||||
|
||||
// Set the lot number as if it was scanned
|
||||
currentLotNumber = lotNumber;
|
||||
|
||||
// Visual feedback (optional, but nice)
|
||||
console.log('Clicked expected lot:', lotNumber);
|
||||
|
||||
// Proceed to check logic (just like a normal scan)
|
||||
// We go through checkDuplicate just in case, consistency is safer
|
||||
checkDuplicate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function cancelWeight() {
|
||||
document.getElementById('weightModal').style.display = 'none';
|
||||
document.getElementById('lotInput').focus();
|
||||
isDuplicateConfirmed = false;
|
||||
isProcessing = false;
|
||||
}
|
||||
|
||||
function updateExistingScansStatus(entryIds, duplicateStatus) {
|
||||
entryIds.forEach(entryId => {
|
||||
const scanRow = document.querySelector(`[data-entry-id="${entryId}"]`);
|
||||
if (scanRow) {
|
||||
const statusElement = scanRow.querySelector('.scan-row-status');
|
||||
if (statusElement) {
|
||||
let statusText = 'Duplicate';
|
||||
let statusDot = 'blue';
|
||||
if (duplicateStatus === '03') {
|
||||
statusText = 'Dup (Other Loc)';
|
||||
statusDot = 'orange';
|
||||
}
|
||||
statusElement.innerHTML = `<span class="status-dot status-dot-${statusDot}"></span> ${statusText}`;
|
||||
}
|
||||
scanRow.className = 'scan-row scan-row-duplicate-' + duplicateStatus;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addScanToList(data, weight) {
|
||||
const scansList = document.getElementById('scansList');
|
||||
|
||||
let statusClass = '';
|
||||
let statusText = '';
|
||||
let statusDot = '';
|
||||
|
||||
if (data.duplicate_status && data.duplicate_status !== '00') {
|
||||
statusClass = 'duplicate-' + data.duplicate_status;
|
||||
if (data.duplicate_status === '01' || data.duplicate_status === '04') {
|
||||
statusText = 'Duplicate';
|
||||
statusDot = 'blue';
|
||||
} else if (data.duplicate_status === '03') {
|
||||
statusText = 'Dup (Other Loc)';
|
||||
statusDot = 'orange';
|
||||
}
|
||||
} else if (data.master_status === 'match') {
|
||||
if (data.master_expected_weight && Math.abs(weight - data.master_expected_weight) >= 0.01) {
|
||||
statusClass = 'weight_discrepancy';
|
||||
statusText = 'Weight Off';
|
||||
statusDot = 'orange';
|
||||
} else {
|
||||
statusClass = 'match';
|
||||
statusText = 'Match';
|
||||
statusDot = 'green';
|
||||
}
|
||||
} else if (data.master_status === 'wrong_location') {
|
||||
statusClass = 'wrong_location';
|
||||
statusText = 'Wrong Loc';
|
||||
statusDot = 'yellow';
|
||||
} else if (data.master_status === 'ghost_lot') {
|
||||
statusClass = 'ghost_lot';
|
||||
statusText = 'Ghost';
|
||||
statusDot = 'purple';
|
||||
}
|
||||
|
||||
const scanRow = document.createElement('div');
|
||||
scanRow.className = 'scan-row scan-row-' + statusClass;
|
||||
scanRow.setAttribute('data-entry-id', data.entry_id);
|
||||
scanRow.onclick = function() { openScanDetail(data.entry_id); };
|
||||
scanRow.innerHTML = `
|
||||
<div class="scan-row-lot">${currentLotNumber}</div>
|
||||
<div class="scan-row-item">${data.item || 'N/A'}</div>
|
||||
<div class="scan-row-weight">${weight} lbs</div>
|
||||
<div class="scan-row-status">
|
||||
<span class="status-dot status-dot-${statusDot}"></span> ${statusText}
|
||||
</div>
|
||||
`;
|
||||
|
||||
scansList.insertBefore(scanRow, scansList.firstChild);
|
||||
|
||||
// Update Scanned Lots count
|
||||
const countSpan = document.getElementById('scanListCount');
|
||||
if (countSpan) {
|
||||
countSpan.textContent = scansList.children.length;
|
||||
}
|
||||
|
||||
// Update Header Found Count
|
||||
const foundStat = document.getElementById('foundCount');
|
||||
if (foundStat) {
|
||||
foundStat.textContent = scansList.children.length;
|
||||
}
|
||||
}
|
||||
|
||||
function openScanDetail(entryId) {
|
||||
fetch('/scan/' + entryId + '/details').then(r => r.json()).then(data => {
|
||||
if (data.success) displayScanDetail(data.scan);
|
||||
else alert('Error loading scan details');
|
||||
});
|
||||
}
|
||||
|
||||
function displayScanDetail(scan) {
|
||||
const content = document.getElementById('scanDetailContent');
|
||||
|
||||
// LOGIC FIX: Check weight variance for the badge
|
||||
let statusBadge = '';
|
||||
|
||||
// Check for weight discrepancy (Tolerance 0.01)
|
||||
let isWeightOff = false;
|
||||
if (scan.master_status === 'match' && scan.master_expected_weight) {
|
||||
if (Math.abs(scan.actual_weight - scan.master_expected_weight) >= 0.01) {
|
||||
isWeightOff = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (scan.duplicate_status === '01' || scan.duplicate_status === '04') {
|
||||
statusBadge = '<span class="badge badge-duplicate">🔵 Duplicate</span>';
|
||||
} else if (scan.duplicate_status === '03') {
|
||||
statusBadge = '<span class="badge badge-orange">🟠 Duplicate (Other Location)</span>';
|
||||
} else if (isWeightOff) {
|
||||
// NEW BADGE FOR WEIGHT OFF
|
||||
statusBadge = '<span class="badge badge-warning">🟠 Weight Discrepancy</span>';
|
||||
} else if (scan.master_status === 'match') {
|
||||
statusBadge = '<span class="badge badge-success">✓ Match</span>';
|
||||
} else if (scan.master_status === 'wrong_location') {
|
||||
statusBadge = '<span class="badge badge-warning">⚠ Wrong Location</span>';
|
||||
} else if (scan.master_status === 'ghost_lot') {
|
||||
statusBadge = '<span class="badge badge-purple">🟣 Ghost Lot</span>';
|
||||
}
|
||||
|
||||
// ... (rest of the function continues as normal)
|
||||
|
||||
content.innerHTML = `
|
||||
<div class="detail-section">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Lot Number:</span>
|
||||
<span class="detail-value detail-lot">${scan.lot_number}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Description:</span>
|
||||
<span class="detail-value">${scan.description || 'N/A'}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Status:</span>
|
||||
<span class="detail-value">${statusBadge}</span>
|
||||
</div>
|
||||
${scan.duplicate_info ? `<div class="detail-row"><span class="detail-label">Info:</span><span class="detail-value detail-info">${scan.duplicate_info}</span></div>` : ''}
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">Scanned:</span>
|
||||
<span class="detail-value">${scan.scan_timestamp}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section">
|
||||
<h4 class="detail-section-title">Edit Scan</h4>
|
||||
<div class="detail-form">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Item Number</label>
|
||||
<input type="text" id="editItem" class="form-input" value="${scan.item || ''}" placeholder="Item/SKU">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Weight (lbs)</label>
|
||||
<input type="number" id="editWeight" class="form-input" value="${scan.actual_weight}" step="0.01" min="0" inputmode="decimal">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Comment</label>
|
||||
<textarea id="editComment" class="form-textarea" rows="3" placeholder="Add a comment...">${scan.comment || ''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-actions">
|
||||
<button class="btn btn-secondary" onclick="closeScanDetail()">Cancel</button>
|
||||
<button class="btn btn-danger" onclick="deleteFromDetail(${scan.entry_id})">Delete</button>
|
||||
<button class="btn btn-primary" onclick="saveScanEdit(${scan.entry_id})">Save Changes</button>
|
||||
</div>
|
||||
`;
|
||||
document.getElementById('scanDetailModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeScanDetail() {
|
||||
document.getElementById('scanDetailModal').style.display = 'none';
|
||||
}
|
||||
|
||||
function saveScanEdit(entryId) {
|
||||
const item = document.getElementById('editItem').value.trim();
|
||||
const weight = document.getElementById('editWeight').value;
|
||||
const comment = document.getElementById('editComment').value;
|
||||
|
||||
if (!weight || weight <= 0) {
|
||||
alert('Please enter a valid weight');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/scan/' + entryId + '/update', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({ item: item, weight: parseFloat(weight), comment: comment })
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
closeScanDetail();
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || 'Error updating scan');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteFromDetail(entryId) {
|
||||
if (!confirm('Delete this scan?')) return;
|
||||
|
||||
fetch('/scan/' + entryId + '/delete', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'}
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
closeScanDetail();
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function finishLocation() {
|
||||
if (!confirm('Are you finished counting this location?')) return;
|
||||
|
||||
fetch('{{ url_for("finish_location", session_id=session_id, location_count_id=location.location_count_id) }}', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'}
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) window.location.href = data.redirect;
|
||||
else alert('Error finishing location');
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
document.getElementById('weightModal').style.display = 'none';
|
||||
document.getElementById('duplicateModal').style.display = 'none';
|
||||
document.getElementById('lotInput').focus();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user