// API base URL const API_BASE_URL = '/api'; // Show toast notification function showToast(message, type = 'success') { const toast = document.createElement('div'); toast.className = `fixed bottom-4 right-4 px-6 py-3 rounded-lg shadow-lg text-white ${ type === 'success' ? 'bg-green-600' : 'bg-red-600' } transform translate-y-0 opacity-100 transition-all duration-300 z-50`; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { toast.style.transform = 'translateY(100%)'; toast.style.opacity = '0'; setTimeout(() => toast.remove(), 300); }, 3000); } // Show loading state function setLoading(isLoading) { const submitButton = document.querySelector('#createLabelForm button[type="submit"]'); if (isLoading) { submitButton.disabled = true; submitButton.classList.add('opacity-50', 'cursor-not-allowed'); submitButton.textContent = 'Creating...'; } else { submitButton.disabled = false; submitButton.classList.remove('opacity-50', 'cursor-not-allowed'); submitButton.textContent = 'Create Label'; } } // Add metadata field function addMetadataField() { const metadataFields = document.getElementById('metadataFields'); const fieldId = Date.now(); // Simple unique ID const fieldDiv = document.createElement('div'); fieldDiv.className = 'flex space-x-3 items-end'; fieldDiv.innerHTML = `
`; metadataFields.appendChild(fieldDiv); } // Remove metadata field function removeMetadataField(button) { button.closest('div').remove(); } // Validate UPC code function validateUPC(upc) { if (!upc) return true; // Empty UPC is valid (optional field) // Remove any non-digit characters const digitsOnly = upc.replace(/[^0-9]/g, ''); // Check for valid lengths if (digitsOnly.length === 12) { return validateUPCAChecksum(digitsOnly); } else if (digitsOnly.length === 8) { return validateUPCChecksum(digitsOnly); } else if (digitsOnly.length === 13) { return validateEAN13Checksum(digitsOnly); } return false; } // Validate UPC-A checksum function validateUPCAChecksum(upc) { if (upc.length !== 12 || !/^\d+$/.test(upc)) { return false; } let total = 0; for (let i = 0; i < 11; i++) { const digit = parseInt(upc[i]); if (i % 2 === 0) { // Odd positions (0-indexed) total += digit * 3; } else { // Even positions total += digit; } } const checksum = (10 - (total % 10)) % 10; return checksum === parseInt(upc[11]); } // Validate UPC-E checksum function validateUPCChecksum(upc) { if (upc.length !== 8 || !/^\d+$/.test(upc)) { return false; } let total = 0; for (let i = 0; i < 7; i++) { const digit = parseInt(upc[i]); if (i % 2 === 0) { // Odd positions (0-indexed) total += digit * 3; } else { // Even positions total += digit; } } const checksum = (10 - (total % 10)) % 10; return checksum === parseInt(upc[7]); } // Validate EAN-13 checksum function validateEAN13Checksum(ean) { if (ean.length !== 13 || !/^\d+$/.test(ean)) { return false; } let total = 0; for (let i = 0; i < 12; i++) { const digit = parseInt(ean[i]); if (i % 2 === 0) { // Even positions (0-indexed) total += digit; } else { // Odd positions total += digit * 3; } } const checksum = (10 - (total % 10)) % 10; return checksum === parseInt(ean[12]); } // Collect form data function collectFormData() { const upc = document.getElementById('upc').value.trim(); const print = document.getElementById('printLabel').checked; // Collect metadata const metadata = []; const metadataFields = document.querySelectorAll('#metadataFields input[type="text"]'); for (let i = 0; i < metadataFields.length; i += 2) { const keyInput = metadataFields[i]; const valueInput = metadataFields[i + 1]; if (keyInput && valueInput && keyInput.value.trim() && valueInput.value.trim()) { metadata.push({ key: keyInput.value.trim(), value: valueInput.value.trim() }); } } return { upc: upc || null, metadata: metadata.length > 0 ? metadata : null, print: print }; } // Create inventory label async function createInventoryLabel(formData) { try { setLoading(true); const response = await fetch(`${API_BASE_URL}/inventory-labels/`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(formData) }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || 'Failed to create inventory label'); } const result = await response.json(); showToast('Inventory label created successfully!', 'success'); // Reset form document.getElementById('createLabelForm').reset(); document.getElementById('metadataFields').innerHTML = ''; // Optionally refresh recent labels // loadRecentLabels(); return result; } catch (error) { showToast('Error creating inventory label: ' + error.message, 'error'); throw error; } finally { setLoading(false); } } // Handle form submission async function handleFormSubmit(event) { event.preventDefault(); const formData = collectFormData(); // Validate UPC if provided if (formData.upc && !validateUPC(formData.upc)) { showToast('Invalid UPC code. Please enter a valid UPC-A, UPC-E, or EAN-13 code.', 'error'); return; } // Validate metadata if provided if (formData.metadata) { for (const item of formData.metadata) { if (!item.key || !item.value) { showToast('All metadata fields must have both key and value.', 'error'); return; } } } try { await createInventoryLabel(formData); } catch (error) { console.error('Error creating inventory label:', error); } } // Load recent labels (placeholder for future implementation) async function loadRecentLabels() { // This could be implemented to show recently created labels // For now, it's a placeholder const recentLabelsDiv = document.getElementById('recentLabels'); recentLabelsDiv.innerHTML = '

No recent labels to display

'; } // Initialize page document.addEventListener('DOMContentLoaded', function() { // Set up form submission handler document.getElementById('createLabelForm').addEventListener('submit', handleFormSubmit); // Load recent labels loadRecentLabels(); // Add initial metadata field addMetadataField(); });