/**
* 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 = `
${content}
`;
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 = `
`;
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 = `
`;
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;