/**
|
* Hours Copy Extension for form.min.js
|
* Adds copy functionality to hours forms with modal interface
|
*
|
* Dependencies: form.min.js, modal.min.js, utility functions (targetCheck, getIcon)
|
*/
|
class HoursCopyExtension {
|
constructor() {
|
this.createModal();
|
this.setupModal();
|
this.currentSourceDay = null;
|
this.days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
|
|
this.init();
|
}
|
|
handleChange(e) {
|
if (window.targetCheck('.hours-copy-btn')) {
|
e.preventDefault({bubbles: true});
|
}
|
}
|
init() {
|
this.addCopyButtons();
|
this.bindEvents();
|
}
|
|
createModal() {
|
this.modalElement = document.querySelector('dialog#copy-hours');
|
// Create modal element if it doesn't exist
|
if (!this.modalElement) {
|
const modal = window.getTemplate('copyHours');
|
document.body.appendChild(modal);
|
this.modalElement = document.querySelector('dialog#copy-hours');
|
}
|
console.log(this.modalElement);
|
}
|
|
setupModal() {
|
this.modal = new window.jvbModal(
|
this.modalElement,
|
{
|
open: '.hours-copy-btn',
|
openMessage: "Copy hours modal opened",
|
closeMessage: "Copy hours modal closed",
|
}
|
);
|
this.modal.subscribe((event, data) => {
|
switch(event) {
|
case 'modal-open':
|
let e = data.event;
|
let modal = data.modal;
|
const dayGroup = e.target.closest('.group-fields:not(.hours)');
|
console.log(dayGroup);
|
const dayName = this.getDayNameFromGroup(dayGroup);
|
console.log(dayName);
|
if (!dayName) return;
|
|
this.currentSourceDay = dayName;
|
console.log(dayName);
|
|
// Get source day hours
|
const sourceData = this.getSourceDayData(dayGroup);
|
|
console.log(sourceData);
|
|
// Update source day info
|
const sourceDayEl = modal.querySelector('.source-day');
|
const sourceHoursEl = modal.querySelector('.source-hours');
|
|
console.log('Elements: ', {sourceDayEl, sourceHoursEl});
|
|
if (sourceDayEl) {
|
sourceDayEl.textContent = window.uppercaseFirst ?
|
window.uppercaseFirst(dayName) :
|
dayName.charAt(0).toUpperCase() + dayName.slice(1);
|
}
|
|
if (sourceHoursEl) {
|
if (sourceData.isOpen && sourceData.opens && sourceData.closes) {
|
sourceHoursEl.textContent = `${sourceData.opens} - ${sourceData.closes}`;
|
sourceHoursEl.className = 'source-hours';
|
} else {
|
sourceHoursEl.textContent = 'Closed';
|
sourceHoursEl.className = 'source-hours closed';
|
}
|
}
|
|
this.modal.modal.querySelector(`label[for=copy-to-${dayName}]`).hidden = true;
|
this.modal.modal.querySelectorAll(`label:not([for=copy-to-${dayName}])[hidden]`).hidden = false;
|
break;
|
case 'modal-close':
|
this.applyCopyHours()
|
this.currentSourceDay = null;
|
break;
|
}
|
});
|
}
|
|
addCopyButtons() {
|
// Add copy buttons to each day group
|
const dayGroups = document.querySelectorAll('.group-fields.hours .group-fields:not(.hours)');
|
|
dayGroups.forEach(group => {
|
if (!group.querySelector('.hours-copy-btn')) {
|
const copyBtn = this.createCopyButton();
|
group.insertBefore(copyBtn, group.querySelector('.field.time'));
|
}
|
});
|
}
|
|
createCopyButton() {
|
const button = window.getTemplate('blankButton');
|
button.type = 'button';
|
button.className = 'hours-copy-btn';
|
button.title = 'Copy this time to other days';
|
button.prepend(window.getIcon('copy'));
|
|
button.setAttribute('data-action', 'copy-hours');
|
return button;
|
}
|
|
bindEvents() {
|
this.changeHandler = this.handleChange.bind(this);
|
this.modal.modal.addEventListener('change', this.changeHandler);
|
}
|
|
getDayNameFromGroup(group) {
|
const classList = Array.from(group.classList);
|
return this.days.find(day => classList.includes(day));
|
}
|
|
getSourceDayData(dayGroup) {
|
console.log(dayGroup);
|
const openCheckbox = dayGroup.querySelector('input[type="checkbox"][name$=":open"]');
|
const opensInput = dayGroup.querySelector('input[name$=":time_opens"]');
|
const closesInput = dayGroup.querySelector('input[name$=":time_closes"]');
|
|
return {
|
isOpen: openCheckbox ? openCheckbox.checked : false,
|
opens: opensInput ? opensInput.value : '',
|
closes: closesInput ? closesInput.value : ''
|
};
|
}
|
|
applyCopyHours() {
|
if (!this.currentSourceDay) return;
|
|
const sourceGroup = document.querySelector(`.group-fields.${this.currentSourceDay}`);
|
if (!sourceGroup) return;
|
|
const sourceData = this.getSourceDayData(sourceGroup);
|
|
// Get selected target days
|
const selectedDays = Array.from(
|
this.modal.modal.querySelectorAll('input:checked')
|
).map(checkbox => checkbox.value);
|
|
if (selectedDays.length === 0) {
|
alert('Please select at least one day to copy to.');
|
|
return;
|
}
|
|
// Apply hours to selected days
|
selectedDays.forEach(day => {
|
this.applyHoursToDay(day, sourceData);
|
});
|
|
// Show success feedback
|
this.showSuccessFeedback(selectedDays.length);
|
}
|
|
applyHoursToDay(dayName, sourceData) {
|
const targetGroup = document.querySelector(`.group-fields.${dayName}`);
|
if (!targetGroup) return;
|
|
const openCheckbox = targetGroup.querySelector('input[type="checkbox"][name$=":open"]');
|
const opensInput = targetGroup.querySelector('input[name$=":time_opens"]');
|
const closesInput = targetGroup.querySelector('input[name$=":time_closes"]');
|
console.log('applying hours to days: ', {
|
openCheckbox,
|
opensInput,
|
closesInput
|
});
|
if (!openCheckbox) return;
|
|
// Set checkbox state
|
openCheckbox.checked = sourceData.isOpen;
|
openCheckbox.dispatchEvent(new Event('change', {bubbles: true}));
|
|
|
// Set time values if open
|
if (sourceData.isOpen && opensInput && closesInput) {
|
opensInput.value = sourceData.opens;
|
closesInput.value = sourceData.closes;
|
} else if (opensInput && closesInput) {
|
opensInput.value = '';
|
closesInput.value = '';
|
}
|
|
}
|
|
showSuccessFeedback(count) {
|
// Create or update feedback element
|
let feedback = document.getElementById('copy-success-feedback');
|
if (!feedback) {
|
feedback = document.createElement('div');
|
feedback.id = 'copy-success-feedback';
|
feedback.className = 'copy-success-feedback';
|
document.body.appendChild(feedback);
|
}
|
|
const message = count === 1 ?
|
'Hours copied to 1 day successfully!' :
|
`Hours copied to ${count} days successfully!`;
|
|
feedback.querySelector('span').textContent = message;
|
|
// Show feedback
|
feedback.classList.add('show');
|
|
// Hide after delay
|
window.debouncer.schedule('copy-success',
|
() => { feedback.classList.remove('show'); },
|
3000);
|
|
// Use accessibility announcements if available
|
if (window.jvbA11y && window.jvbA11y.announce) {
|
window.jvbA11y.announce(message);
|
}
|
}
|
}
|
|
document.addEventListener('DOMContentLoaded', () => {
|
window.jvbCopy = new HoursCopyExtension();
|
});
|