From 7bee3bfedc46a711c76693702345b208bbbc3f15 Mon Sep 17 00:00:00 2001 From: NguyenND Date: Wed, 15 Apr 2026 15:38:51 -0400 Subject: [PATCH] 04/15 Updated Editing QR code page, QR code name is unchangeable --- routes/qr_codes.py | 10 +- templates/edit_qr_code.html | 519 +++++++++++++++--------------------- 2 files changed, 228 insertions(+), 301 deletions(-) diff --git a/routes/qr_codes.py b/routes/qr_codes.py index 6ee2a2c..f31f30f 100644 --- a/routes/qr_codes.py +++ b/routes/qr_codes.py @@ -454,9 +454,11 @@ def edit_qr_code(qr_id): 'back_color': getattr(qr_code, 'back_color', '#FFFFFF') } - # Update QR code fields - new_name = request.form['name'] - qr_code.name = new_name + # QR code name is immutable after creation — always retain the existing value. + # The name field in the edit form is rendered read-only; this guard ensures + # the constraint is enforced even if the form is submitted programmatically. + new_name = qr_code.name # do not accept name changes from the form + # qr_code.name is intentionally NOT reassigned here # --- ADDED: for dynamic QR codes, location/address are auto-managed --- new_qr_type = request.form.get('qr_type', 'standard') @@ -1196,4 +1198,4 @@ def deactivate_qr_code(qr_id): return jsonify({ 'success': False, 'message': 'Error deactivating QR code. Please try again.' - }), 500 + }), 500 \ No newline at end of file diff --git a/templates/edit_qr_code.html b/templates/edit_qr_code.html index 1545efd..0c92825 100644 --- a/templates/edit_qr_code.html +++ b/templates/edit_qr_code.html @@ -289,7 +289,7 @@ background: var(--primary-color); cursor: pointer; border: 2px solid white; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .range-input-group input[type="range"]::-moz-range-thumb { @@ -299,7 +299,7 @@ background: var(--primary-color); cursor: pointer; border: 2px solid white; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .range-value { @@ -544,18 +544,18 @@ .form-row { grid-template-columns: 1fr; } - + .qr-preview-container { flex-direction: column; text-align: center; } - + .range-input-group { flex-direction: column; gap: 0.5rem; align-items: stretch; } - + .range-value { text-align: center; } @@ -579,9 +579,17 @@ } @keyframes pulse { - 0% { transform: scale(1); } - 50% { transform: scale(1.05); } - 100% { transform: scale(1); } + 0% { + transform: scale(1); + } + + 50% { + transform: scale(1.05); + } + + 100% { + transform: scale(1); + } } /* Toast notification styles */ @@ -629,24 +637,19 @@
- - A unique name to identify this QR code -
- {{ qr_code.name|length }}/100 -
+ style="background-color: var(--gray-100); color: var(--gray-600); cursor: not-allowed; border-color: var(--gray-300);" /> + + + The QR code name cannot be changed after creation. +
@@ -657,8 +660,10 @@ * Standard: employee checks in at one fixed location.
@@ -668,30 +673,23 @@ -
-
- - - The name of the physical location where this QR code will be - used -
- {{ qr_code.location|length if qr_code.qr_type != 'dynamic' else '0' }}/100 +
+
+ + + The name of the physical location where this QR code will be + used +
+ {{ qr_code.location|length if qr_code.qr_type != 'dynamic' else '0' + }}/100 +
-
@@ -699,10 +697,11 @@ Project (Optional) - {% for project in projects %} - {% endfor %} @@ -715,96 +714,81 @@
-
-
-
-

- - Location Details -

-

Update the complete address and event information

-
- -
- - - Include all address details for accurate location - identification -
- {{ qr_code.location_address|length }}/500 +
+
+
+

+ + Location Details +

+

Update the complete address and event information

- -
-
- -

Address Coordinates

+
+ + + Include all address details for accurate location + identification +
+ {{ qr_code.location_address|length }}/500
-
-
-
-
- {% if qr_code.has_coordinates %} - {{ "%.6f"|format(qr_code.address_latitude) }} - {% else %} - ---.---------- - {% endif %} -
-
Latitude
-
-
-
- {% if qr_code.has_coordinates %} - {{ "%.6f"|format(qr_code.address_longitude) }} - {% else %} - ---.---------- - {% endif %} -
-
Longitude
-
+ +
+
+ +

Address Coordinates

-
- - -
+
+
+
+
+ {% if qr_code.has_coordinates %} + {{ "%.6f"|format(qr_code.address_latitude) }} + {% else %} + ---.---------- + {% endif %} +
+
Latitude
+
+
+
+ {% if qr_code.has_coordinates %} + {{ "%.6f"|format(qr_code.address_longitude) }} + {% else %} + ---.---------- + {% endif %} +
+
Longitude
+
+
-
+
+ + +
+ +
+
-
-
+
@@ -815,20 +799,14 @@ Event or Purpose * - - - + + - Select the event type for this QR code + Select the event type for this QR code
@@ -852,13 +830,9 @@ - + +
Color of the QR code modules
@@ -900,21 +863,10 @@ Background Color
- - + +
Background color of the QR code
@@ -928,15 +880,8 @@ Module Size
- + {{ qr_code.box_size or 10 }}px
Size of each QR code module (affects overall size) @@ -948,15 +893,8 @@ Border Size
- + {{ qr_code.border or 4 }} modules
White border around the QR code @@ -970,10 +908,11 @@ Error Correction Level Higher levels allow QR code to work even if partially damaged
@@ -1008,24 +947,12 @@
- - - + + +
@@ -1110,9 +1037,11 @@
Colors: - + on - +
@@ -1125,11 +1054,11 @@ function updateCharacterCount(inputId, counterId, maxLength) { const input = document.getElementById(inputId); const counter = document.getElementById(counterId); - + if (input && counter) { const length = input.value.length; counter.textContent = `${length}/${maxLength}`; - + if (length > maxLength * 0.9) { counter.classList.add('warning'); } else { @@ -1142,7 +1071,7 @@ function applyStylePreset() { const styleSelect = document.getElementById('style_id'); const selectedOption = styleSelect.options[styleSelect.selectedIndex]; - + if (selectedOption.value) { // Apply preset values const fillColor = selectedOption.getAttribute('data-fill'); @@ -1150,7 +1079,7 @@ const boxSize = selectedOption.getAttribute('data-box-size'); const border = selectedOption.getAttribute('data-border'); const errorCorrection = selectedOption.getAttribute('data-error-correction'); - + // Update form inputs document.getElementById('fill_color').value = fillColor; document.getElementById('fill_color_text').value = fillColor; @@ -1159,14 +1088,14 @@ document.getElementById('box_size').value = boxSize; document.getElementById('border').value = border; document.getElementById('error_correction').value = errorCorrection; - + // Update range value displays updateRangeValue('box_size'); updateRangeValue('border'); - + // Update preview updatePreview(); - + // Show toast notification showToast(`Applied "${selectedOption.text}" style preset`, 'success'); } @@ -1175,14 +1104,14 @@ function syncColorInput(type) { const colorInput = document.getElementById(`${type}_color`); const textInput = document.getElementById(`${type}_color_text`); - + let value = textInput.value.trim().toUpperCase(); - + // Add # if missing if (!value.startsWith('#')) { value = '#' + value; } - + // Validate hex format if (/^#[0-9A-F]{6}$/i.test(value)) { colorInput.value = value; @@ -1198,7 +1127,7 @@ function updateRangeValue(inputId) { const input = document.getElementById(inputId); const valueDisplay = document.getElementById(`${inputId}_value`); - + if (inputId === 'box_size') { valueDisplay.textContent = `${input.value}px`; } else if (inputId === 'border') { @@ -1211,31 +1140,31 @@ const backColor = document.getElementById('back_color').value; const boxSize = document.getElementById('box_size').value; const border = document.getElementById('border').value; - + // Update preview QR modules const qrSample = document.getElementById('qr_sample'); const qrModules = qrSample.querySelectorAll('.qr-module:not(.empty)'); - + // Apply colors to QR modules qrModules.forEach(module => { module.style.backgroundColor = fillColor; }); - + // Apply background color qrSample.style.backgroundColor = backColor; - + // Apply border (padding represents border) const borderPx = Math.max(4, parseInt(border) * 2); qrSample.style.padding = `${borderPx}px`; - + // Apply module size effect (simulate with scale) const scale = Math.max(0.7, Math.min(1.3, parseInt(boxSize) / 10)); qrSample.style.transform = `scale(${scale})`; - + // Sync text inputs with color inputs document.getElementById('fill_color_text').value = fillColor.toUpperCase(); document.getElementById('back_color_text').value = backColor.toUpperCase(); - + // Add animation class const preview = document.getElementById('qr_preview'); preview.style.animation = 'none'; @@ -1253,11 +1182,11 @@ document.getElementById('box_size').value = '10'; document.getElementById('border').value = '4'; document.getElementById('error_correction').value = 'L'; - + updateRangeValue('box_size'); updateRangeValue('border'); updatePreview(); - + showToast('Reset to default QR code styling', 'info'); } @@ -1271,7 +1200,7 @@ ${message}
`; - + toast.style.cssText = ` position: fixed; top: 20px; @@ -1287,14 +1216,14 @@ border-left: 4px solid ${getToastColor(type)}; max-width: 350px; `; - + document.body.appendChild(toast); - + setTimeout(() => { toast.style.opacity = '1'; toast.style.transform = 'translateX(0)'; }, 100); - + setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translateX(100%)'; @@ -1330,23 +1259,23 @@ function validateQRCustomization() { const fillColor = document.getElementById('fill_color_text').value; const backColor = document.getElementById('back_color_text').value; - + // Check if colors are too similar if (fillColor.toLowerCase() === backColor.toLowerCase()) { showToast('QR code color and background color cannot be the same', 'error'); return false; } - + return true; } // Geocoding functionality function geocodeAddress(address) { showStatus('info', 'Getting coordinates...'); - + // Using server API which prefers Google Maps with OpenStreetMap fallback const encodedAddress = encodeURIComponent(address); - + // First try the server API fetch('/api/geocode', { method: 'POST', @@ -1355,32 +1284,32 @@ }, body: JSON.stringify({ address: address }) }) - .then(response => response.json()) - .then(data => { - if (data.success) { - const lat = data.data.latitude; - const lng = data.data.longitude; - - updateCoordinates(lat, lng, 'geocoded'); - showStatus('success', data.message || 'Coordinates updated successfully'); - } else { - showStatus('warning', data.message || 'No coordinates found for this address'); - } - }) - .catch(error => { - console.error('Geocoding error:', error); - showStatus('error', 'Failed to get coordinates. Please try again.'); - }); + .then(response => response.json()) + .then(data => { + if (data.success) { + const lat = data.data.latitude; + const lng = data.data.longitude; + + updateCoordinates(lat, lng, 'geocoded'); + showStatus('success', data.message || 'Coordinates updated successfully'); + } else { + showStatus('warning', data.message || 'No coordinates found for this address'); + } + }) + .catch(error => { + console.error('Geocoding error:', error); + showStatus('error', 'Failed to get coordinates. Please try again.'); + }); } function updateCoordinates(lat, lng, accuracy) { document.getElementById('address_latitude').value = lat; document.getElementById('address_longitude').value = lng; document.getElementById('coordinate_accuracy').value = accuracy; - + document.getElementById('latitudeDisplay').textContent = lat.toFixed(10); document.getElementById('longitudeDisplay').textContent = lng.toFixed(10); - + document.getElementById('clearCoordinatesBtn').style.display = 'inline-flex'; document.getElementById('geocodeBtn').innerHTML = ' Update Coordinates'; } @@ -1389,13 +1318,13 @@ document.getElementById('address_latitude').value = ''; document.getElementById('address_longitude').value = ''; document.getElementById('coordinate_accuracy').value = ''; - + document.getElementById('latitudeDisplay').textContent = '---.----------'; document.getElementById('longitudeDisplay').textContent = '---.----------'; - + document.getElementById('clearCoordinatesBtn').style.display = 'none'; document.getElementById('geocodeBtn').innerHTML = ' Get Coordinates'; - + showStatus('info', 'Coordinates cleared'); } @@ -1403,7 +1332,7 @@ const statusDiv = document.getElementById('coordinateStatus'); if (statusDiv) { statusDiv.innerHTML = `
${message}
`; - + setTimeout(() => { statusDiv.innerHTML = ''; }, 5000); @@ -1418,12 +1347,8 @@ } // Initialize on page load - document.addEventListener('DOMContentLoaded', function() { + document.addEventListener('DOMContentLoaded', function () { // Set up character counters - document.getElementById('name').addEventListener('input', () => { - updateCharacterCount('name', 'nameCounter', 100); - updateCurrentInfo(); - }); document.getElementById('location').addEventListener('input', () => { updateCharacterCount('location', 'locationCounter', 100); updateCurrentInfo(); @@ -1432,33 +1357,33 @@ updateCharacterCount('location_address', 'addressCounter', 500); updateCurrentInfo(); }); - + // Set up event listener for location_event document.getElementById('location_event').addEventListener('change', updateCurrentInfo); - + // Set up initial values for QR customization updateRangeValue('box_size'); updateRangeValue('border'); updatePreview(); - + // Add form validation const form = document.getElementById('editQRForm'); if (form) { - form.addEventListener('submit', function(e) { + form.addEventListener('submit', function (e) { if (!validateQRCustomization()) { e.preventDefault(); return false; } }); } - + // Add color input synchronization - document.getElementById('fill_color').addEventListener('change', function() { + document.getElementById('fill_color').addEventListener('change', function () { document.getElementById('fill_color_text').value = this.value.toUpperCase(); updatePreview(); }); - - document.getElementById('back_color').addEventListener('change', function() { + + document.getElementById('back_color').addEventListener('change', function () { document.getElementById('back_color_text').value = this.value.toUpperCase(); updatePreview(); }); @@ -1467,7 +1392,7 @@ const geocodeBtn = document.getElementById('geocodeBtn'); const clearBtn = document.getElementById('clearCoordinatesBtn'); - geocodeBtn.addEventListener('click', function() { + geocodeBtn.addEventListener('click', function () { const address = document.getElementById('location_address').value.trim(); if (address.length > 10) { geocodeAddress(address); @@ -1483,26 +1408,26 @@