From 281dad2b75cb25cd79e13aeeda27f2b89690f96a Mon Sep 17 00:00:00 2001 From: Nguyen Ngo Date: Wed, 13 Aug 2025 16:08:47 -0400 Subject: [PATCH] Update dashboard layout --- templates/dashboard.html | 135 +++++++++++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 14 deletions(-) diff --git a/templates/dashboard.html b/templates/dashboard.html index 2db14b0..5396956 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -308,6 +308,16 @@ color: var(--white); } +.qr-action-btn.download { + background: rgba(16, 185, 129, 0.1); + color: #059669; +} + +.qr-action-btn.download:hover { + background: #059669; + color: var(--white); +} + .qr-action-btn.delete { background: rgba(239, 68, 68, 0.1); color: #dc2626; @@ -493,6 +503,19 @@ text-align: center; } +.modal-actions { + display: flex; + gap: var(--spacing-3); + justify-content: center; + margin-top: var(--spacing-4); + flex-wrap: wrap; +} + +.modal-actions .btn { + flex: 1; + min-width: 140px; +} + /* Animations */ @keyframes fadeIn { from { opacity: 0; } @@ -693,14 +716,14 @@ {% for qr in project_qr_codes %}
- QR Code for {{ qr.name }} + QR Code for {{ qr.name }}

{{ qr.name }}

@@ -717,6 +740,10 @@
+ + @@ -769,14 +796,14 @@ {% for qr in unassigned_qr_codes %}
- QR Code for {{ qr.name }} + QR Code for {{ qr.name }}

{{ qr.name }}

@@ -793,6 +820,10 @@
+ + @@ -847,7 +878,17 @@
@@ -936,23 +977,29 @@ class ProjectDashboardManager { // QR Code Management Functions async toggleQRCodeStatus(qrId) { try { - const response = await fetch(`/qr-codes/${qrId}/toggle`, { + const response = await fetch(`/qr-codes/${qrId}/toggle-status`, { method: 'POST', headers: { 'Content-Type': 'application/json', + 'X-Requested-With': 'XMLHttpRequest' } }); if (response.ok) { - // Show success message - if (window.showToast) { - window.showToast('QR code status updated successfully', 'success'); + const result = await response.json(); + if (result.success) { + // Show success message + if (window.showToast) { + window.showToast(result.message, 'success'); + } + + // Reload page to reflect changes + setTimeout(() => { + window.location.reload(); + }, 1000); + } else { + throw new Error(result.message || 'Failed to toggle QR code status'); } - - // Reload page to reflect changes - setTimeout(() => { - window.location.reload(); - }, 1000); } else { throw new Error('Failed to toggle QR code status'); } @@ -1062,6 +1109,15 @@ class ProjectDashboardManager { modalImage.src = qrData.image; modal.style.display = 'flex'; + // Store current modal QR data for download and copy functions + this.currentModalQR = { + name: qrData.name, + image: qrData.image, + location: qrData.location, + address: qrData.address, + event: qrData.event + }; + // Add keyboard listener for escape key document.addEventListener('keydown', this.handleModalKeydown.bind(this)); } @@ -1071,6 +1127,7 @@ class ProjectDashboardManager { const modal = document.getElementById('qrModal'); if (modal) { modal.style.display = 'none'; + this.currentModalQR = null; // Remove keyboard listener document.removeEventListener('keydown', this.handleModalKeydown.bind(this)); @@ -1083,6 +1140,53 @@ class ProjectDashboardManager { } } + // Download QR Code functionality + downloadQR(base64Image, filename) { + try { + // Extract base64 data if it includes the data URL prefix + const base64Data = base64Image.includes('base64,') + ? base64Image.split('base64,')[1] + : base64Image; + + const link = document.createElement('a'); + link.href = `data:image/png;base64,${base64Data}`; + link.download = `${filename.replace(/[^a-z0-9]/gi, '_').toLowerCase()}_qr_code.png`; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + // Show success toast + if (window.showToast) { + window.showToast('QR code downloaded successfully!', 'success'); + } + } catch (error) { + console.error('Download error:', error); + if (window.showToast) { + window.showToast('Failed to download QR code', 'error'); + } + } + } + + // Download from modal + downloadModalQR() { + if (this.currentModalQR) { + this.downloadQR(this.currentModalQR.image, this.currentModalQR.name); + } + } + + // Copy QR data from modal + copyModalQRData() { + if (this.currentModalQR) { + this.copyQRData( + this.currentModalQR.name, + this.currentModalQR.location, + this.currentModalQR.address, + this.currentModalQR.event + ); + } + } + // Utility Methods copyQRData(name, location, address, event) { const data = `QR Code: ${name}\nLocation: ${location}\nAddress: ${address}\nEvent: ${event}`; @@ -1160,6 +1264,9 @@ document.addEventListener('DOMContentLoaded', function() { window.closeQRModal = () => dashboardManager.closeQRModal(); window.copyQRData = (name, location, address, event) => dashboardManager.copyQRData(name, location, address, event); + window.downloadModalQR = () => dashboardManager.downloadModalQR(); + window.copyModalQRData = () => dashboardManager.copyModalQRData(); + window.downloadQR = (base64Image, filename) => dashboardManager.downloadQR(base64Image, filename); // Add keyboard shortcuts (optional) document.addEventListener('keydown', function(event) {