/** * Roz Skin - Modal Components * Reusable modal system for the application */ const RozModals = { // Create modal container if it doesn't exist init() { if (!document.getElementById('modal-container')) { const container = document.createElement('div'); container.id = 'modal-container'; document.body.appendChild(container); } }, // Show confirmation modal confirm(options = {}) { const { title = 'Confirm', message = 'Are you sure?', confirmText = 'Confirm', cancelText = 'Cancel', onConfirm = () => {}, onCancel = () => {} } = options; this.init(); const modal = document.createElement('div'); modal.className = 'modal-overlay fade-in'; modal.innerHTML = ` `; document.getElementById('modal-container').appendChild(modal); // Handle actions modal.querySelector('[data-action="confirm"]').onclick = () => { onConfirm(); this.close(modal); }; modal.querySelector('[data-action="cancel"]').onclick = () => { onCancel(); this.close(modal); }; modal.onclick = (e) => { if (e.target === modal) { onCancel(); this.close(modal); } }; }, // Show alert modal alert(options = {}) { const { title = 'Alert', message = '', buttonText = 'OK', onClose = () => {} } = options; this.init(); const modal = document.createElement('div'); modal.className = 'modal-overlay fade-in'; modal.innerHTML = ` `; document.getElementById('modal-container').appendChild(modal); modal.querySelector('[data-action="close"]').onclick = () => { onClose(); this.close(modal); }; modal.onclick = (e) => { if (e.target === modal) { onClose(); this.close(modal); } }; }, // Show custom modal show(content, options = {}) { const { className = '', closeOnOverlay = true, onClose = () => {} } = options; this.init(); const modal = document.createElement('div'); modal.className = `modal-overlay fade-in ${className}`; modal.innerHTML = ` `; document.getElementById('modal-container').appendChild(modal); if (closeOnOverlay) { modal.onclick = (e) => { if (e.target === modal) { onClose(); this.close(modal); } }; } return modal; }, // Show bottom sheet bottomSheet(content, options = {}) { const { className = '', onClose = () => {} } = options; this.init(); const modal = document.createElement('div'); modal.className = `modal-overlay fade-in ${className}`; modal.innerHTML = `
${content}
`; document.getElementById('modal-container').appendChild(modal); modal.onclick = (e) => { if (e.target === modal) { onClose(); this.close(modal); } }; return modal; }, // Show filter modal showFilters(options = {}) { const { categories = [], priceRange = { min: 0, max: 1000 }, onApply = () => {} } = options; const content = `

Filters

Categories

${categories.map(cat => ` `).join('')}

Price Range

${priceRange.min} EGP ${priceRange.max} EGP
`; return this.bottomSheet(content); }, // Apply filters applyFilters() { // Get selected filters const selected = Array.from(document.querySelectorAll('.filter-chip input:checked')) .map(input => input.value); console.log('Selected filters:', selected); RozSkin.showToast('Filters applied', 'success'); this.closeAll(); }, // Close specific modal close(modal) { modal.classList.add('fade-out'); setTimeout(() => { modal.remove(); }, 300); }, // Close all modals closeAll() { const container = document.getElementById('modal-container'); if (container) { container.innerHTML = ''; } } }; // Add modal styles const modalStyles = document.createElement('style'); modalStyles.textContent = ` #modal-container { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 9999; pointer-events: none; } .modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; padding: var(--space-md); pointer-events: all; z-index: 9999; } .modal-content { background: var(--color-white); border-radius: var(--radius-2xl); max-width: 400px; width: 100%; max-height: 80vh; overflow-y: auto; } .modal-header { padding: var(--space-lg) var(--space-lg) var(--space-md); border-bottom: 1px solid var(--color-background); } .modal-title { font-size: var(--font-size-xl); font-weight: var(--font-weight-semibold); margin: 0; } .modal-body { padding: var(--space-lg); } .modal-footer { padding: var(--space-md) var(--space-lg) var(--space-lg); display: flex; gap: var(--space-md); } .modal-footer button { flex: 1; height: 48px; border: none; border-radius: var(--radius-lg); font-weight: var(--font-weight-semibold); cursor: pointer; } .bottom-sheet { position: fixed; bottom: 0; left: 0; right: 0; background: var(--color-white); border-radius: var(--radius-2xl) var(--radius-2xl) 0 0; max-height: 80vh; overflow-y: auto; padding: var(--space-lg); } .bottom-sheet-handle { width: 40px; height: 4px; background: var(--color-background); border-radius: var(--radius-full); margin: 0 auto var(--space-lg); } .filter-modal { padding: var(--space-md); } .filter-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-lg); } .filter-header h3 { font-size: var(--font-size-xl); font-weight: var(--font-weight-semibold); margin: 0; } .filter-section { margin-bottom: var(--space-xl); } .filter-section h4 { font-size: var(--font-size-base); font-weight: var(--font-weight-semibold); margin-bottom: var(--space-md); } .filter-chips { display: flex; flex-wrap: wrap; gap: var(--space-sm); } .filter-chip { display: inline-block; cursor: pointer; } .filter-chip input { display: none; } .filter-chip span { display: inline-block; padding: var(--space-sm) var(--space-md); background: var(--color-background); border-radius: var(--radius-full); font-size: var(--font-size-sm); transition: all var(--transition-base); } .filter-chip input:checked + span { background: var(--color-text-primary); color: var(--color-white); } .price-range { padding: var(--space-md) 0; } .range-slider { width: 100%; height: 4px; border-radius: var(--radius-full); background: var(--color-background); outline: none; -webkit-appearance: none; } .range-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; border-radius: 50%; background: var(--color-text-primary); cursor: pointer; } .price-labels { display: flex; justify-content: space-between; margin-top: var(--space-sm); font-size: var(--font-size-sm); color: var(--color-text-secondary); } .filter-footer { display: flex; gap: var(--space-md); padding-top: var(--space-lg); border-top: 1px solid var(--color-background); } .filter-footer button { flex: 1; height: 48px; border: none; border-radius: var(--radius-lg); font-weight: var(--font-weight-semibold); cursor: pointer; } .btn-primary { background: var(--color-text-primary); color: var(--color-white); } .btn-secondary { background: var(--color-background); color: var(--color-text-primary); } .btn-text { background: none; border: none; color: var(--color-text-primary); cursor: pointer; font-size: var(--font-size-base); } .fade-out { animation: fadeOut 0.3s ease-out forwards; } @keyframes fadeOut { to { opacity: 0; } } .slide-up { animation: slideUp 0.3s ease-out; } @keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } } `; document.head.appendChild(modalStyles); // Export for use in other scripts window.RozModals = RozModals;