From fc782105b91a77480ad5e7592d3227f27611517b Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Fri, 30 May 2025 11:49:29 +0200 Subject: [PATCH] e --- admin-dashboard.html | 351 +++++++++++++++++++++++++++++++++---------- 1 file changed, 272 insertions(+), 79 deletions(-) diff --git a/admin-dashboard.html b/admin-dashboard.html index 67d7c02..e994adc 100644 --- a/admin-dashboard.html +++ b/admin-dashboard.html @@ -194,64 +194,164 @@ border-color: var(--secondary-color); transform: translateY(-2px); } - /* Icon Picker Styles */ + /* Icon Picker Styles - Enhanced */ #iconDropdown { position: absolute; width: 100%; + max-width: 500px; background: white; border: 1px solid #e5e7eb; - border-radius: 0.375rem; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); - z-index: 50; - margin-top: 0.25rem; + border-radius: 0.5rem; + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); + z-index: 1000; + margin-top: 0.5rem; + overflow: hidden; } #iconSearch { width: 100%; - padding: 0.5rem; - border: 1px solid #e5e7eb; - border-radius: 0.25rem; - font-size: 0.875rem; - margin-bottom: 0.5rem; + padding: 0.75rem 1rem; + border: none; + border-bottom: 2px solid #e5e7eb; + border-radius: 0; + font-size: 0.9375rem; + margin: 0; + background-color: #f9fafb; + transition: all 0.2s ease; } #iconSearch:focus { outline: none; - border-color: #3b82f6; - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2); + border-color: var(--primary-color); + background-color: white; + box-shadow: 0 2px 0 0 var(--primary-color); } #iconList { display: grid; - grid-template-columns: repeat(6, minmax(0, 1fr)); - gap: 0.5rem; - padding: 0.5rem; - max-height: 300px; + grid-template-columns: repeat(8, minmax(0, 1fr)); + gap: 0.75rem; + padding: 1rem; + max-height: 400px; overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: #cbd5e0 #f1f5f9; + } + + #iconList::-webkit-scrollbar { + width: 8px; + height: 8px; + } + + #iconList::-webkit-scrollbar-track { + background: #f1f5f9; + border-radius: 4px; + } + + #iconList::-webkit-scrollbar-thumb { + background-color: #cbd5e0; + border-radius: 4px; + } + + .icon-category { + grid-column: 1 / -1; + margin: 0.5rem 0 0.25rem; + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: #6b7280; + background-color: #f9fafb; + border-radius: 0.25rem; + position: sticky; + top: 0; + z-index: 10; } .icon-option { display: flex; + flex-direction: column; align-items: center; justify-content: center; - padding: 0.5rem; + padding: 0.75rem 0.5rem; border: 1px solid #e5e7eb; - border-radius: 0.25rem; - font-size: 1.25rem; - color: #4b5563; + border-radius: 0.5rem; + background: white; cursor: pointer; - transition: all 0.2s; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + position: relative; + overflow: hidden; + } + + .icon-option i { + font-size: 1.5rem; + color: #4b5563; + margin-bottom: 0.25rem; + transition: all 0.2s ease; + pointer-events: none; + } + + .icon-option .icon-name { + font-size: 0.625rem; + color: #6b7280; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + opacity: 0; + transform: translateY(5px); + transition: all 0.2s ease; + pointer-events: none; } .icon-option:hover { background-color: #f3f4f6; border-color: #d1d5db; - color: #1f2937; + transform: translateY(-2px); + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + } + + .icon-option:hover i { + color: var(--primary-color); transform: scale(1.1); } - .icon-option i { - pointer-events: none; + .icon-option:hover .icon-name { + opacity: 1; + transform: translateY(0); + } + + .icon-option.active { + background-color: var(--primary-color); + border-color: var(--primary-hover); + } + + .icon-option.active i, + .icon-option.active .icon-name { + color: white; + } + + /* Responsive adjustments */ + @media (max-width: 768px) { + #iconList { + grid-template-columns: repeat(6, minmax(0, 1fr)); + gap: 0.5rem; + padding: 0.75rem; + } + + .icon-option i { + font-size: 1.25rem; + } + } + + @media (max-width: 480px) { + #iconList { + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 0.5rem; + padding: 0.5rem; + } } .banner-preview { @@ -1968,6 +2068,62 @@ function openAddAppModal() { // Update title document.getElementById('appModalTitle').textContent = 'Přidat aplikaci'; + // Select an icon + function selectIcon(iconClass) { + const iconInput = document.getElementById('appIcon'); + const selectedIcon = document.getElementById('selectedIcon'); + const iconPreview = document.getElementById('iconPreview'); + const customIconPreview = document.getElementById('customIconPreview'); + const iconClassInput = document.getElementById('appIconClass'); + + if (iconInput && selectedIcon && iconClassInput) { + // Hide any custom icon preview + if (customIconPreview) { + customIconPreview.classList.add('hidden'); + customIconPreview.src = ''; + } + + // Show the Font Awesome icon + if (selectedIcon) { + selectedIcon.className = `fas ${iconClass} text-2xl text-blue-600`; + selectedIcon.classList.remove('hidden'); + } + + // Update the hidden input with the icon class + iconClassInput.value = iconClass; + + // Update the visible input with a friendly name + const iconName = iconClass.replace('fa-', '').replace(/-/g, ' '); + iconInput.value = iconName.split(' ') + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + + // Scroll the selected icon into view in the dropdown + const selectedOption = document.querySelector(`.icon-option[data-icon="${iconClass}"]`); + if (selectedOption) { + selectedOption.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + + // Highlight the selected icon + document.querySelectorAll('.icon-option').forEach(option => { + option.classList.toggle('active', option.getAttribute('data-icon') === iconClass); + }); + } + + // Hide the dropdown after a short delay + setTimeout(() => { + const dropdown = document.getElementById('iconDropdown'); + if (dropdown) { + dropdown.classList.add('hidden'); + } + }, 200); + + // Update the preview + if (iconPreview) { + iconPreview.className = 'w-12 h-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center mr-3'; + } + } + } + // Reset icon selection const appIcon = document.getElementById('appIcon'); const customIconInput = document.getElementById('customIconInput'); @@ -2145,77 +2301,114 @@ document.getElementById('appModal').addEventListener('hidden.bs.modal', function if (dropdown) dropdown.classList.add('hidden'); }); -// Icon picker functionality +// Icon picker functionality with more categories and icons const iconCategories = { - 'Doprava': ['car', 'truck', 'bus', 'bicycle', 'motorcycle', 'plane', 'ship', 'subway', 'train', 'walking'], - 'Jídlo': ['utensils', 'hamburger', 'pizza-slice', 'ice-cream', 'coffee', 'wine-glass', 'beer', 'wine-bottle', 'wine-glass-alt', 'wine-bottle-alt'], - 'Nástroje': ['tools', 'wrench', 'screwdriver', 'hammer', 'toolbox', 'ruler', 'ruler-combined', 'ruler-horizontal', 'ruler-vertical', 'screwdriver-wrench'], - 'Kancelář': ['briefcase', 'folder', 'file', 'file-alt', 'file-archive', 'file-audio', 'file-code', 'file-excel', 'file-image', 'file-pdf'], - 'Lidé': ['user', 'users', 'user-tie', 'user-graduate', 'user-astronaut', 'user-ninja', 'user-secret', 'user-shield', 'user-tag', 'user-tie'], - 'Komunikace': ['envelope', 'envelope-open', 'envelope-square', 'inbox', 'comment', 'comments', 'comment-alt', 'comment-dots', 'comment-medical', 'comment-slash'], - 'Sociální sítě': ['thumbs-up', 'thumbs-down', 'share', 'share-alt', 'retweet', 'reply', 'comment', 'comments', 'heart', 'star'] + 'Doprava': ['car', 'car-side', 'truck', 'bus', 'bicycle', 'motorcycle', 'plane', 'plane-departure', 'ship', 'subway', 'train', 'train-subway', 'walking', 'gas-pump', 'map-marker-alt', 'route'], + 'Jídlo a nápoje': ['utensils', 'hamburger', 'pizza-slice', 'ice-cream', 'coffee', 'mug-hot', 'beer', 'wine-glass', 'wine-bottle', 'wine-glass-alt', 'wine-bottle-alt', 'apple-alt', 'bread-slice', 'cheese', 'drumstick-bite', 'egg', 'fish', 'hotdog', 'ice-cream', 'lemon', 'pepper-hot', 'shrimp', 'stroopwafel'], + 'Nástroje': ['tools', 'wrench', 'screwdriver', 'hammer', 'toolbox', 'ruler', 'ruler-combined', 'ruler-horizontal', 'ruler-vertical', 'screwdriver-wrench', 'screwdriver', 'hammer', 'paint-roller', 'paint-brush', 'pencil-ruler', 'ruler', 'screwdriver', 'toolbox', 'wrench'], + 'Kancelář': ['briefcase', 'folder', 'folder-open', 'file', 'file-alt', 'file-archive', 'file-audio', 'file-code', 'file-excel', 'file-image', 'file-pdf', 'file-word', 'file-powerpoint', 'file-signature', 'file-upload', 'file-download', 'file-export', 'file-import', 'file-invoice', 'file-invoice-dollar', 'file-medical', 'file-prescription'], + 'Lidé': ['user', 'user-alt', 'user-astronaut', 'user-check', 'user-circle', 'user-clock', 'user-cog', 'user-edit', 'user-friends', 'user-graduate', 'user-injured', 'user-lock', 'user-md', 'user-ninja', 'user-nurse', 'user-plus', 'user-secret', 'user-shield', 'user-tag', 'user-tie', 'users', 'users-cog', 'user-tie'], + 'Komunikace': ['envelope', 'envelope-open', 'envelope-open-text', 'envelope-square', 'inbox', 'comment', 'comments', 'comment-alt', 'comment-dots', 'comment-medical', 'comment-slash', 'comment-alt', 'comments', 'inbox', 'mail-bulk', 'phone', 'phone-alt', 'phone-slash', 'phone-square', 'phone-square-alt', 'phone-volume', 'sms', 'voicemail'], + 'Sociální sítě': ['thumbs-up', 'thumbs-down', 'share', 'share-alt', 'share-square', 'retweet', 'reply', 'comment', 'comments', 'heart', 'heart-broken', 'star', 'star-half-alt', 'thumbs-up', 'thumbs-down', 'user-plus', 'user-friends', 'user-check', 'user-tag', 'user-shield'], + 'Finance': ['money-bill', 'money-bill-wave', 'money-bill-alt', 'money-check', 'money-check-alt', 'credit-card', 'credit-card-alt', 'wallet', 'donate', 'dollar-sign', 'euro-sign', 'lira-sign', 'pound-sign', 'rupee-sign', 'shekel-sign', 'yen-sign', 'bitcoin', 'ethereum', 'btc', 'euro', 'gg', 'gg-circle', 'ils', 'krw', 'money-bill', 'money-bill-alt', 'money-bill-wave', 'money-bill-wave-alt', 'money-check', 'money-check-alt', 'receipt', 'ruble-sign', 'rupee-sign', 'shekel-sign', 'tenge', 'won-sign', 'yen-sign'], + 'Zdraví': ['heart', 'heartbeat', 'heart-broken', 'hospital', 'hospital-alt', 'hospital-symbol', 'ambulance', 'band-aid', 'briefcase-medical', 'capsules', 'clinic-medical', 'diagnoses', 'disease', 'dna', 'file-medical', 'file-medical-alt', 'file-prescription', 'first-aid', 'heart', 'heartbeat', 'hospital', 'hospital-alt', 'hospital-symbol', 'hospital-user', 'id-card', 'id-card-alt', 'notes-medical', 'pills', 'plus', 'plus-circle', 'plus-square', 'prescription', 'prescription-bottle', 'prescription-bottle-alt', 'procedures', 'sign-in-alt', 'sign-out-alt', 'stethoscope', 'syringe', 'tablets', 'teeth', 'teeth-open', 'thermometer', 'user-md', 'user-nurse', 'vial', 'vials', 'weight', 'weight-hanging', 'wheelchair'], + 'Vzdělání': ['graduation-cap', 'university', 'school', 'chalkboard', 'chalkboard-teacher', 'book', 'book-open', 'book-reader', 'bookmark', 'brain', 'calculator', 'chalkboard', 'chalkboard-teacher', 'graduation-cap', 'school', 'university', 'user-graduate', 'user-tie'] }; -// Initialize icon picker +// Initialize icon picker with enhanced functionality function initIconPicker() { const iconList = document.getElementById('iconList'); if (!iconList) return; - let iconsHtml = ''; - - // Add icons from all categories - for (const [category, icons] of Object.entries(iconCategories)) { - iconsHtml += `
${category}
`; - - icons.forEach(icon => { - const iconClass = `fa-${icon}`; - iconsHtml += ` -
- -
`; - }); - } - - iconList.innerHTML = iconsHtml; + renderIcons(''); // Add event listener for icon search const iconSearch = document.getElementById('iconSearch'); if (iconSearch) { - iconSearch.addEventListener('input', filterIcons); - } -} - -// Filter icons based on search input -function filterIcons() { - const searchTerm = document.getElementById('iconSearch')?.value.toLowerCase() || ''; - const iconOptions = document.querySelectorAll('.icon-option'); - - iconOptions.forEach(option => { - const iconName = option.getAttribute('data-icon')?.toLowerCase() || ''; - const categoryHeader = option.previousElementSibling; + iconSearch.addEventListener('input', function() { + renderIcons(this.value.toLowerCase()); + }); - if (searchTerm === '' || iconName.includes(searchTerm)) { - option.style.display = 'flex'; - // Show the category header if at least one icon in the category is visible - if (categoryHeader && categoryHeader.classList.contains('col-span-6')) { - categoryHeader.style.display = 'block'; - } - } else { - option.style.display = 'none'; - // Hide the category header if no icons in the category are visible - if (categoryHeader && categoryHeader.classList.contains('col-span-6')) { - const categoryIcons = Array.from(option.parentElement.children) - .filter(el => el !== categoryHeader && el.style.display !== 'none'); - if (categoryIcons.length === 0) { - categoryHeader.style.display = 'none'; - } - } + // Focus the search input when dropdown is shown + const iconInput = document.getElementById('appIcon'); + if (iconInput) { + iconInput.addEventListener('focus', function() { + setTimeout(() => { + iconSearch.focus(); + }, 100); + }); + } + } + + // Close dropdown when clicking outside + document.addEventListener('click', function(event) { + const dropdown = document.getElementById('iconDropdown'); + const iconInput = document.getElementById('appIcon'); + const isClickInside = dropdown?.contains(event.target) || + event.target === iconInput || + event.target === document.getElementById('iconSearch'); + + if (!isClickInside && dropdown && !dropdown.classList.contains('hidden')) { + dropdown.classList.add('hidden'); } }); } +// Render icons based on search term +function renderIcons(searchTerm) { + const iconList = document.getElementById('iconList'); + if (!iconList) return; + + let iconsHtml = ''; + let hasVisibleIcons = false; + + // Add icons from all categories + for (const [category, icons] of Object.entries(iconCategories)) { + const filteredIcons = icons.filter(icon => + icon.toLowerCase().includes(searchTerm) || + category.toLowerCase().includes(searchTerm) + ); + + if (filteredIcons.length > 0) { + hasVisibleIcons = true; + iconsHtml += `
${category}
`; + + filteredIcons.forEach(icon => { + const iconClass = `fa-${icon}`; + const displayName = icon.replace(/-/g, ' '); + + iconsHtml += ` +
+ + ${displayName} +
`; + }); + } + } + + if (!hasVisibleIcons) { + iconsHtml = ` +
+ +

Žádné ikony nenalezeny

+
`; + } + + iconList.innerHTML = iconsHtml; + + // Add click handlers to icon options + document.querySelectorAll('.icon-option').forEach(option => { + option.addEventListener('click', function() { + const iconClass = this.getAttribute('data-icon'); + selectIcon(iconClass); + }); + }); +} + +// Filter icons based on search input (now handled in renderIcons) + // Select an icon function selectIcon(iconClass) { const selectedIcon = document.getElementById('selectedIcon');