4040 }
4141 } ) ;
4242 } ) ;
43- } ) ( jQuery ) ;
43+ } ) ( jQuery ) ;
44+
45+ // =============================================================================
46+ // Premium Survey Modal — Integration Alegra WooCommerce
47+ // =============================================================================
48+ ( function ( $ ) {
49+
50+ // -------------------------------------------------------------------------
51+ // Constants
52+ // -------------------------------------------------------------------------
53+ const premiumSurveyButton = 'button.alegra-send-premium-survey' ;
54+ const actionSendPremiumSurvey = 'integration_alegra_send_premium_survey' ;
55+ const actionDismissPremiumSurveyNotice = 'integration_alegra_dismiss_premium_survey_notice' ;
56+
57+ // -------------------------------------------------------------------------
58+ // Question options
59+ // -------------------------------------------------------------------------
60+ const premiumSurveyOptions = {
61+ q2 : [
62+ { value : '' , label : '— Selecciona —' } ,
63+ { value : 'facturacion' , label : 'Problemas con la facturación automática' } ,
64+ { value : 'sincronizacion' , label : 'Sincronización lenta o incompleta de productos/pedidos' } ,
65+ { value : 'configuracion' , label : 'Configuración compleja o poco intuitiva' } ,
66+ { value : 'soporte' , label : 'Falta de soporte técnico oportuno' } ,
67+ { value : 'funcionalidades' , label : 'Faltan funcionalidades que necesito' } ,
68+ { value : 'otro' , label : 'Otro' } ,
69+ ] ,
70+ q3 : [
71+ { value : '' , label : '— Selecciona —' } ,
72+ { value : 'menos_1h' , label : 'Menos de 1 hora' } ,
73+ { value : '1_3h' , label : 'Entre 1 y 3 horas' } ,
74+ { value : '3_5h' , label : 'Entre 3 y 5 horas' } ,
75+ { value : 'mas_5h' , label : 'Más de 5 horas' } ,
76+ ] ,
77+ q4 : [
78+ { value : 'webhooks' , label : 'Webhooks: sincronización automática entre Alegra y WooCommerce' } ,
79+ { value : 'notas_credito' , label : 'Notas de crédito automáticas' } ,
80+ { value : 'cotizaciones' , label : 'Cotizaciones desde WooCommerce' } ,
81+ { value : 'reportes' , label : 'Reportes y alertas inteligentes' } ,
82+ { value : 'otras' , label : 'Otras funcionalidades (especificar abajo)' } ,
83+ ] ,
84+ q6 : [
85+ { value : '' , label : '— Selecciona —' } ,
86+ { value : 'mensual' , label : 'Pago mensual recurrente' } ,
87+ { value : 'anual' , label : 'Pago anual (descuento)' } ,
88+ { value : 'pago_unico' , label : 'Pago único (licencia permanente)' } ,
89+ ] ,
90+ q7 : [
91+ { value : '' , label : '— Selecciona —' } ,
92+ { value : '30000_49000' , label : '$30.000 – $49.000 COP/mes' } ,
93+ { value : '50000_99000' , label : '$50.000 – $99.000 COP/mes' } ,
94+ { value : '100000_199000' , label : '$100.000 – $199.000 COP/mes' } ,
95+ { value : '200000_mas' , label : '$200.000 o más COP/mes' } ,
96+ ] ,
97+ } ;
98+
99+ // -------------------------------------------------------------------------
100+ // Build HTML
101+ // -------------------------------------------------------------------------
102+ function buildPremiumSurveyHtml ( ) {
103+ const select = ( id , opts , required = false ) =>
104+ `<select id="${ id } " style="width:100%;margin-top:4px" ${ required ? 'required' : '' } >
105+ ${ opts . map ( o => `<option value="${ o . value } ">${ o . label } </option>` ) . join ( '' ) }
106+ </select>` ;
107+
108+ const checkboxes = ( opts ) =>
109+ opts . map ( o =>
110+ `<label style="display:block;margin:4px 0">
111+ <input type="checkbox" class="swal2-checkbox" name="q4_top_features[]" value="${ o . value } "> ${ o . label }
112+ </label>`
113+ ) . join ( '' ) ;
114+
115+ return `
116+ <div style="text-align:left;font-size:14px">
117+
118+ <p style="margin-bottom:16px">Tus respuestas nos ayudan a construir la versión premium que realmente necesitas. 🙏</p>
119+
120+ <!-- Q1: Satisfacción -->
121+ <div class="swal2-input-wrapper" style="margin-bottom:12px">
122+ <label for="q1_score"><strong>1. ¿Qué tan satisfecho estás con el plugin actual? (1 = muy insatisfecho, 10 = muy satisfecho) *</strong></label>
123+ ${ select ( 'q1_score' , Array . from ( { length :10 } , ( _ , i ) => ( { value : String ( i + 1 ) , label : String ( i + 1 ) } ) ) ) }
124+ </div>
125+
126+ <!-- Q1-motivo: solo visible si score < 8 -->
127+ <div id="q1_motivo_wrapper" style="margin-bottom:12px;display:none">
128+ <label for="q1_motivo"><strong>¿Por qué diste esa puntuación? (requerido) *</strong></label>
129+ <textarea id="q1_motivo" style="width:100%;margin-top:4px" rows="3" maxlength="500" placeholder="Cuéntanos qué podemos mejorar..."></textarea>
130+ </div>
131+
132+ <!-- Q2: Pain point -->
133+ <div class="swal2-input-wrapper" style="margin-bottom:12px">
134+ <label for="q2_pain_point"><strong>2. ¿Cuál es tu principal dolor con la integración actual?</strong></label>
135+ ${ select ( 'q2_pain_point' , premiumSurveyOptions . q2 ) }
136+ </div>
137+
138+ <!-- Q3: Time loss -->
139+ <div class="swal2-input-wrapper" style="margin-bottom:12px">
140+ <label for="q3_time_loss"><strong>3. ¿Cuánto tiempo semanal pierdes en tareas manuales de facturación/contabilidad?</strong></label>
141+ ${ select ( 'q3_time_loss' , premiumSurveyOptions . q3 ) }
142+ </div>
143+
144+ <!-- Q4: Top features (checkboxes, max 3) -->
145+ <div style="margin-bottom:12px">
146+ <label><strong>4. ¿Cuáles de estas funcionalidades valorarías más en la versión premium? (máximo 3) *</strong></label>
147+ <div id="q4_top_features" style="margin-top:6px">
148+ ${ checkboxes ( premiumSurveyOptions . q4 ) }
149+ </div>
150+ </div>
151+
152+ <!-- Q5: Other feature -->
153+ <div class="swal2-input-wrapper" style="margin-bottom:12px">
154+ <label for="q5_other_feature"><strong>5. Si seleccionaste "Otras", ¿cuál funcionalidad necesitas?</strong></label>
155+ <input id="q5_other_feature" type="text" style="width:100%;margin-top:4px" maxlength="200" placeholder="Describe la funcionalidad...">
156+ </div>
157+
158+ <!-- Q6: Billing model -->
159+ <div class="swal2-input-wrapper" style="margin-bottom:12px">
160+ <label for="q6_billing_model"><strong>6. ¿Qué modelo de cobro prefieres para la versión premium?</strong></label>
161+ ${ select ( 'q6_billing_model' , premiumSurveyOptions . q6 ) }
162+ </div>
163+
164+ <!-- Q7: Price range -->
165+ <div class="swal2-input-wrapper" style="margin-bottom:12px">
166+ <label for="q7_price_range"><strong>7. ¿Cuánto estarías dispuesto a pagar mensualmente? *</strong></label>
167+ ${ select ( 'q7_price_range' , premiumSurveyOptions . q7 , true ) }
168+ </div>
169+
170+ <!-- Q8: Open feedback -->
171+ <div class="swal2-input-wrapper" style="margin-bottom:12px">
172+ <label for="q8_open_feedback"><strong>8. ¿Algo más que quieras compartirnos?</strong></label>
173+ <textarea id="q8_open_feedback" style="width:100%;margin-top:4px" rows="3" maxlength="1000" placeholder="Comentarios adicionales..."></textarea>
174+ </div>
175+
176+ <!-- Consent -->
177+ <div style="margin-bottom:12px">
178+ <label>
179+ <input type="checkbox" id="consent_yes_no" class="swal2-checkbox">
180+ Autorizo que el equipo de Alegra WooCommerce me contacte para profundizar en mis respuestas.
181+ </label>
182+ </div>
183+
184+ <p style="font-size:12px;color:#666">* Campos obligatorios</p>
185+ </div>` ;
186+ }
187+
188+ // -------------------------------------------------------------------------
189+ // Collect and validate
190+ // -------------------------------------------------------------------------
191+ function collectPremiumSurveyData ( ) {
192+ const q1Score = parseInt ( $ ( '#q1_score' ) . val ( ) , 10 ) ;
193+
194+ if ( isNaN ( q1Score ) || q1Score < 1 || q1Score > 10 ) {
195+ Swal . showValidationMessage ( 'La satisfacción debe ser un valor entre 1 y 10.' ) ;
196+ return false ;
197+ }
198+
199+ if ( q1Score < 8 ) {
200+ const motivo = $ ( '#q1_motivo' ) . val ( ) . trim ( ) ;
201+ if ( ! motivo ) {
202+ Swal . showValidationMessage ( 'Por favor explica el motivo de tu baja satisfacción.' ) ;
203+ return false ;
204+ }
205+ }
206+
207+ const selectedFeatures = [ ] ;
208+ $ ( '#q4_top_features input[type="checkbox"]:checked' ) . each ( function ( ) {
209+ selectedFeatures . push ( $ ( this ) . val ( ) ) ;
210+ } ) ;
211+
212+ if ( selectedFeatures . length === 0 ) {
213+ Swal . showValidationMessage ( 'Selecciona al menos una funcionalidad premium.' ) ;
214+ return false ;
215+ }
216+
217+ if ( selectedFeatures . length > 3 ) {
218+ Swal . showValidationMessage ( 'Selecciona máximo 3 funcionalidades.' ) ;
219+ return false ;
220+ }
221+
222+ const q7PriceRange = $ ( '#q7_price_range' ) . val ( ) ;
223+ if ( ! q7PriceRange ) {
224+ Swal . showValidationMessage ( 'Selecciona un rango de precio.' ) ;
225+ return false ;
226+ }
227+
228+ return {
229+ q1_score : q1Score ,
230+ q1_motivo : $ ( '#q1_motivo' ) . val ( ) . trim ( ) ,
231+ q2_pain_point : $ ( '#q2_pain_point' ) . val ( ) ,
232+ q3_time_loss : $ ( '#q3_time_loss' ) . val ( ) ,
233+ q4_top_features : JSON . stringify ( selectedFeatures ) ,
234+ q5_other_feature : $ ( '#q5_other_feature' ) . val ( ) . trim ( ) ,
235+ q6_billing_model : $ ( '#q6_billing_model' ) . val ( ) ,
236+ q7_price_range : q7PriceRange ,
237+ q8_open_feedback : $ ( '#q8_open_feedback' ) . val ( ) . trim ( ) ,
238+ consent_yes_no : $ ( '#consent_yes_no' ) . is ( ':checked' ) ? 'yes' : 'no' ,
239+ } ;
240+ }
241+
242+ // -------------------------------------------------------------------------
243+ // Send survey via AJAX
244+ // -------------------------------------------------------------------------
245+ function sendPremiumSurveyResponse ( nonce , surveyData ) {
246+ return $ . ajax ( {
247+ url : ajaxurl ,
248+ type : 'POST' ,
249+ dataType : 'json' ,
250+ data : Object . assign ( { } , surveyData , {
251+ action : actionSendPremiumSurvey ,
252+ nonce,
253+ } ) ,
254+ } ) ;
255+ }
256+
257+ // -------------------------------------------------------------------------
258+ // Open modal
259+ // -------------------------------------------------------------------------
260+ function openPremiumSurveyModal ( nonce ) {
261+ Swal . fire ( {
262+ title : 'Encuesta Premium — Integration Alegra' ,
263+ html : buildPremiumSurveyHtml ( ) ,
264+ width : '680px' ,
265+ showCancelButton : true ,
266+ confirmButtonText : 'Enviar respuesta' ,
267+ cancelButtonText : 'Cancelar' ,
268+ allowOutsideClick : false ,
269+ showLoaderOnConfirm : true ,
270+ didOpen : ( ) => {
271+ // Show/hide q1_motivo based on q1_score
272+ $ ( '#q1_score' ) . on ( 'change' , function ( ) {
273+ const score = parseInt ( $ ( this ) . val ( ) , 10 ) ;
274+ if ( score < 8 ) {
275+ $ ( '#q1_motivo_wrapper' ) . show ( ) ;
276+ } else {
277+ $ ( '#q1_motivo_wrapper' ) . hide ( ) ;
278+ $ ( '#q1_motivo' ) . val ( '' ) ;
279+ }
280+ } ) ;
281+
282+ // Enforce max 3 checkboxes
283+ $ ( document ) . on ( 'change' , '#q4_top_features input[type="checkbox"]' , function ( ) {
284+ const checked = $ ( '#q4_top_features input[type="checkbox"]:checked' ) ;
285+ if ( checked . length > 3 ) {
286+ $ ( this ) . prop ( 'checked' , false ) ;
287+ Swal . showValidationMessage ( 'Solo puedes seleccionar un máximo de 3 funcionalidades.' ) ;
288+ }
289+ } ) ;
290+ } ,
291+ preConfirm : ( ) => {
292+ return collectPremiumSurveyData ( ) ;
293+ } ,
294+ } ) . then ( ( result ) => {
295+ if ( ! result . isConfirmed || ! result . value ) return ;
296+
297+ Swal . fire ( {
298+ title : 'Enviando respuesta…' ,
299+ didOpen : ( ) => Swal . showLoading ( ) ,
300+ allowOutsideClick : false ,
301+ } ) ;
302+
303+ sendPremiumSurveyResponse ( nonce , result . value )
304+ . done ( ( r ) => {
305+ if ( r . status ) {
306+ Swal . fire ( {
307+ icon : 'success' ,
308+ title : '¡Gracias!' ,
309+ text : r . message || 'Tu respuesta fue enviada correctamente.' ,
310+ } ) ;
311+ } else {
312+ Swal . fire ( {
313+ icon : 'error' ,
314+ title : 'Error' ,
315+ text : r . message || 'No fue posible enviar la respuesta.' ,
316+ } ) ;
317+ }
318+ } )
319+ . fail ( ( ) => {
320+ Swal . fire ( {
321+ icon : 'error' ,
322+ title : 'Error de conexión' ,
323+ text : 'No fue posible conectar con el servidor. Intenta nuevamente.' ,
324+ } ) ;
325+ } ) ;
326+ } ) ;
327+ }
328+
329+ // -------------------------------------------------------------------------
330+ // Auto-open from URL (?open_premium_survey=1)
331+ // -------------------------------------------------------------------------
332+ function maybeOpenPremiumSurveyFromUrl ( ) {
333+ const params = new URLSearchParams ( window . location . search ) ;
334+ if ( params . get ( 'open_premium_survey' ) !== '1' ) return ;
335+
336+ const $btn = $ ( premiumSurveyButton ) . first ( ) ;
337+ if ( ! $btn . length ) return ;
338+
339+ openPremiumSurveyModal ( $btn . data ( 'nonce' ) ) ;
340+ }
341+
342+ // -------------------------------------------------------------------------
343+ // Dismiss notice via AJAX on WP dismiss button click
344+ // -------------------------------------------------------------------------
345+ function persistPremiumSurveyNoticeDismiss ( ) {
346+ $ ( document ) . on ( 'click' , '.alegra-premium-survey-notice .notice-dismiss' , function ( ) {
347+ const nonce = $ ( this ) . closest ( '.alegra-premium-survey-notice' ) . data ( 'dismiss-nonce' ) ;
348+ if ( ! nonce ) return ;
349+
350+ $ . post ( ajaxurl , {
351+ action : actionDismissPremiumSurveyNotice ,
352+ nonce,
353+ } ) ;
354+ } ) ;
355+ }
356+
357+ // -------------------------------------------------------------------------
358+ // Event listeners
359+ // -------------------------------------------------------------------------
360+ $ ( document ) . on ( 'click' , premiumSurveyButton , function ( e ) {
361+ e . preventDefault ( ) ;
362+ openPremiumSurveyModal ( $ ( this ) . data ( 'nonce' ) ) ;
363+ } ) ;
364+
365+ $ ( document ) . ready ( function ( ) {
366+ maybeOpenPremiumSurveyFromUrl ( ) ;
367+ } ) ;
368+ persistPremiumSurveyNoticeDismiss ( ) ;
369+
370+ } ) ( jQuery ) ;
0 commit comments