// 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();
});