/* WooDoo Frontend JS – Calendar Booking */ ( function () { 'use strict'; const cfg = window.WooDooCalendar; if ( ! cfg ) return; // not on calendar page const i18n = cfg.i18n; const ajaxUrl = cfg.ajax_url; const nonce = cfg.nonce; // ── Element refs ──────────────────────────────────────────────────── const dateInput = document.getElementById( 'woodoo-booking-date' ); const slotsWrap = document.getElementById( 'woodoo-slots-wrap' ); const slotsGrid = document.getElementById( 'woodoo-slots-grid' ); const confirmBlock = document.getElementById( 'woodoo-booking-confirm' ); const bookBtn = document.getElementById( 'woodoo-book-btn' ); const notesArea = document.getElementById( 'woodoo-booking-notes' ); const slotLabel = document.getElementById( 'woodoo-selected-slot-label' ); const successMsg = document.getElementById( 'woodoo-booking-success' ); const errorMsg = document.getElementById( 'woodoo-booking-error' ); let selectedStart = null; let selectedEnd = null; // ── Date change → load slots ──────────────────────────────────────── if ( dateInput ) { dateInput.addEventListener( 'change', function () { const date = this.value; if ( ! date ) return; slotsGrid.innerHTML = '' + esc( i18n.loading ) + ''; slotsWrap.style.display = 'block'; confirmBlock.style.display = 'none'; successMsg.style.display = 'none'; errorMsg.style.display = 'none'; selectedStart = selectedEnd = null; bookBtn.disabled = true; post( 'woodoo_get_slots', { date } ) .then( res => { if ( ! res.success ) { slotsGrid.innerHTML = '' + esc( i18n.error ) + ''; return; } const slots = res.data; if ( ! slots.length ) { slotsGrid.innerHTML = '' + esc( i18n.no_slots ) + ''; confirmBlock.style.display = 'none'; return; } slotsGrid.innerHTML = ''; slots.forEach( slot => { const btn = document.createElement( 'button' ); btn.type = 'button'; btn.className = 'woodoo-slot'; btn.textContent = formatTime( slot.start ) + ' – ' + formatTime( slot.end ); btn.dataset.start = slot.start; btn.dataset.end = slot.end; btn.addEventListener( 'click', onSlotClick ); slotsGrid.appendChild( btn ); } ); } ) .catch( () => { slotsGrid.innerHTML = '' + esc( i18n.error ) + ''; } ); } ); } // ── Slot selection ─────────────────────────────────────────────────── function onSlotClick( e ) { document.querySelectorAll( '.woodoo-slot' ) .forEach( b => b.classList.remove( 'selected' ) ); const btn = e.currentTarget; btn.classList.add( 'selected' ); selectedStart = btn.dataset.start; selectedEnd = btn.dataset.end; slotLabel.textContent = new Date( selectedStart ).toLocaleDateString( undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', } ) + ' ' + formatTime( selectedStart ) + ' – ' + formatTime( selectedEnd ); confirmBlock.style.display = 'block'; bookBtn.disabled = false; successMsg.style.display = 'none'; errorMsg.style.display = 'none'; } // ── Confirm booking ────────────────────────────────────────────────── if ( bookBtn ) { bookBtn.addEventListener( 'click', function () { if ( ! selectedStart || ! selectedEnd ) return; bookBtn.disabled = true; bookBtn.textContent = i18n.booking; errorMsg.style.display = 'none'; post( 'woodoo_book_slot', { start : selectedStart, end : selectedEnd, notes : notesArea ? notesArea.value : '', } ) .then( res => { if ( res.success ) { successMsg.textContent = res.data.message; successMsg.style.display = 'block'; confirmBlock.style.display = 'none'; slotsWrap.style.display = 'none'; dateInput.value = ''; selectedStart = selectedEnd = null; // Re-fetch meetings after booking refreshMeetings(); } else { showError( res.data || i18n.error ); bookBtn.disabled = false; bookBtn.textContent = i18n.book_btn; } } ) .catch( () => { showError( i18n.error ); bookBtn.disabled = false; bookBtn.textContent = i18n.book_btn; } ); } ); } // ── Cancel meeting ─────────────────────────────────────────────────── document.querySelectorAll( '.woodoo-cancel-meeting' ).forEach( btn => { btn.addEventListener( 'click', function () { if ( ! confirm( i18n.cancel_confirm ) ) return; const eventId = this.dataset.eventId; const card = this.closest( '.woodoo-meeting-card' ); this.disabled = true; this.textContent = i18n.cancelling; post( 'woodoo_cancel_meeting', { event_id: eventId } ) .then( res => { if ( res.success ) { card.style.opacity = '0.4'; card.style.transition = 'opacity .3s'; setTimeout( () => card.remove(), 350 ); } else { alert( res.data || i18n.error ); this.disabled = false; this.textContent = 'Cancel'; } } ) .catch( () => { this.disabled = false; this.textContent = 'Cancel'; } ); } ); } ); // ── Refresh meetings list ──────────────────────────────────────────── function refreshMeetings() { const listEl = document.getElementById( 'woodoo-meetings-list' ); if ( ! listEl ) return; post( 'woodoo_get_meetings', {} ) .then( res => { if ( ! res.success ) return; const meetings = res.data; if ( ! meetings.length ) { listEl.innerHTML = '

' + esc( 'No upcoming meetings scheduled.' ) + '

'; return; } let html = '
'; meetings.forEach( ev => { const start = new Date( ev.start.replace( ' ', 'T' ) ); const end = new Date( ev.stop.replace( ' ', 'T' ) ); html += '
' + '
' + '' + pad( start.getDate() ) + '' + '' + monthShort( start ) + '' + '
' + '
' + '' + esc( ev.name ) + '' + '' + timeStr( start ) + ' – ' + timeStr( end ) + '' + ( ev.videocall_location ? 'Join Video Call' : '' ) + '
' + '
' + '' + '
' + '
'; } ); html += '
'; listEl.innerHTML = html; // Re-bind cancel buttons listEl.querySelectorAll( '.woodoo-cancel-meeting' ).forEach( btn => { btn.addEventListener( 'click', function () { // same handler as above – re-use via custom event trick btn.dispatchEvent( new Event( 'woodoo:cancel' ) ); } ); } ); } ); } // ── Helpers ────────────────────────────────────────────────────────── function post( action, data ) { const body = new URLSearchParams( Object.assign( { action, nonce }, data ) ); return fetch( ajaxUrl, { method: 'POST', body } ) .then( r => r.json() ); } function formatTime( datetimeStr ) { return datetimeStr.slice( 11, 16 ); } function timeStr( d ) { return pad( d.getHours() ) + ':' + pad( d.getMinutes() ); } function pad( n ) { return String( n ).padStart( 2, '0' ); } function monthShort( d ) { return d.toLocaleDateString( undefined, { month: 'short' } ); } function esc( str ) { return String( str ) .replace( /&/g, '&' ) .replace( //g, '>' ) .replace( /"/g, '"' ); } function showError( msg ) { errorMsg.textContent = msg; errorMsg.style.display = 'block'; } } )();