Files
quality_app/py_app/app/templates/store_articles.html
Quality App System 5a423b3704 Add Set Boxes Locations page with status management and remove company branding from labels
- Renamed Store Articles card to Set Boxes Locations on warehouse main page
- Created new mobile-optimized page with two tabs for box location management:
  - Tab 1: Assign box to location (scan box, change status to closed, assign location)
  - Tab 2: Move box from location (scan location, list boxes, move to new location)
- Added box status management (open/closed) with status change button
- Enforced rule: only closed boxes can be assigned to locations
- Moved API logic to warehouse.py module:
  - search_box_by_number()
  - assign_box_to_location()
  - search_location_with_boxes()
  - move_box_to_new_location()
  - change_box_status()
- Added API routes in routes.py as thin wrappers
- Aligned page theme colors with application Bootstrap theme
- Added dark mode support for the new page
- Added Warehouse Main button to page header
- Removed 'INNOFA ROMANIA SRL' branding from:
  - Print module label preview and PDF generation
  - Print lost labels page
  - pdf_generator.py PDF creation function
2025-12-27 19:47:32 +02:00

1099 lines
32 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Set Boxes Locations{% endblock %}
{% block content %}
<style>
/* Mobile-first responsive design - Aligned with application theme */
.location-manager-container {
max-width: 100%;
margin: 0 auto;
padding: 10px;
}
.main-card {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
overflow: hidden;
}
/* Tab navigation */
.tab-navigation {
display: flex;
background: #f8f9fa;
border-bottom: 2px solid #dee2e6;
}
.tab-button {
flex: 1;
padding: 15px 10px;
background: none;
border: none;
font-size: 14px;
font-weight: 600;
color: #6c757d;
cursor: pointer;
transition: all 0.3s;
border-bottom: 3px solid transparent;
}
.tab-button.active {
color: #007bff;
border-bottom-color: #007bff;
background: #ffffff;
}
.tab-button:hover:not(.active) {
background: #e9ecef;
}
/* Tab content */
.tab-content {
display: none;
padding: 20px;
animation: fadeIn 0.3s;
}
.tab-content.active {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* Form sections */
.form-section {
margin-bottom: 25px;
}
.form-section h3 {
color: #333;
font-size: 18px;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 8px;
}
.section-icon {
font-size: 20px;
}
/* Input groups */
.input-group {
margin-bottom: 15px;
}
.input-group label {
display: block;
font-weight: 600;
color: #495057;
margin-bottom: 8px;
font-size: 14px;
}
.input-group input,
.input-group select {
width: 100%;
padding: 12px 15px;
font-size: 16px;
border: 2px solid #ced4da;
border-radius: 4px;
transition: all 0.3s;
box-sizing: border-box;
}
.input-group input:focus,
.input-group select:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}
/* Buttons */
.btn-primary {
width: 100%;
padding: 12px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.btn-primary:hover {
background: #0056b3;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,123,255,0.3);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-secondary {
width: 100%;
padding: 10px;
background: #6c757d;
color: white;
border: none;
border-radius: 4px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
margin-top: 10px;
}
.btn-secondary:hover {
background: #5a6268;
}
.btn-success {
background: #28a745;
}
.btn-success:hover {
background: #218838;
}
/* Info display */
.info-box {
background: #f8f9fa;
border-radius: 4px;
padding: 15px;
margin-top: 15px;
display: none;
border: 1px solid #dee2e6;
}
.info-box.show {
display: block;
animation: slideDown 0.3s;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.info-row {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #dee2e6;
}
.info-row:last-child {
border-bottom: none;
}
.info-label {
font-weight: 600;
color: #6c757d;
}
.info-value {
color: #333;
font-weight: 500;
}
.status-badge {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
}
.status-badge.open {
background: #fff3cd;
color: #856404;
border: 1px solid #ffc107;
}
.status-badge.closed {
background: #d4edda;
color: #155724;
border: 1px solid #28a745;
}
.btn-status {
width: 100%;
padding: 10px;
background: #ffc107;
color: #212529;
border: none;
border-radius: 4px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
margin-top: 10px;
}
.btn-status:hover {
background: #e0a800;
}
.btn-status:disabled {
background: #e9ecef;
cursor: not-allowed;
}
/* Box list */
.box-list {
margin-top: 15px;
display: none;
}
.box-list.show {
display: block;
}
.box-item {
background: #ffffff;
border: 2px solid #dee2e6;
border-radius: 4px;
padding: 12px;
margin-bottom: 10px;
cursor: pointer;
transition: all 0.2s;
display: flex;
justify-content: space-between;
align-items: center;
}
.box-item:hover {
border-color: #007bff;
background: #f8f9fa;
}
.box-item.selected {
border-color: #007bff;
background: #e7f1ff;
}
.box-info {
flex: 1;
}
.box-number {
font-weight: 700;
color: #333;
font-size: 16px;
}
.box-status {
font-size: 12px;
color: #6c757d;
margin-top: 4px;
}
.box-icon {
font-size: 24px;
color: #6c757d;
}
/* Alert messages */
.alert {
padding: 12px 15px;
border-radius: 4px;
margin-bottom: 15px;
font-weight: 500;
display: none;
animation: slideDown 0.3s;
}
.alert.show {
display: block;
}
.alert-success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.alert-error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.alert-info {
background: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
/* Loading spinner */
.spinner {
display: none;
border: 3px solid #f3f3f3;
border-top: 3px solid #007bff;
border-radius: 50%;
width: 20px;
height: 20px;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Laptop view adjustments */
@media (min-width: 768px) {
.location-manager-container {
padding: 30px;
max-width: 800px;
}
.tab-button {
font-size: 16px;
padding: 18px 20px;
}
.tab-content {
padding: 30px;
}
.form-section h3 {
font-size: 20px;
}
.btn-primary,
.btn-secondary {
max-width: 400px;
}
}
/* Accessibility */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
border: 0;
}
/* Dark Mode Support */
body.dark-mode .main-card {
background: #2d2d2d;
color: #e0e0e0;
}
body.dark-mode .tab-navigation {
background: #1a1a1a;
border-bottom-color: #444;
}
body.dark-mode .tab-button {
color: #aaa;
}
body.dark-mode .tab-button.active {
color: #4a9eff;
background: #2d2d2d;
}
body.dark-mode .tab-button:hover:not(.active) {
background: #333;
}
body.dark-mode .form-section h3 {
color: #fff;
}
body.dark-mode .input-group label {
color: #ccc;
}
body.dark-mode .input-group input,
body.dark-mode .input-group select {
background: #3a3a3a;
border-color: #555;
color: #e0e0e0;
}
body.dark-mode .input-group input:focus,
body.dark-mode .input-group select:focus {
border-color: #4a9eff;
background: #404040;
}
body.dark-mode .info-box {
background: #1a1a1a;
border-color: #444;
}
body.dark-mode .info-box h4 {
color: #fff;
}
body.dark-mode .info-row {
border-bottom-color: #444;
}
body.dark-mode .info-label {
color: #aaa;
}
body.dark-mode .info-value {
color: #e0e0e0;
}
body.dark-mode .status-badge.open {
background: #4a3800;
color: #ffc107;
border-color: #6a5000;
}
body.dark-mode .status-badge.closed {
background: #1a3a1a;
color: #5cb85c;
border-color: #2a5a2a;
}
body.dark-mode .box-item {
background: #3a3a3a;
border-color: #555;
}
body.dark-mode .box-item:hover {
border-color: #4a9eff;
background: #404040;
}
body.dark-mode .box-item.selected {
border-color: #4a9eff;
background: #2a4a6a;
}
body.dark-mode .box-number {
color: #fff;
}
body.dark-mode .box-status {
color: #aaa;
}
body.dark-mode .box-icon {
color: #aaa;
}
body.dark-mode .alert-success {
background: #1a3a1a;
color: #5cb85c;
border-color: #2a5a2a;
}
body.dark-mode .alert-error {
background: #3a1a1a;
color: #e57373;
border-color: #5a2a2a;
}
body.dark-mode .alert-info {
background: #1a2a3a;
color: #64b5f6;
border-color: #2a4a6a;
}
</style>
<div class="location-manager-container">
<div class="main-card">
<!-- Tab Navigation -->
<div class="tab-navigation">
<button class="tab-button active" onclick="switchTab(0)" id="tab-btn-0">
📦 Assign Box to Location
</button>
<button class="tab-button" onclick="switchTab(1)" id="tab-btn-1">
📍 Move Box from Location
</button>
</div>
<!-- Tab 1: Assign Box to Location -->
<div class="tab-content active" id="tab-0">
<div class="form-section">
<h3><span class="section-icon">📦</span> Scan/Enter Box Number</h3>
<div id="alert-tab1" class="alert"></div>
<div class="input-group">
<label for="box-number-input">Box Number</label>
<input
type="text"
id="box-number-input"
placeholder="Scan or enter box number"
autocomplete="off"
autofocus
>
</div>
<button class="btn-primary" onclick="searchBox()">
<span class="spinner" id="spinner-search-box"></span>
<span id="btn-search-text">🔍 Search Box</span>
</button>
<!-- Box Information -->
<div class="info-box" id="box-info">
<h4 style="margin-top: 0; color: #1e293b;">Box Details</h4>
<div class="info-row">
<span class="info-label">Box Number:</span>
<span class="info-value" id="display-box-number">-</span>
</div>
<div class="info-row">
<span class="info-label">Status:</span>
<span class="info-value">
<span class="status-badge" id="display-box-status-badge">-</span>
</span>
</div>
<div class="info-row">
<span class="info-label">Current Location:</span>
<span class="info-value" id="display-current-location">-</span>
</div>
<button class="btn-status" id="btn-change-status" onclick="changeBoxStatus()" style="display: none;">
<span class="spinner" id="spinner-status" style="display: none;"></span>
<span id="btn-status-text">🔒 Close Box</span>
</button>
</div>
</div>
<!-- Location Assignment -->
<div class="form-section" id="assign-section" style="display: none;">
<h3><span class="section-icon">📍</span> Assign to Location</h3>
<div class="input-group">
<label for="location-code-input-tab1">Location Code</label>
<input
type="text"
id="location-code-input-tab1"
placeholder="Scan or enter location code"
autocomplete="off"
>
</div>
<button class="btn-primary btn-success" onclick="assignBoxToLocation()">
<span class="spinner" id="spinner-assign"></span>
<span id="btn-assign-text">✅ Assign to Location</span>
</button>
</div>
</div>
<!-- Tab 2: Move Box from Location -->
<div class="tab-content" id="tab-1">
<div class="form-section">
<h3><span class="section-icon">📍</span> Scan/Enter Location Code</h3>
<div id="alert-tab2" class="alert"></div>
<div class="input-group">
<label for="location-code-input-tab2">Location Code</label>
<input
type="text"
id="location-code-input-tab2"
placeholder="Scan or enter location code"
autocomplete="off"
>
</div>
<button class="btn-primary" onclick="searchLocation()">
<span class="spinner" id="spinner-search-location"></span>
<span id="btn-search-location-text">🔍 Search Location</span>
</button>
<!-- Location Information -->
<div class="info-box" id="location-info">
<h4 style="margin-top: 0; color: #1e293b;">Location Details</h4>
<div class="info-row">
<span class="info-label">Location Code:</span>
<span class="info-value" id="display-location-code">-</span>
</div>
<div class="info-row">
<span class="info-label">Boxes Count:</span>
<span class="info-value" id="display-boxes-count">-</span>
</div>
</div>
<!-- Boxes List -->
<div class="box-list" id="boxes-list">
<h4 style="margin-bottom: 15px; color: #1e293b;">Boxes in This Location</h4>
<div id="boxes-container"></div>
</div>
</div>
<!-- Move Box Section -->
<div class="form-section" id="move-section" style="display: none;">
<h3><span class="section-icon">🚚</span> Move Selected Box</h3>
<div class="info-box show">
<div class="info-row">
<span class="info-label">Selected Box:</span>
<span class="info-value" id="selected-box-display">-</span>
</div>
</div>
<div class="input-group">
<label for="new-location-input">New Location Code</label>
<input
type="text"
id="new-location-input"
placeholder="Scan or enter new location code"
autocomplete="off"
>
</div>
<button class="btn-primary btn-success" onclick="moveBox()">
<span class="spinner" id="spinner-move"></span>
<span id="btn-move-text">🚚 Move to New Location</span>
</button>
<button class="btn-secondary" onclick="clearSelection()">
Clear Selection
</button>
</div>
</div>
</div>
</div>
<script>
// Global variables
let currentBoxId = null;
let currentLocationId = null;
let selectedBoxId = null;
let selectedBoxNumber = null;
// Tab switching
function switchTab(tabIndex) {
// Hide all tabs
document.querySelectorAll('.tab-content').forEach(tab => {
tab.classList.remove('active');
});
document.querySelectorAll('.tab-button').forEach(btn => {
btn.classList.remove('active');
});
// Show selected tab
document.getElementById(`tab-${tabIndex}`).classList.add('active');
document.getElementById(`tab-btn-${tabIndex}`).classList.add('active');
// Clear alerts and reset states
hideAlert('alert-tab1');
hideAlert('alert-tab2');
if (tabIndex === 0) {
document.getElementById('box-number-input').focus();
} else {
document.getElementById('location-code-input-tab2').focus();
}
}
// Alert functions
function showAlert(elementId, message, type) {
const alert = document.getElementById(elementId);
alert.className = `alert alert-${type} show`;
alert.textContent = message;
}
function hideAlert(elementId) {
const alert = document.getElementById(elementId);
alert.classList.remove('show');
}
// Loading spinner functions
function showSpinner(spinnerId, btnTextId, loadingText) {
document.getElementById(spinnerId).style.display = 'inline-block';
if (btnTextId) {
document.getElementById(btnTextId).textContent = loadingText;
}
}
function hideSpinner(spinnerId, btnTextId, normalText) {
document.getElementById(spinnerId).style.display = 'none';
if (btnTextId) {
document.getElementById(btnTextId).textContent = normalText;
}
}
// Tab 1: Change Box Status
async function changeBoxStatus() {
if (!currentBoxId) {
showAlert('alert-tab1', 'No box selected', 'error');
return;
}
hideAlert('alert-tab1');
showSpinner('spinner-status', 'btn-status-text', 'Changing...');
try {
const response = await fetch('/api/warehouse/box/change-status', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
box_id: currentBoxId,
new_status: 'closed'
})
});
const data = await response.json();
if (data.success) {
// Update status display
const statusBadge = document.getElementById('display-box-status-badge');
statusBadge.textContent = 'closed';
statusBadge.className = 'status-badge closed';
// Hide status button and show assign section
document.getElementById('btn-change-status').style.display = 'none';
document.getElementById('assign-section').style.display = 'block';
showAlert('alert-tab1', 'Box status changed to closed! You can now assign it to a location.', 'success');
} else {
showAlert('alert-tab1', data.message || 'Failed to change box status', 'error');
}
} catch (error) {
showAlert('alert-tab1', 'Error changing box status', 'error');
console.error('Error:', error);
} finally {
hideSpinner('spinner-status', 'btn-status-text', '🔒 Close Box');
}
}
// Tab 1: Search Box
async function searchBox() {
const boxNumber = document.getElementById('box-number-input').value.trim();
if (!boxNumber) {
showAlert('alert-tab1', 'Please enter a box number', 'error');
return;
}
hideAlert('alert-tab1');
showSpinner('spinner-search-box', 'btn-search-text', 'Searching...');
try {
const response = await fetch('/api/warehouse/box/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ box_number: boxNumber })
});
const data = await response.json();
if (data.success) {
currentBoxId = data.box.id;
document.getElementById('display-box-number').textContent = data.box.box_number;
// Update status badge
const statusBadge = document.getElementById('display-box-status-badge');
statusBadge.textContent = data.box.status;
statusBadge.className = `status-badge ${data.box.status}`;
document.getElementById('display-current-location').textContent =
data.box.location_code || 'Not assigned';
document.getElementById('box-info').classList.add('show');
// Show/hide status change button and assign section based on status
const statusBtn = document.getElementById('btn-change-status');
const statusBtnText = document.getElementById('btn-status-text');
const assignSection = document.getElementById('assign-section');
if (data.box.status === 'open') {
statusBtn.style.display = 'block';
statusBtnText.textContent = '🔒 Close Box';
assignSection.style.display = 'none';
showAlert('alert-tab1', 'Box found! Please close the box before assigning to a location.', 'info');
} else {
statusBtn.style.display = 'none';
assignSection.style.display = 'block';
showAlert('alert-tab1', 'Box found! You can now assign it to a location.', 'success');
}
} else {
currentBoxId = null;
document.getElementById('box-info').classList.remove('show');
document.getElementById('assign-section').style.display = 'none';
showAlert('alert-tab1', data.message || 'Box not found', 'error');
}
} catch (error) {
showAlert('alert-tab1', 'Error searching for box', 'error');
console.error('Error:', error);
} finally {
hideSpinner('spinner-search-box', 'btn-search-text', '🔍 Search Box');
}
}
// Tab 1: Assign Box to Location
async function assignBoxToLocation() {
const locationCode = document.getElementById('location-code-input-tab1').value.trim();
if (!currentBoxId) {
showAlert('alert-tab1', 'Please search for a box first', 'error');
return;
}
if (!locationCode) {
showAlert('alert-tab1', 'Please enter a location code', 'error');
return;
}
// Check if box is closed before allowing assignment
const statusBadge = document.getElementById('display-box-status-badge');
if (statusBadge.textContent === 'open') {
showAlert('alert-tab1', 'Please close the box before assigning to a location', 'error');
return;
}
hideAlert('alert-tab1');
showSpinner('spinner-assign', 'btn-assign-text', 'Assigning...');
try {
const response = await fetch('/api/warehouse/box/assign-location', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
box_id: currentBoxId,
location_code: locationCode
})
});
const data = await response.json();
if (data.success) {
showAlert('alert-tab1', data.message, 'success');
// Update display
document.getElementById('display-current-location').textContent = locationCode;
// Clear inputs
document.getElementById('box-number-input').value = '';
document.getElementById('location-code-input-tab1').value = '';
// Reset after 2 seconds
setTimeout(() => {
document.getElementById('box-info').classList.remove('show');
document.getElementById('assign-section').style.display = 'none';
hideAlert('alert-tab1');
currentBoxId = null;
document.getElementById('box-number-input').focus();
}, 2000);
} else {
showAlert('alert-tab1', data.message || 'Failed to assign box', 'error');
}
} catch (error) {
showAlert('alert-tab1', 'Error assigning box to location', 'error');
console.error('Error:', error);
} finally {
hideSpinner('spinner-assign', 'btn-assign-text', '✅ Assign to Location');
}
}
// Tab 2: Search Location
async function searchLocation() {
const locationCode = document.getElementById('location-code-input-tab2').value.trim();
if (!locationCode) {
showAlert('alert-tab2', 'Please enter a location code', 'error');
return;
}
hideAlert('alert-tab2');
showSpinner('spinner-search-location', 'btn-search-location-text', 'Searching...');
try {
const response = await fetch('/api/warehouse/location/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ location_code: locationCode })
});
const data = await response.json();
if (data.success) {
currentLocationId = data.location.id;
document.getElementById('display-location-code').textContent = data.location.location_code;
document.getElementById('display-boxes-count').textContent = data.boxes.length;
document.getElementById('location-info').classList.add('show');
if (data.boxes.length > 0) {
displayBoxes(data.boxes);
document.getElementById('boxes-list').classList.add('show');
showAlert('alert-tab2', `Found ${data.boxes.length} box(es) in this location`, 'success');
} else {
document.getElementById('boxes-list').classList.remove('show');
showAlert('alert-tab2', 'No boxes found in this location', 'info');
}
} else {
currentLocationId = null;
document.getElementById('location-info').classList.remove('show');
document.getElementById('boxes-list').classList.remove('show');
showAlert('alert-tab2', data.message || 'Location not found', 'error');
}
} catch (error) {
showAlert('alert-tab2', 'Error searching for location', 'error');
console.error('Error:', error);
} finally {
hideSpinner('spinner-search-location', 'btn-search-location-text', '🔍 Search Location');
}
}
// Display boxes in location
function displayBoxes(boxes) {
const container = document.getElementById('boxes-container');
container.innerHTML = '';
boxes.forEach(box => {
const boxItem = document.createElement('div');
boxItem.className = 'box-item';
boxItem.onclick = () => selectBox(box.id, box.box_number, boxItem);
boxItem.innerHTML = `
<div class="box-info">
<div class="box-number">📦 ${box.box_number}</div>
<div class="box-status">Status: ${box.status}</div>
</div>
<div class="box-icon"></div>
`;
container.appendChild(boxItem);
});
}
// Select a box
function selectBox(boxId, boxNumber, element) {
// Remove previous selection
document.querySelectorAll('.box-item').forEach(item => {
item.classList.remove('selected');
});
// Add selection
element.classList.add('selected');
selectedBoxId = boxId;
selectedBoxNumber = boxNumber;
// Show move section
document.getElementById('selected-box-display').textContent = boxNumber;
document.getElementById('move-section').style.display = 'block';
document.getElementById('new-location-input').focus();
}
// Clear selection
function clearSelection() {
selectedBoxId = null;
selectedBoxNumber = null;
document.querySelectorAll('.box-item').forEach(item => {
item.classList.remove('selected');
});
document.getElementById('move-section').style.display = 'none';
document.getElementById('new-location-input').value = '';
}
// Move box to new location
async function moveBox() {
const newLocationCode = document.getElementById('new-location-input').value.trim();
if (!selectedBoxId) {
showAlert('alert-tab2', 'Please select a box first', 'error');
return;
}
if (!newLocationCode) {
showAlert('alert-tab2', 'Please enter a new location code', 'error');
return;
}
hideAlert('alert-tab2');
showSpinner('spinner-move', 'btn-move-text', 'Moving...');
try {
const response = await fetch('/api/warehouse/box/move-location', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
box_id: selectedBoxId,
new_location_code: newLocationCode
})
});
const data = await response.json();
if (data.success) {
showAlert('alert-tab2', data.message, 'success');
// Refresh the location search
setTimeout(() => {
clearSelection();
searchLocation();
}, 1500);
} else {
showAlert('alert-tab2', data.message || 'Failed to move box', 'error');
}
} catch (error) {
showAlert('alert-tab2', 'Error moving box', 'error');
console.error('Error:', error);
} finally {
hideSpinner('spinner-move', 'btn-move-text', '🚚 Move to New Location');
}
}
// Handle Enter key press for inputs
document.getElementById('box-number-input').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
searchBox();
}
});
document.getElementById('location-code-input-tab1').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
assignBoxToLocation();
}
});
document.getElementById('location-code-input-tab2').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
searchLocation();
}
});
document.getElementById('new-location-input').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
moveBox();
}
});
</script>
{% endblock %}