From 0f631ed1ae7b647767ab373354e2abee86fadf2e Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Fri, 30 May 2025 10:30:17 +0200 Subject: [PATCH] ggg --- admin-dashboard.html | 369 +++++++++++++++++++++++-------------------- 1 file changed, 196 insertions(+), 173 deletions(-) diff --git a/admin-dashboard.html b/admin-dashboard.html index 730a9d3..76aa5f4 100644 --- a/admin-dashboard.html +++ b/admin-dashboard.html @@ -1158,7 +1158,10 @@ function updateBannerPreview() { } // Banner variables will be initialized in DOMContentLoaded -let bannerVisible, bannerBgColor, bannerTextColor, bannerText, bannerTextAlign, bannerFontSize, bannerPadding, bannerMargin, bannerBorderRadius, bannerPreview; +let bannerBgColor, bannerTextColor, bannerText, bannerTextAlign, bannerFontSize, bannerPadding, bannerMargin, bannerBorderRadius, bannerPreview; + +// Banner visibility state +let bannerVisible; // Initialize template object let template = { @@ -2030,30 +2033,48 @@ function filterIcons() { // Select an icon function selectIcon(iconClass) { - document.getElementById('selectedIcon').className = `fas ${iconClass} text-xl`; - document.getElementById('appIconClass').value = iconClass; - document.getElementById('fileName').textContent = iconClass.replace('fa-', '').replace(/-/g, ' '); + const selectedIcon = document.getElementById('selectedIcon'); + const appIconClass = document.getElementById('appIconClass'); + const fileName = document.getElementById('fileName'); + const iconPreview = document.getElementById('iconPreview'); + const appIcon = document.getElementById('appIcon'); + + if (selectedIcon) selectedIcon.className = `fas ${iconClass} text-xl`; + if (appIconClass) appIconClass.value = iconClass; + if (fileName) fileName.textContent = iconClass.replace('fa-', '').replace(/-/g, ' '); // Update preview with random color const colors = ['blue', 'green', 'red', 'yellow', 'indigo', 'purple', 'pink', 'gray']; const randomColor = colors[Math.floor(Math.random() * colors.length)]; - document.getElementById('iconPreview').className = `w-12 h-12 rounded-full bg-${randomColor}-100 text-${randomColor}-600 flex items-center justify-center mr-3`; + if (iconPreview) { + iconPreview.className = `w-12 h-12 rounded-full bg-${randomColor}-100 text-${randomColor}-600 flex items-center justify-center mr-3`; + } // Reset file input if an icon is selected - document.getElementById('appIcon').value = ''; + if (appIcon) appIcon.value = ''; } // Initialize icon picker when the page loads document.addEventListener('DOMContentLoaded', function() { - initIconPicker(); + // Initialize banner visibility + bannerVisible = document.getElementById('bannerVisibility'); + + // Initialize icon picker + const iconPicker = document.getElementById('iconPicker'); + if (iconPicker) { + initIconPicker(); + } // Update icon preview when editing an existing app - document.getElementById('appModal').addEventListener('shown.bs.modal', function() { - const iconClass = document.getElementById('appIconClass').value; - if (iconClass) { - selectIcon(iconClass); - } - }); + const appModal = document.getElementById('appModal'); + if (appModal) { + appModal.addEventListener('shown.bs.modal', function() { + const iconClass = document.getElementById('appIconClass')?.value; + if (iconClass) { + selectIcon(iconClass); + } + }); + } }); // Initialize file input handling when the page loads @@ -2061,6 +2082,40 @@ document.addEventListener('DOMContentLoaded', () => { setupFileInput(); }); +// Delete app function +async function deleteApp(appId) { + if (!confirm('Opravdu chcete smazat tuto aplikaci? Tuto akci nelze vrátit zpět.')) { + return; + } + + try { + const token = localStorage.getItem('token'); + if (!token) { + window.location.href = '/login.html'; + return; + } + + const response = await fetch(`/api/apps/${appId}`, { + method: 'DELETE', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + throw new Error('Nepodařilo se smazat aplikaci'); + } + + // Reload the apps list + await loadDynamicApps(); + showNotification('Aplikace byla úspěšně smazána', 'success'); + } catch (error) { + console.error('Error deleting app:', error); + showNotification(error.message || 'Nastala chyba při mazání aplikace', 'error'); + } +} + // Logout functionality document.getElementById('logoutBtn').addEventListener('click', function() { localStorage.removeItem('token'); @@ -2610,25 +2665,22 @@ function updateBannerPreview() { const bannerTemplates = document.getElementById('bannerTemplates'); const imagePreview = document.getElementById('imagePreview'); const imagePreviewContainer = document.getElementById('imagePreviewContainer'); - const imageSizeControls = document.getElementById('imageSizeControls'); - // Get the current template config or use default - const defaultTemplate = templateConfigs['modern-minimal'] || {}; + // Get the current template config or use modern as default + const defaultTemplate = templateConfigs['modern'] || {}; const template = currentTemplate ? (templateConfigs[currentTemplate] || defaultTemplate) : defaultTemplate; const fileInput = document.getElementById('bannerImage'); const hasImage = Boolean(currentImage || (fileInput && fileInput.files && fileInput.files.length > 0)); // Ensure template has required properties if (!template.background && !template.backgroundColor) { - template.backgroundColor = '#f8f9fa'; + template.backgroundColor = template.backgroundColor || '#f8f9fa'; + template.background = template.background || template.backgroundColor; } - // Show/hide templates and size controls based on image presence + // Always show templates section if (bannerTemplates) { - bannerTemplates.style.display = hasImage ? 'block' : 'none'; - } - if (imageSizeControls) { - imageSizeControls.style.display = hasImage ? 'flex' : 'none'; + bannerTemplates.style.display = 'block'; } // Create banner content based on template @@ -2636,33 +2688,85 @@ function updateBannerPreview() { const bannerLink = document.getElementById('bannerLink')?.value || ''; const bannerTextContent = bannerText || 'Náhled banneru'; - // Get the current position or default to 'right' - const position = currentImagePosition || 'right'; + // Get all styles from template or use defaults + const styles = { + // Background styles + background: (bannerBgColorPicker?.value || template.background || template.backgroundColor || '#f8f9fa').trim(), + backgroundColor: (bannerBgColorPicker?.value || template.backgroundColor || '#f8f9fa').trim(), + + // Text styles + color: (bannerTextColorPicker?.value || template.textColor || template.textStyle?.match(/color:\s*([^;]+)/)?.[1] || '#212529').trim(), + textColor: (bannerTextColorPicker?.value || template.textColor || template.textStyle?.match(/color:\s*([^;]+)/)?.[1] || '#212529').trim(), + textAlign: (document.getElementById('bannerTextAlign')?.value || 'left').trim(), + fontSize: (document.getElementById('bannerFontSize')?.value ? `${document.getElementById('bannerFontSize').value}px` : '16px'), + + // Layout styles + padding: (document.getElementById('bannerPadding')?.value ? `${document.getElementById('bannerPadding').value}px` : '20px'), + margin: (document.getElementById('bannerMargin')?.value ? `${document.getElementById('bannerMargin').value}px` : '20px'), + borderRadius: (document.getElementById('bannerBorderRadius')?.value ? `${document.getElementById('bannerBorderRadius').value}px` : '8px'), + + // Container styles + containerStyle: (template.containerStyle || '').trim() + }; + // Special handling for specific templates + if (currentTemplate === 'modern') { + // Apply modern template specific styles + styles.background = template.background || styles.background; + styles.backgroundColor = template.backgroundColor || styles.backgroundColor; + styles.color = template.textColor || styles.color; + styles.textColor = template.textColor || styles.textColor; + + // Add text shadow for better readability + if (template.textStyle && template.textStyle.includes('text-shadow')) { + const match = template.textStyle.match(/text-shadow:\s*([^;]+)/); + if (match && match[1]) { + styles.textShadow = match[1]; + } + } + } else if (currentTemplate === 'dark') { + styles.background = '#2d3748'; + styles.backgroundColor = '#2d3748'; + styles.color = '#e2e8f0'; + styles.textColor = '#e2e8f0'; + } + + // Create text content with template styles + const textStyle = ` + font-size: ${styles.fontSize}; + color: ${styles.textColor}; + text-align: ${styles.textAlign}; + margin: 0; + padding: 20px 0; + line-height: 1.5; + flex: 1; + ${template.textStyle || ''} + ${styles.textShadow ? `text-shadow: ${styles.textShadow};` : ''} + `; + + // Create the text element + const textElement = ` + `; + + // Handle image if present + let imgContainer = ''; if (hasImage && currentImage) { - // Get image dimensions - const imageWidth = parseInt(document.getElementById('bannerImageWidth')?.value || '300'); - const imageHeight = parseInt(document.getElementById('bannerImageHeight')?.value || '200'); - - // Set max dimensions for the image - const maxWidth = '300px'; - const maxHeight = '200px'; - - // Create image container with proper positioning - let imgContainer = ` + imgContainer = ` `; - + // Wrap image with link if URL is provided if (bannerLink) { imgContainer = ` @@ -2682,145 +2786,61 @@ function updateBannerPreview() { ${imgContainer} `; } - - // Get all styles from template or use defaults - const styles = { - // Background styles - background: template.background || '', - backgroundColor: (bannerBgColorPicker?.value || template.backgroundColor || '#f8f9fa').trim(), - - // Text styles - color: (bannerTextColorPicker?.value || template.textColor || '#212529').trim(), - textColor: (bannerTextColorPicker?.value || template.textColor || '#212529').trim(), - textAlign: (template.textAlign || 'left').trim(), - fontSize: template.fontSize ? `${template.fontSize}px` : '16px', - - // Layout styles - padding: (template.padding ? `${template.padding}px` : '20px').trim(), - margin: (template.margin ? `${template.margin}px` : '20px').trim(), - borderRadius: (template.borderRadius ? `${template.borderRadius}px` : '8px').trim(), - - // Image position (always right) - imagePosition: 'right', - - // Container styles - containerStyle: (template.containerStyle || '').trim() - }; - - // Ensure background is properly set - if (!styles.background && styles.backgroundColor) { - styles.background = styles.backgroundColor; + } + + // Build the background style + let backgroundStyle = styles.background && styles.background.includes('gradient') + ? `background: ${styles.background}` + : `background-color: ${styles.backgroundColor || '#f8f9fa'}`; + + // Create the banner container with proper flex layout + bannerContent = ` + `; + + // Show the image preview in the container + try { + const bannerImagePreview = document.getElementById('bannerImagePreview'); + if (bannerImagePreview && currentImage) { + bannerImagePreview.src = currentImage; + bannerImagePreview.style.width = '100%'; + bannerImagePreview.style.height = 'auto'; + bannerImagePreview.style.maxHeight = '200px'; + bannerImagePreview.style.display = 'block'; + bannerImagePreview.style.objectFit = 'contain'; + bannerImagePreview.onerror = function() { + console.error('Failed to load banner image:', this.src); + this.style.display = 'none'; + }; } - - // Create text content with template styles - only create the text element once - const textStyle = ` - font-size: ${document.getElementById('bannerFontSize')?.value || '16'}px; - color: ${document.getElementById('bannerTextColor')?.value || '#000'}; - text-align: ${document.getElementById('bannerTextAlign')?.value || 'left'}; - margin: 0; - padding: 20px 0; - line-height: 1.5; - flex: 1; - ${template?.textStyle || ''} - `; - // Create the text element content - const textContent = ` - `; - - // Set the text element variable that will be used in the banner content - const textElement = textContent; - - // Special handling for specific templates - if (currentTemplate === 'dark') { - styles.background = '#2d3748'; - styles.backgroundColor = '#2d3748'; - styles.color = '#e2e8f0'; - styles.textColor = '#e2e8f0'; - } - - // Build the background style - let backgroundStyle = styles.background && styles.background.includes('gradient') - ? `background: ${styles.background}` - : `background-color: ${styles.backgroundColor || '#f8f9fa'}`; - - // Create the banner container with proper flex layout - bannerContent = ` - `; - - // Show the image preview in the container - try { - const bannerImagePreview = document.getElementById('bannerImagePreview'); - if (bannerImagePreview && currentImage) { - bannerImagePreview.src = currentImage; - bannerImagePreview.style.width = '100%'; - bannerImagePreview.style.height = 'auto'; - bannerImagePreview.style.maxHeight = '200px'; - bannerImagePreview.style.display = 'block'; - bannerImagePreview.style.objectFit = 'contain'; - bannerImagePreview.onerror = function() { - console.error('Failed to load banner image:', this.src); - this.style.display = 'none'; - }; - } - - if (imagePreviewContainer) { - imagePreviewContainer.style.display = 'block'; - } - } catch (error) { - console.error('Error updating banner preview:', error); + if (imagePreviewContainer) { + imagePreviewContainer.style.display = 'block'; } // Add the with-image class to the banner preview for proper spacing - bannerPreview.classList.add('with-image'); - } else { - // No image, just show text - bannerContent = ` - `; - - // Hide image preview container if no image - if (imagePreviewContainer) { - imagePreviewContainer.style.display = 'none'; - } if (bannerPreview) { - bannerPreview.classList.remove('with-image'); + bannerPreview.classList.add('with-image'); } + } catch (error) { + console.error('Error updating banner preview:', error); } // Apply template styles to the banner preview @@ -3088,7 +3108,10 @@ const templateConfigs = { containerStyle: 'background: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);', textStyle: 'color: #1a365d; font-weight: 600; text-shadow: 0 1px 2px rgba(0,0,0,0.1);', buttonStyle: 'background: #2b6cb0; color: white; border: 2px solid #2c5282; padding: 8px 20px; border-radius: 25px;', - isVisible: true + isVisible: true, + background: 'linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%)', + backgroundColor: '#84fab0', + textColor: '#1a365d' }, 'elegant': { name: 'Elegantní',