/* WooDoo Frontend JS */ ( function () { 'use strict'; // ══════════════════════════════════════════════════════════════════════ // INVOICE EMAIL // ══════════════════════════════════════════════════════════════════════ const inv = window.WooDooInvoices; if ( inv ) { document.querySelectorAll( '.woodoo-send-invoice' ).forEach( function ( btn ) { btn.addEventListener( 'click', function () { const invoiceId = this.dataset.id; const $btn = this; const row = $btn.closest( 'tr' ); // Remove any previous feedback in this row const prev = row.querySelector( '.woodoo-inline-msg' ); if ( prev ) prev.remove(); $btn.disabled = true; $btn.textContent = 'Enviando…'; const body = new URLSearchParams( { action : 'woodoo_send_invoice_email', nonce : inv.nonce, invoice_id : invoiceId, } ); fetch( inv.ajax_url, { method: 'POST', body } ) .then( r => r.json() ) .then( function ( res ) { if ( res.success ) { $btn.textContent = '✓ Enviado'; $btn.style.color = '#065f46'; // Show success message below the row const td = document.createElement( 'td' ); td.colSpan = 6; td.className = 'woodoo-inline-msg woodoo-inline-msg--ok'; td.textContent = res.data.message; const msgRow = document.createElement( 'tr' ); msgRow.className = 'woodoo-inline-msg'; msgRow.appendChild( td ); row.insertAdjacentElement( 'afterend', msgRow ); // Auto-hide after 6s setTimeout( function () { msgRow.remove(); $btn.disabled = false; $btn.textContent = '✉ Reenviar'; $btn.style.color = ''; }, 6000 ); } else { showInvoiceError( row, res.data || 'Error desconocido.' ); $btn.disabled = false; $btn.textContent = '✉ Reenviar'; } } ) .catch( function () { showInvoiceError( row, 'Error de conexión. Inténtalo de nuevo.' ); $btn.disabled = false; $btn.textContent = '✉ Reenviar'; } ); } ); } ); function showInvoiceError( row, msg ) { const prev = row.querySelector( '.woodoo-inline-msg' ); if ( prev ) prev.remove(); const td = document.createElement( 'td' ); td.colSpan = 6; td.className = 'woodoo-inline-msg woodoo-inline-msg--err'; td.textContent = msg; const msgRow = document.createElement( 'tr' ); msgRow.className = 'woodoo-inline-msg'; msgRow.appendChild( td ); row.insertAdjacentElement( 'afterend', msgRow ); } } // ══════════════════════════════════════════════════════════════════════ // CALENDAR BOOKING // ══════════════════════════════════════════════════════════════════════ const cfg = window.WooDooCalendar; if ( ! cfg ) return; const i18n = cfg.i18n; const ajaxUrl = cfg.ajax_url; const nonce = cfg.nonce; 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 ) + ''; } ); } ); } 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( 'es-ES', { 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; refreshMeetings(); } else { showCalError( res.data || i18n.error ); bookBtn.disabled = false; bookBtn.textContent = i18n.book_btn; } } ) .catch( () => { showCalError( 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 = 'Cancelar'; } } ) .catch( () => { this.disabled = false; this.textContent = 'Cancelar'; } ); } ); } ); // ── Refresh meetings list ──────────────────────────────────────────── function refreshMeetings() { const listEl = document.getElementById( 'woodoo-meetings-list' ); if ( ! listEl ) return; post( 'woodoo_get_meetings', {} ) .then( res => { if ( ! res.success || ! res.data.length ) { listEl.innerHTML = '

No tienes reuniones programadas.

'; return; } const meses = [ '', 'ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic' ]; let html = '
'; res.data.forEach( ev => { const start = new Date( ev.start.replace( ' ', 'T' ) ); const end = new Date( ev.stop.replace( ' ', 'T' ) ); html += '
' + '
' + '' + pad( start.getDate() ) + '' + '' + ( meses[ start.getMonth() + 1 ] || '' ) + '' + '
' + '
' + '' + esc( ev.name ) + '' + '' + timeStr( start ) + ' – ' + timeStr( end ) + '' + ( ev.videocall_location ? 'Unirse a la videollamada' : '' ) + '
' + '
' + '' + '
' + '
'; } ); html += '
'; listEl.innerHTML = html; } ); } // ── 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( dt ) { return dt.slice( 11, 16 ); } function timeStr( d ) { return pad( d.getHours() ) + ':' + pad( d.getMinutes() ); } function pad( n ) { return String( n ).padStart( 2, '0' ); } function esc( str ) { return String( str ) .replace( /&/g, '&' ).replace( //g, '>' ).replace( /"/g, '"' ); } function showCalError( msg ) { errorMsg.textContent = msg; errorMsg.style.display = 'block'; } } )();