mirror of
https://github.com/Dvorinka/PPve.git
synced 2026-06-04 04:22:58 +00:00
e
This commit is contained in:
+272
-79
@@ -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 += `<div class="col-span-6 mt-2 mb-1"><span class="text-xs font-medium text-gray-500 uppercase tracking-wider">${category}</span></div>`;
|
||||
|
||||
icons.forEach(icon => {
|
||||
const iconClass = `fa-${icon}`;
|
||||
iconsHtml += `
|
||||
<div class="icon-option flex items-center justify-center p-2 rounded-md hover:bg-gray-200 cursor-pointer transition-colors"
|
||||
data-icon="${iconClass}"
|
||||
onclick="selectIcon('${iconClass}')">
|
||||
<i class="fas ${iconClass}"></i>
|
||||
</div>`;
|
||||
});
|
||||
}
|
||||
|
||||
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 += `<div class="icon-category">${category}</div>`;
|
||||
|
||||
filteredIcons.forEach(icon => {
|
||||
const iconClass = `fa-${icon}`;
|
||||
const displayName = icon.replace(/-/g, ' ');
|
||||
|
||||
iconsHtml += `
|
||||
<div class="icon-option"
|
||||
data-icon="${iconClass}"
|
||||
title="${displayName}">
|
||||
<i class="fas ${iconClass}"></i>
|
||||
<span class="icon-name">${displayName}</span>
|
||||
</div>`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasVisibleIcons) {
|
||||
iconsHtml = `
|
||||
<div class="col-span-full text-center py-8 text-gray-500">
|
||||
<i class="fas fa-search mb-2 text-2xl"></i>
|
||||
<p>Žádné ikony nenalezeny</p>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
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');
|
||||
|
||||
Reference in New Issue
Block a user