Si è verificato un errore nell'elaborarazione del modello.
The following has evaluated to null or missing: ==> docTitle [in template "383767#383802#7056679" at line 2128, column 50] ---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: ${docTitle?js_string} [in template "383767#383802#7056679" at line 2128, column 48] ----
1<#--
2 Sezione di pagamento Zainetto Verde
3 ©Suggesto 2024
4-->
5
6<#assign
7 RoleService = serviceLocator.findService("com.liferay.portal.kernel.service.RoleService")
8 hasAccompagnatorePerm = RoleService.hasUserRole(themeDisplay.getUser().userId, themeDisplay.getCompanyId(), "Accompagnatore", false)
9
10 JALS = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")
11 JSONFactoryUtil = staticUtil["com.liferay.portal.kernel.json.JSONFactoryUtil"]
12 articleId = "1221309"
13 article = JALS.fetchArticle(groupId, articleId)
14 document = saxReaderUtil.read(article.getContent())
15 rootElement = document.getRootElement()
16 allegati = []
17
18 stringSelector = "dynamic-element[@name='allegato']"
19 xPathSelector = saxReaderUtil.createXPath(stringSelector)
20/>
21
22<#if xPathSelector.selectNodes(rootElement)??>
23 <#assign allegati = xPathSelector.selectNodes(rootElement)>
24</#if>
25
26<style>
27 .bg-light-gray{
28 background-color:#f4f4f4;
29 }
30</style>
31
32<#macro printContent>
33 <div id="pay" class="p-3" v-cloak>
34 <div v-show="loading">
35 <div class="d-flex align-items-center justify-content-center h-full">
36 <div class="loading-animation"></div>
37 </div>
38 </div>
39
40 <div class="container" v-show="!loading">
41 <div class="text-center" v-if="name == 'Placeholder'">
42 <p class="text-dark">Errore interno.</p>
43 <p class="text-dark">Ricarica la pagina per continuare.</p>
44 </div>
45 <div class="row" v-else>
46 <div class="col-12">
47 <ol class="d-none d-lg-flex nav multi-step-nav multi-step-nav-collapse-sm flex-row" role="tablist">
48 <li v-for="(num, index) in totalSteps" class="multi-step-item" :class="{'complete': currentStep >= num, 'multi-step-item-expand': index != totalSteps-1}">
49 <div class="multi-step-divider"></div>
50 <div class="multi-step-indicator">
51 <button class="multi-step-icon bg-image-none" data-toggle="tab" @click="currentStep = num" v-if="isDev">
52 <span class="text-white font-weight-bold">{{ num }}</span>
53 </button>
54 <div class="multi-step-icon bg-image-none" data-toggle="tab" v-else>
55 <span class="text-white font-weight-bold">{{ num }}</span>
56 </div>
57 </div>
58 </li>
59 </ol>
60
61 <div class="tbar subnav-tbar subnav-tbar-light d-lg-none">
62 <div class="container-fluid container-fluid-max-xl">
63 <div class="tbar-nav">
64 <div class="tbar-item tbar-item-expand">
65 <div class="tbar-section">
66 <span class="component-text text-truncate-inline">
67 <span class="text-truncate">Acquisto</span>
68 </span>
69 </div>
70 </div>
71 <div class="tbar-item">
72 <span class="component-text">Pagina {{ currentStep }} di {{ totalSteps }}</span>
73 </div>
74 </div>
75 </div>
76 </div>
77
78 <div class="tab-content mt-lg-5">
79
80 <#-- STEP 1: CALENDARIO -->
81 <div class="tab-pane fade" :class="{'show active': currentStep == 1}" role="tabpanel">
82 <div class="row justify-content-between">
83 <div class="d-none d-lg-block col-12 mb-4">
84 <p class="text-dark display-5 font-weight-light">Vai avanti per confermare il pacchetto Test <span class="text-gray small" style="font-size:1rem;">(oppure modifica la tua scelta)</span></p>
85 </div>
86
87 <#-- <div class="col-12 col-lg-5">
88 <div id="v-calendar" class="single w-100 w-lg-75 mx-auto mb-3 mb-lg-4">
89 <v-calendar
90 v-if="calendar.ready"
91 v-model="calendar.dataSelected"
92 @dayclick="selectDate"
93 :available-dates="calendar.dateDisponibili"
94 :attributes="calendar.attributes"
95 :min-page="calendar.initialPage"
96 :min-date="calendar.dataInizio"
97 :max-date="calendar.dataFine"
98 nav-visibility="hidden"
99 title-position="left"
100 ref="calendar"
101 mode="single"
102 is-expanded
103 is-inline
104 />
105 </div>
106
107 <div class="card void mt-4 mt-lg-0">
108 <div class="card-row flex-column flex-md-row">
109 <div class="autofit-col autofit-col-expand">
110 <section class="autofit-section">
111 <p class="text-dark text-center text-md-left mb-lg-0">Desideri prenotare per un gruppo o verificare la disponibilità di date e orari non elencati?</p>
112 </section>
113 </div>
114 <div class="autofit-col">
115 <section class="autofit-section">
116 <button @click="openParentModal('#requestinfo-payment-modal')" class="btn btn-outline-dark btn-block py-2 px-3">Contattaci</button>
117 </section>
118 </div>
119 </div>
120 </div>
121 </div>-->
122
123 <div id="results" class="row" style="width:100%;">
124 <template v-for="(package, index) in packages">
125 <template v-if="!needsPermission(package) || (needsPermission(package) && hasAccompagnatorePermission)">
126 <div class="col-12 col-lg-6">
127 <div v-if="isAfter(package.startDate) && !package.additionalInfo.ritirato && !package.startDate.includes('2030')" class="card no-shadow rounded" style="border: 2px solid #43A08E !important;" :key="package._id.$oid">
128
129 <div :class="_.get(selectedPackage, '_id.$oid', '') == package._id.$oid ? 'card-body p-3 bg-light-gray':'card-body p-3'">
130
131 <div class="card-row" v-show="package.show"> <#-- && !isBefore(package?.endDate) && !package.additionalInfo.ritirato -->
132 <div class="autofit-col autofit-col-expand">
133 <section class="autofit-section">
134 <p class="text-muted mb-0">dal {{ package?.startDate | moment().format("DD MMMM YYYY") }} al {{ package?.endDate | moment().format("DD MMMM YYYY") }}</p>
135 <p class="mb-0">
136 <span class="badge badge-pill badge-primary bg-gradient-h" v-if="package.forGroup">
137 <span class="badge-item badge-item-expand">Per gruppi</span>
138 </span>
139 <template v-if="package.marketingGroups">
140 <span v-for="(item, index) in package.marketingGroups" :key="'mg-' + index" class="badge badge-pill badge-primary bg-gradient-h">
141 <span class="badge-item badge-item-expand">{{ item.name }}</span>
142 </span>
143 </template>
144 </p>
145 <p class="text-dark mb-0">A partire da {{ package.basePrice | money }}</p>
146
147 <template v-for="(sconto, index) in package.purchaseBeforeDiscount">
148 <p v-if="isDiscountValid(sconto) && sconto.discount != 0" :key="'discount-' + index + '-' + package._id.$oid" class="text-muted small mb-0">
149 Acquista entro il {{ sconto.dateEnd | moment().subtract(1, "days").format("DD MMMM YYYY") }}:
150 <span class="label label-success">
151 <span class="label-item label-item-expand">Sconto di {{ sconto.discount | money }}</span>
152 </span>
153 </p>
154 </template>
155 </section>
156 </div>
157 <div class="autofit-col">
158 <section class="autofit-section">
159 <button class="btn btn-gradient py-2 px-3 px-lg-4" v-if="_.get(selectedPackage, '_id.$oid', '') == package._id.$oid">
160 Scelto
161 <i class="fas fa-check ml-2"></i>
162 </button>
163
164 <button @click="selectPackage(package._id.$oid)" class="btn btn-outline-dark py-2 px-3 px-lg-4" v-else>
165 Scegli
166 </button>
167 </section>
168 </div>
169 </div>
170 </div>
171
172 <#-- <div v-if="index < packages.length - 1 && !isBefore(package?.endDate)" class="dropdown-divider w-75 mx-auto my-3"></div> -->
173 </div>
174 </div>
175 </template>
176 </template>
177 </div>
178
179 <div class="col-12">
180 <div class="card void mt-3 mt-lg-5 mb-0">
181 <div class="card-row">
182 <div class="autofit-col autofit-col-expand">
183 <section class="autofit-section text-left">
184 <#--
185 <button @click="gotoStep('prev')" class="btn btn-outline-dark py-2 px-3 px-lg-4">
186 Indietro
187 </button>
188 -->
189 </section>
190 </div>
191 <div class="autofit-col autofit-col-expand">
192 <section class="autofit-section text-right">
193 <button @click="!_.isEmpty(selectedPackage) ? gotoStep('next') : ''" class="btn btn-gradient py-2 px-3 px-lg-4" :disabled="_.isEmpty(selectedPackage)">
194 Avanti
195 </button>
196 </section>
197 </div>
198 </div>
199 </div>
200 </div>
201 </div>
202 </div>
203
204 <#-- STEP 2: TRASPORTO -->
205 <div class="tab-pane fade" :class="{'show active': currentStep == 2}" role="tabpanel">
206 <div class="row justify-content-between">
207 <div class="d-none d-lg-block col-12 mb-4">
208 <p class="text-dark display-5 font-weight-light">Scegli il tuo trasferimento</p>
209 </div>
210
211 <div class="col-12 col-lg-6" v-if="!_.isEmpty(selectedPackage)">
212 <ul class="list-group mb-lg-0">
213 <li v-for="(partenza, index) in selectedPackage.airportsAndPrices" :key="'airport-' + index" class="list-group-item">
214 <div class="card-row flex-column flex-lg-row">
215 <div class="autofit-col autofit-col-expand">
216 <section class="autofit-section my-auto">
217 <#-- <span class="label label-success" v-if="partenza.price == 0">
218 <span class="label-item label-item-expand">Volo incluso</span>
219 </span>
220 -->
221 <div class="custom-control custom-radio">
222 <label>
223 <input class="custom-control-input" type="radio" name="airportsAndPrices" v-model="selectedAirport" :value="partenza" />
224 <span class="custom-control-label">
225 <span class="custom-control-label-text">{{ getCity(partenza.airport) }}</span>
226 </span>
227 </label>
228 </div>
229 </section>
230 </div>
231 <div class="autofit-col autofit-col-expand">
232 <section class="autofit-section my-auto">
233 <p class="text-dark text-right h3 mb-0 mr-3">{{ partenza.price | money }}</p>
234 </section>
235 </div>
236 </div>
237 </li>
238 </ul>
239 </div>
240 <div class="col-12 col-lg-6" v-else>
241 <p class="text-dark display-5 font-weight-light">Per continuare, seleziona un periodo dalla prima pagina.</p>
242 </div>
243
244 <div class="col-12">
245 <div class="card void mt-3 mt-lg-5 mb-0">
246 <div class="card-row">
247 <div class="autofit-col autofit-col-expand">
248 <section class="autofit-section text-left">
249 <button @click="gotoStep('prev')" class="btn btn-outline-dark py-2 px-3 px-lg-4">
250 Indietro
251 </button>
252 </section>
253 </div>
254 <div class="autofit-col autofit-col-expand">
255 <section class="autofit-section text-right">
256 <button @click="!_.isEmpty(selectedAirport) ? gotoStep('next') : ''" class="btn btn-gradient py-2 px-3 px-lg-4" :disabled="_.isEmpty(selectedAirport)">
257 Avanti
258 </button>
259 </section>
260 </div>
261 </div>
262 </div>
263 </div>
264 </div>
265 </div>
266
267 <#-- STEP 3: ALLOGGIO -->
268 <div class="tab-pane fade" :class="{'show active': currentStep == 3}" role="tabpanel">
269 <div class="row">
270 <div class="d-none d-lg-block col-12 mb-4">
271 <p class="text-dark display-5 font-weight-light">Scegli l'alloggio</p>
272 </div>
273
274 <div class="col-12 col-lg-7" v-if="!_.isEmpty(selectedPackage)">
275 <ul class="list-group mb-lg-0">
276 <li v-for="(accomodation, index) in selectedPackage.lodgingTypesAndPrices" :key="'accomodation-' + index" class="list-group-item">
277 <div class="card-row flex-column flex-lg-row">
278 <div class="autofit-col autofit-col-expand">
279 <section class="autofit-section my-auto">
280 <div class="custom-control custom-radio">
281 <label>
282 <input class="custom-control-input" type="radio" name="lodgingTypesAndPrices" v-model="selectedAccomodation" :value="accomodation" />
283 <span class="custom-control-label">
284 <span class="custom-control-label-text">{{ accomodation.lodgingType }}</span>
285 </span>
286 </label>
287 </div>
288 </section>
289 </div>
290 <div class="autofit-col autofit-col-expand">
291 <section class="autofit-section my-auto">
292 <p class="text-dark text-right h3 mb-0 mr-3">{{ accomodation.price | money }}</p>
293 </section>
294 </div>
295 </div>
296 </li>
297 </ul>
298 </div>
299 <div class="col-12" v-else>
300 <p class="text-dark display-5 font-weight-light">Per continuare, seleziona un periodo dalla prima pagina.</p>
301 </div>
302
303 <div class="col-12">
304 <div class="card void mt-3 mt-lg-5 mb-0">
305 <div class="card-row">
306 <div class="autofit-col autofit-col-expand">
307 <section class="autofit-section text-left">
308 <button @click="gotoStep('prev')" class="btn btn-outline-dark py-2 px-3 px-lg-4">
309 Indietro
310 </button>
311 </section>
312 </div>
313 <div class="autofit-col autofit-col-expand">
314 <section class="autofit-section text-right">
315 <button @click="!_.isEmpty(selectedAccomodation) ? gotoStep('next') : ''" class="btn btn-gradient py-2 px-3 px-lg-4" :disabled="_.isEmpty(selectedAccomodation)">
316 Avanti
317 </button>
318 </section>
319 </div>
320 </div>
321 </div>
322 </div>
323 </div>
324 </div>
325
326 <#-- STEP 4: SERVIZI -->
327 <div class="tab-pane fade" :class="{'show active': currentStep == 4}" role="tabpanel">
328 <div class="row">
329 <div class="d-none d-lg-block col-12 mb-4">
330 <p class="text-dark display-5 font-weight-light">Scegli altri servizi</p>
331 </div>
332
333 <div class="col-12 col-lg-7" v-if="!_.isEmpty(selectedPackage)">
334 <ul class="list-group mb-lg-0">
335 <li v-for="(service, index) in selectedPackage.servicesAndPrices" :key="'service-' + index" class="list-group-item">
336 <div class="card-row flex-column flex-lg-row">
337 <div class="autofit-col autofit-col-expand">
338 <section class="autofit-section my-auto">
339 <span class="label label-danger" v-if="service.mandatory">
340 <span class="label-item label-item-expand">Obbligatorio</span>
341 </span>
342
343 <div class="custom-control custom-checkbox">
344 <label class="{'no-events': service.mandatory}">
345 <input class="custom-control-input" :class="{'no-events': service.mandatory}" type="checkbox" v-model="selectedServices" :value="service" :checked="service.mandatory" :disabled="service.mandatory" />
346 <span class="custom-control-label">
347 <span class="custom-control-label-text">{{ service.service }}</span>
348 </span>
349 </label>
350 </div>
351 </section>
352 </div>
353 <div class="autofit-col autofit-col-expand" style="min-width: 15%;">
354 <section class="autofit-section my-auto">
355 <p class="text-dark text-right h3 mb-0 mr-3">{{ service.price | money }}</p>
356 </section>
357 </div>
358 </div>
359 </li>
360 </ul>
361 </div>
362 <div class="col-12" v-else>
363 <p class="text-dark display-5 font-weight-light">Per continuare, seleziona un periodo dalla prima pagina.</p>
364 </div>
365
366 <div class="col-12">
367 <div class="card void mt-3 mt-lg-5 mb-0">
368 <div class="card-row">
369 <div class="autofit-col autofit-col-expand">
370 <section class="autofit-section text-left">
371 <button @click="gotoStep('prev')" class="btn btn-outline-dark py-2 px-3 px-lg-4">
372 Indietro
373 </button>
374 </section>
375 </div>
376 <div class="autofit-col autofit-col-expand">
377 <section class="autofit-section text-right">
378 <button @click="selectedServices.length > 0 ? gotoStep('next') : ''" class="btn btn-gradient py-2 px-3 px-lg-4" :disabled="selectedServices.length == 0">
379 Avanti
380 </button>
381 </section>
382 </div>
383 </div>
384 </div>
385 </div>
386 </div>
387 </div>
388
389 <#-- STEP 5: FORM DATI MINIMAL -->
390 <div class="tab-pane fade" :class="{'show active': currentStep == 5}" role="tabpanel">
391 <div class="row justify-content-center">
392 <div class="d-none d-lg-block col-12 mb-4">
393 <p class="text-dark display-5 font-weight-light">Inserisci i tuoi dati</p>
394 </div>
395
396 <div class="col-12 col-lg-9" v-if="!_.isEmpty(selectedPackage)">
397 <div class="sheet sheet-lg">
398 <div class="sheet-header">
399 <div class="sheet-text">
400 Inserisci i tuoi dati per poter calcolare, senza impegno, il preventivo e riceverlo automaticamente per email.
401 </div>
402 </div>
403 <div class="sheet-section">
404 <div class="form-group-autofit">
405 <div class="form-group-item">
406 <label for="userName">Nome *</label>
407 <input class="form-control" id="userName" v-model="userData.firstName" type="text"/>
408 </div>
409 <div class="form-group-item">
410 <label for="userSurname">Cognome *</label>
411 <input class="form-control" id="userSurname" v-model="userData.lastName" type="text"/>
412 </div>
413 </div>
414 <div class="form-group-autofit">
415 <div class="form-group-item">
416 <label for="billingEmail">Email *</label>
417 <input class="form-control" id="billingEmail" v-model="userMail" type="email"/>
418 </div>
419 <div class="form-group-item">
420 <label for="phone">Telefono</label>
421 <input class="form-control" id="phone" v-model="userData.phone" type="text"/>
422 </div>
423 </div>
424
425 <div class="form-group-autofit">
426 <div class="form-group-item">
427 <div class="form-text">I campi contrassegnati con * sono obbligatori.</div>
428 </div>
429 </div>
430
431
432 <div class="form-group-autofit" v-if='sendingMessageError != ""'>
433 <div class="form-group-item">
434 <div class="form-text">
435 <p class="text-muted " style="color:red !important;">
436 Errore durante l'invio del preventivo. Correggi i dati inseriti e riprova
437 </p>
438 </div>
439 </div>
440 </div>
441
442
443 </div>
444 </div>
445 </div>
446 <div class="col-12" v-else>
447 <p class="text-dark display-5 font-weight-light">Per continuare, seleziona un periodo dalla prima pagina.</p>
448 </div>
449
450 <div class="col-12">
451 <div class="card void mt-3 mt-lg-5 mb-0">
452 <div class="card-row">
453 <div class="autofit-col autofit-col-expand">
454 <section class="autofit-section text-left">
455 <button @click="gotoStep('prev')" class="btn btn-outline-dark py-2 px-3 px-lg-4">
456 Indietro
457 </button>
458 </section>
459 </div>
460 <div class="autofit-col autofit-col-expand">
461 <section class="autofit-section text-right">
462 <button @click="sendRequestMessage()" class="btn btn-gradient py-2 px-3 px-lg-4" :disabled="!minimumValid">
463 Scarica preventivo
464 </button>
465 </section>
466 </div>
467 </div>
468 </div>
469 </div>
470 </div>
471 </div>
472
473 <#-- STEP 6: RIEPILOGO -->
474 <div class="tab-pane fade" :class="{'show active': currentStep == 6}" role="tabpanel">
475
476 <div class="sheet border-0 p-0 p-lg-4">
477 <div class="row">
478 <div class="d-none d-lg-block col-12 mb-4">
479 <p class="text-dark display-5 font-weight-light">Il tuo preventivo</p>
480 </div>
481
482 <div class="col-12">
483 <div class="card void">
484 <div class="card-row flex-column flex-lg-row mb-4 mb-lg-0">
485 <div class="autofit-col autofit-col-expand">
486 <section class="autofit-section mb-auto">
487 <p class="h1 display-5 title-large">{{ name }}</p>
488 <p class="text-dark">
489 Dal {{ selectedPackage?.startDate | moment().format("DD MMMM YYYY") }} al {{ selectedPackage?.endDate | moment().format("DD MMMM YYYY") }}
490 </p>
491 </section>
492 </div>
493 </div>
494 </div>
495 </div>
496 </div>
497
498 <div class="row">
499 <div class="col-12 col-lg-6 order-2 order-lg-1">
500 <div class="panel panel-secondary" v-if="packagePrice != 0">
501 <div class="panel-header">
502 <div class="panel-title">
503 Informazioni di base:
504 </div>
505 </div>
506 <div class="panel-body">
507 <p class="mb-0">
508 Prezzo del viaggio: <span class="font-weight-bold">{{ packagePrice | money }}</span>
509 </p>
510 <p class="mb-0" v-if="packageDiscount != 0">
511 Sconto applicato: <span class="font-weight-bold">{{ packageDiscount | money }}</span>
512 </p>
513 </div>
514 </div>
515
516 <div class="panel panel-secondary">
517 <div class="panel-header">
518 <div class="panel-title">
519 Sistemazione:
520 </div>
521 </div>
522 <div class="panel-body">
523 <p class="mb-0">
524 {{ selectedAccomodation.lodgingType }} <span class="font-weight-bold">({{ selectedAccomodation.price | money }})</span>
525 </p>
526 </div>
527 </div>
528
529 <div class="panel panel-secondary">
530 <div class="panel-header">
531 <div class="panel-title">
532 Servizi scelti:
533 </div>
534 </div>
535 <div class="panel-body">
536 <p v-for="(service, index) in selectedServices" :key="'selectedService-' + index" class="mb-0">
537 {{ service.service }} <span class="font-weight-bold">({{ service.price | money }})</span>
538 </p>
539 </div>
540 </div>
541
542 <div class="panel panel-secondary">
543 <div class="panel-header">
544 <div class="panel-title">
545 Trasporto scelto:
546 </div>
547 </div>
548 <div class="panel-body">
549 <p class="mb-0">
550 {{ selectedAirport.airport }} <span class="font-weight-bold">({{ selectedAirport.price | money }})</span>
551 </p>
552 </div>
553 </div>
554
555 <div class="panel panel-secondary" v-if="!_.isEmpty(selectedPayment)">
556 <div class="panel-header">
557 <div class="panel-title">
558 Tipo di pagamento scelto (Acconto):
559 </div>
560 </div>
561 <div class="panel-body">
562 <div class="card void m-0 p-0">
563 <div class="card-row">
564 <div class="autofit-col autofit-col-expand my-auto">
565 <section class="autofit-section">
566 <p class="mb-0">
567 {{ selectedPayment.type }} <span class="font-weight-bold" v-if="selectedPayment.amount && selectedPayment.amount != 0">( Acconto: {{ selectedPayment.amount | money }})</span>
568 </p>
569 </section>
570 </div>
571 </div>
572 </div>
573 </div>
574 </div>
575
576 <div class="panel panel-secondary" v-if="!_.isEmpty(selectedBalance)">
577 <div class="panel-header">
578 <div class="panel-title">
579 Tipo di pagamento scelto (Saldo):
580 </div>
581 </div>
582 <div class="panel-body">
583 <div class="card void m-0 p-0">
584 <div class="card-row">
585 <div class="autofit-col autofit-col-expand my-auto">
586 <section class="autofit-section">
587 <p class="mb-0">
588 {{ selectedBalance.type }}
589 </p>
590 </section>
591 </div>
592 </div>
593 </div>
594 </div>
595 </div>
596
597 <div class="panel panel-secondary">
598 <div class="panel-header">
599 <div class="panel-title">
600 Voucher:
601 </div>
602 </div>
603 <div class="panel-body">
604 <p v-if="voucherDiscount > 0">
605 Sconto applicato: <span class="font-weight-bold">{{ voucherDiscount | money }}</span>
606 </p>
607
608 <div class="card void m-0 p-0">
609 <div class="card-row">
610 <div class="autofit-col autofit-col-expand my-auto">
611 <section class="autofit-section">
612 <div class="form-group">
613 <div class="input-group">
614 <div class="input-group-item input-group-prepend">
615 <input type="text" v-model="voucher" class="form-control" placeholder="Inserisci il codice" :disabled="voucherValid" />
616 </div>
617 <span class="input-group-append input-group-item input-group-item-shrink">
618 <button @click="checkVoucher()" class="btn btn-secondary" :disabled="voucher == '' || voucherValid">
619 <span v-if="voucherValid">
620 Valido
621 <i class="fas fa-check ml-2"></i>
622 </span>
623 <span v-else>
624 Verifica
625 </span>
626 </button>
627 </span>
628 </div>
629 </div>
630 </section>
631 </div>
632 </div>
633 </div>
634 </div>
635 </div>
636 </div>
637 <div class="col-12 col-lg-6 order-1 order-lg-2">
638 <div class="panel panel-secondary">
639 <div class="panel-body">
640 <div class="card void my-3">
641 <div class="d-flex justify-content-center">
642 <div class="d-flex flex-column text-center mx-auto">
643 <span class="sticker sticker-xl sticker-person rounded-circle mb-4">
644 <span class="sticker-overlay">
645 <img :src="image" class="w-100 h-100" :alt="name">
646 </span>
647 </span>
648
649 <button type="button" v-if="signedIn" class="btn btn-outline-dark px-3" @click="favourite ? removeFavourite() : setFavourite()">
650 <span>{{ favourite ? 'Salvato' : 'Salva' }}</span>
651 <i class="fa-heart fa-lg ml-3" :class="favourite ? 'fas' : 'far'"></i>
652 </button>
653 </div>
654 </div>
655 </div>
656
657 <div class="card void my-3">
658 <div class="card-row flex-column">
659 <div class="autofit-col autofit-col-expand">
660 <section v-if="voucherDiscount > 0" class="autofit-section">
661 <div class="d-flex flex-row text-dark text-center my-4 justify-content-center">
662 <p class="my-auto">Totale importo: </p>
663 <span class="text-left d-flex flex-column">
664 <span class="ml-3" style="text-decoration: line-through;">{{ totalPrice | money }}</span>
665 <span class="display-5 ml-3">{{ totalPriceWithVoucher | money }}</span>
666 </span>
667 </div>
668 <p v-if="_.get(selectedPayment, 'amount', 0) != 0" class="text-dark text-center my-4">
669 Acconto da pagare:
670 <span class="display-5 ml-3">{{ selectedPayment.depositAmount | money }}</span>
671 </p>
672 </section>
673
674 <section v-else class="autofit-section">
675 <p class="text-dark text-center my-4">
676 Totale importo:
677 <span class="display-5 ml-3">{{ totalPrice | money }}</span>
678 </p>
679 <p class="text-dark text-center my-4" v-if="_.get(selectedPayment, 'amount', 0) != 0">
680 Acconto da pagare:
681 <span class="display-5 ml-3">{{ selectedPayment.amount | money }}</span>
682 </p>
683 </section>
684 </div>
685 <div class="autofit-col autofit-col-expand">
686 <div class="autofit-section">
687 <p style="font-size: 0.9rem; line-height: 1.5 !important;">
688 Modalità di pagamento: acconto alla conferma, saldo prima della data prevista per la partenza. Se sei interessato ad un eventuale finanziamento, richiedi informazioni a
689 <a href="mailto:info@zainettoverde.it" class="text-aqua"><u>info@zainettoverde.it</u></a>.
690 </p>
691 </div>
692 </div>
693 <div class="autofit-col autofit-col-expand">
694 <section class="autofit-section">
695
696 <button v-if="signedIn" @click="gotoStep('next')" class="btn btn-gradient btn-block py-2">
697 Iscrizione e pagamento acconto
698 </button>
699 <button v-else @click="setProgressData();redirectParent('/login')" class="btn btn-outline-dark btn-block py-2">
700 Accedi per procedere al pagamento acconto
701 </button>
702 </section>
703 </div>
704 </div>
705 </div>
706 </div>
707 </div>
708 </div>
709 </div>
710
711 <div class="row">
712 <div class="col-12">
713 <div class="card void mt-3 mt-lg-5 mb-0">
714 <div class="card-row">
715 <div class="autofit-col autofit-col-expand">
716 <section class="autofit-section text-left">
717 <button @click="gotoStep('prev')" class="btn btn-outline-dark py-2 px-3 px-lg-4">
718 Indietro
719 </button>
720 </section>
721 </div>
722 </div>
723 </div>
724 </div>
725 </div>
726 </div>
727 </div>
728
729 <#-- STEP 7: FORM DATI ESTESO -->
730 <div class="tab-pane fade" id="payment_step" :class="{'show active': currentStep == 7}" role="tabpanel">
731 <div class="row justify-content-center">
732 <div class="d-none d-lg-block col-12 mb-4">
733 <p class="text-dark display-5 font-weight-light">Completa il modulo di iscrizione</p>
734 </div>
735
736 <div class="col-12 col-lg-9" v-if="!_.isEmpty(selectedPackage) && userData != null && signedIn">
737 <div class="sheet sheet-lg">
738 <div class="sheet-header">
739 <div class="sheet-text" style="color:red;">
740 <span class="text-red font-weight-bold">IMPORTANTE:</span>
741 per poter impostare correttamente la pratica, è indispensabile compilare <u>tutti i campi</u> del presente modulo
742 </div>
743 </div>
744
745 <div class="sheet-section">
746 <p class="sheet-title">Dati del genitore per fatturazione</p>
747
748 <div class="form-group-autofit">
749 <div class="form-group-item">
750 <label for="tutoreFirstName">Nome</label>
751 <input @blur="checkEmpty($event)" class="form-control" id="tutoreFirstName" v-model="userData.tutore.firstName" type="text"/>
752 </div>
753 <div class="form-group-item">
754 <label for="tutoreLastName">Cognome</label>
755 <input @blur="checkEmpty($event)" class="form-control" id="tutoreLastName" v-model="userData.tutore.lastName" type="text"/>
756 </div>
757 </div>
758
759 <div class="form-group-autofit">
760 <div class="form-group-item">
761 <label for="tutoreBirthdayPlace">Nato a</label>
762 <input @blur="checkEmpty($event)" class="form-control" id="tutoreBirthdayPlace" v-model="userData.tutore.birthdayPlace" type="text"/>
763 </div>
764 <div class="form-group-item">
765 <label for="tutoreBirthday">il (gg/mm/aaaa)</label>
766 <input @blur="checkDateLength($event)" class="form-control" id="tutoreBirthday" @keydown="restrictDateInput" v-model="userData.tutore.birthday" type="text"/>
767 </div>
768 <div class="form-group-item">
769 <label>Sesso</label>
770 <div>
771 <div class="custom-control custom-radio custom-control-inline">
772 <label>
773 <input @change="checkRadio('tutoreGender')" class="custom-control-input" name="tutoreGender" type="radio" value="male" v-model="userData.tutore.gender"/>
774 <span class="custom-control-label">
775 <span class="custom-control-label-text">M</span>
776 </span>
777 </label>
778 </div>
779 <div class="custom-control custom-radio custom-control-inline">
780 <label>
781 <input @change="checkRadio('tutoreGender')" class="custom-control-input" name="tutoreGender" type="radio" value="female" v-model="userData.tutore.gender"/>
782 <span class="custom-control-label">
783 <span class="custom-control-label-text">F</span>
784 </span>
785 </label>
786 </div>
787 </div>
788 </div>
789 <div class="form-group-item">
790 <label for="tutoreNazione">Nazione</label>
791 <input @blur="checkEmpty($event)" class="form-control" id="tutoreNazione" v-model="userData.tutore.nazione" type="text"/>
792 </div>
793 </div>
794
795 <div class="form-group-autofit">
796 <div class="form-group-item">
797 <label for="tutoreAddress">Indirizzo</label>
798 <input @blur="checkEmpty($event)" class="form-control" id="tutoreAddress" v-model="userData.tutore.address" type="text"/>
799 </div>
800 </div>
801 <div class="form-group-autofit">
802 <div class="form-group-item">
803 <label for="tutoreCitta">Città</label>
804 <input @blur="checkEmpty($event)" class="form-control" id="tutoreCitta" v-model="userData.tutore.citta" type="text"/>
805 </div>
806 <div class="form-group-item">
807 <label for="tutoreCap">CAP</label>
808 <input @blur="checkEmpty($event)" class="form-control" id="tutoreCap" v-model="userData.tutore.cap" type="text"/>
809 </div>
810 <div class="form-group-item">
811 <label for="tutoreProvincia">Provincia</label>
812 <select @blur="checkSelect($event)" class="form-control" id="tutoreProvincia" v-model="userData.tutore.provincia">
813 <option v-for="province in italianProvinces" :key="province.code" :value="province.code">{{ province.name }}</option>
814 </select>
815 </div>
816 </div>
817 <div class="form-group-autofit">
818 <div class="form-group-item">
819 <label for="tutoreCodiceFiscale">Codice fiscale</label>
820 <input @blur="checkCodiceFiscale($event)" class="form-control" id="tutoreCodiceFiscale" v-model="userData.tutore.codiceFiscale" type="text"/>
821 </div>
822 <div class="form-group-item">
823 <label for="tutoreCellulare">Telefono/Cellulare (solo numeri)</label>
824 <input @blur="checkTelefono($event)" class="form-control" id="tutoreCellulare" @keydown="restrictDigitInput" v-model="userData.tutore.cellulare" type="text"/>
825 </div>
826 <div class="form-group-item">
827 <label for="tutoreEmail">Email</label>
828 <input @blur="checkEmail($event)" class="form-control" id="tutoreEmail" v-model="userData.tutore.email" type="email"/>
829 </div>
830 </div>
831 </div>
832
833 <div class="sheet-section">
834 <p class="sheet-title">Recapiti altro genitore</p>
835
836 <div class="form-group-autofit">
837 <div class="form-group-item">
838 <label for="tutore2Telefono">Telefono casa/ufficio (inserisci solo numeri)</label>
839 <input @blur="checkTelefono($event)" class="form-control" id="tutore2Telefono" @keydown="restrictDigitInput" v-model="userData.tutore2.telefono" type="text"/>
840 </div>
841 </div>
842 <div class="form-group-autofit">
843 <div class="form-group-item">
844 <label for="tutore2Cellulare">Cellulare (inserisci solo numeri)</label>
845 <input @blur="checkTelefono($event)" class="form-control" id="tutore2Cellulare" @keydown="restrictDigitInput" v-model="userData.tutore2.cellulare" type="text"/>
846 </div>
847 <div class="form-group-item">
848 <label for="tutore2Email">Email</label>
849 <input @blur="checkEmail($event)" class="form-control" id="tutore2Email" v-model="userData.tutore2.email" type="email"/>
850 </div>
851 </div>
852 </div>
853
854 <div class="sheet-section">
855 <p class="sheet-title">Dati anagrafici del partecipante</p>
856
857 <div class="form-group-autofit">
858 <div class="form-group-item">
859 <label for="firstName">Nome</label>
860 <input @blur="checkEmpty($event)" @change="checkOrderAlreadyPresent()" class="form-control" id="firstName" v-model="userData.firstName" type="text"/>
861 </div>
862 <div class="form-group-item">
863 <label for="lastName">Cognome</label>
864 <input @blur="checkEmpty($event)" @change="checkOrderAlreadyPresent()" class="form-control" id="lastName" v-model="userData.lastName" type="text"/>
865 </div>
866 </div>
867 <div class="form-group-autofit">
868 <div class="form-group-item">
869 <label for="birthPlace">Nato a</label>
870 <input @blur="checkEmpty($event)" class="form-control" id="birthPlace" v-model="userData.birthPlace" type="text"/>
871 </div>
872 <div class="form-group-item">
873 <label for="birthday">Il (gg/mm/aaaa)</label>
874 <input @blur="checkDateLength($event)" class="form-control" id="birthday" @keydown="restrictDateInput" v-model="userData.birthday" type="text"/>
875 </div>
876 <div class="form-group-item">
877 <label>Sesso</label>
878 <div>
879 <div class="custom-control custom-radio custom-control-inline">
880 <label>
881 <input @change="checkRadio('gender')" class="custom-control-input" name="gender" type="radio" value="male" v-model="userData.gender"/>
882 <span class="custom-control-label">
883 <span class="custom-control-label-text">M</span>
884 </span>
885 </label>
886 </div>
887 <div class="custom-control custom-radio custom-control-inline">
888 <label>
889 <input @change="checkRadio('gender')" class="custom-control-input" name="gender" type="radio" value="female" v-model="userData.gender"/>
890 <span class="custom-control-label">
891 <span class="custom-control-label-text">F</span>
892 </span>
893 </label>
894 </div>
895 </div>
896 </div>
897 <div class="form-group-item">
898 <label for="nazionalita">Nazionalità</label>
899 <input @blur="checkEmpty($event)" class="form-control" id="nazionalita" v-model="userData.nazionalita" type="text"/>
900 </div>
901 </div>
902 <div class="form-group-autofit">
903 <div class="form-group-item">
904 <label for="address">Indirizzo</label>
905 <input @blur="checkEmpty($event)" class="form-control" id="address" v-model="userData.billingStreetAddress" type="text"/>
906 </div>
907 </div>
908 <div class="form-group-autofit">
909 <div class="form-group-item">
910 <label for="citta">Città</label>
911 <input @blur="checkEmpty($event)" class="form-control" id="citta" v-model="userData.billingCity" type="text"/>
912 </div>
913 <div class="form-group-item">
914 <label for="cap">CAP</label>
915 <input @blur="checkEmpty($event)" class="form-control" id="cap" v-model="userData.billingPostalCode" type="text"/>
916 </div>
917 <div class="form-group-item">
918 <label for="provincia">Provincia</label>
919 <select @blur="checkSelect($event)" class="form-control" id="provincia" v-model="userData.billingRegionCode">
920 <option v-for="province in italianProvinces" :key="province.code" :value="province.code">{{ province.name }}</option>
921 </select>
922 </div>
923 </div>
924
925 <div class="form-group-autofit">
926 <div class="form-group-item">
927 <label>Problemi di salute del partecipante (patologie/allergie intolleranze alimentari o disturbi di altro genere)</label>
928 <div class="custom-control custom-radio">
929 <label>
930 <input @change="checkRadio('problemiSalute')" class="custom-control-input" name="problemiSalute" type="radio" value="true" v-model="userData.problemiSalute"/>
931 <span class="custom-control-label">
932 <span class="custom-control-label-text">Si, come da certificato medico che sarà inviato</span>
933 </span>
934 </label>
935 </div>
936 <div class="custom-control custom-radio">
937 <label>
938 <input @change="checkRadio('problemiSalute')" class="custom-control-input" name="problemiSalute" type="radio" value="false" v-model="userData.problemiSalute"/>
939 <span class="custom-control-label">
940 <span class="custom-control-label-text">No</span>
941 </span>
942 </label>
943 </div>
944 </div>
945 </div>
946 </div>
947
948 <div class="sheet-section">
949 <p class="sheet-title">Documento di identità dello studente (carta d'identità valida per l'espatrio o passaporto)</p>
950
951 <div class="form-group-autofit">
952 <div class="form-group-item">
953 <label for="tipoDocumento">Tipo di documento</label>
954 <input @blur="checkEmpty($event)" class="form-control" id="tipoDocumento" v-model="userData.tipoDocumento" type="text"/>
955 </div>
956 <div class="form-group-item">
957 <label for="numeroDocumento">Numero</label>
958 <input @blur="checkEmpty($event)" class="form-control" id="numeroDocumento" v-model="userData.numeroDocumento" type="text"/>
959 </div>
960 <div class="form-group-item">
961 <label for="cittadinanzaDocumento">Cittadinanza</label>
962 <input @blur="checkEmpty($event)" class="form-control" id="cittadinanzaDocumento" v-model="userData.cittadinanzaDocumento" type="text"/>
963 </div>
964 </div>
965 <div class="form-group-autofit">
966 <div class="form-group-item">
967 <label for="enteRilascioDocumento">Rilasciato da</label>
968 <input @blur="checkEmpty($event)" class="form-control" id="enteRilascioDocumento" v-model="userData.enteRilascioDocumento" type="text"/>
969 </div>
970 <div class="form-group-item">
971 <label for="dataRilascioDocumento">Data rilascio (gg/mm/aaaa)</label>
972 <input @blur="checkDateLength($event)" class="form-control" id="dataRilascioDocumento" @keydown="restrictDateInput" v-model="userData.dataRilascioDocumento" type="text"/>
973 </div>
974 <div class="form-group-item">
975 <label for="dataScadenzaDocumento">Data di scadenza (gg/mm/aaaa)</label>
976 <input @blur="checkDateLength($event)" class="form-control" id="dataScadenzaDocumento" @keydown="restrictDateInput" v-model="userData.dataScadenzaDocumento" type="text"/>
977 </div>
978 </div>
979
980 <p class="sheet-text strong-aqua">
981 <strong>IMPORTANTE</strong>: verificare bene i dati del partecipante, che saranno utilizzati per effettuare il check-in online. <br>
982 In caso variazione del documento che sarà presentato alla partenza, o di errori rilevati dopo l'invio, è necessario darne tempestiva comunicazione, pena l'impossibilità di imbarco.
983 </p>
984 </div>
985
986 <div class="sheet-section">
987 <div class="form-group-autofit">
988 <div class="form-group-item">
989 <label for="allergie">Allergie da segnalare:</label>
990 <input class="form-control" id="allergie" v-model="userData.allergie" type="text"/>
991 </div>
992 </div>
993 <div class="form-group-autofit">
994 <div class="form-group-item">
995 <label for="inCameraCon">Vorrei essere sistemato in camera con:</label>
996 <input class="form-control" id="inCameraCon" v-model="userData.inCameraCon" type="text"/>
997 </div>
998 </div>
999 </div>
1000
1001 <div class="sheet-section">
1002 <div class="form-group-autofit">
1003 <div class="form-group-item">
1004 <label>Autorizzo la pubblicazione di foto e video di mio/a figlio/a, realizzati durante il programma, sulle pagine social di Zainetto Verde e sul gruppo creato per le famiglie</label>
1005 <div class="custom-control custom-radio">
1006 <label>
1007 <input @change="checkRadio('autorizzazioneFotoFiglio')" class="custom-control-input" name="autorizzazioneFotoFiglio" type="radio" value="true" v-model="userData.autorizzazioneFotoFiglio"/>
1008 <span class="custom-control-label">
1009 <span class="custom-control-label-text">Si</span>
1010 </span>
1011 </label>
1012 </div>
1013 <div class="custom-control custom-radio">
1014 <label>
1015 <input @change="checkRadio('autorizzazioneFotoFiglio')" class="custom-control-input" name="autorizzazioneFotoFiglio" type="radio" value="false" v-model="userData.autorizzazioneFotoFiglio"/>
1016 <span class="custom-control-label">
1017 <span class="custom-control-label-text">No</span>
1018 </span>
1019 </label>
1020 </div>
1021 </div>
1022 </div>
1023 </div>
1024 </div>
1025 </div>
1026 <div class="col-12" v-else>
1027 <p class="text-dark display-5 font-weight-light">Per continuare, seleziona un periodo dalla prima pagina.</p>
1028 </div>
1029
1030 <div class="col-12 mt-4 text-center" v-if="!moduloValid">
1031 <span style="color:red;">Non sono compilati tutti i campi richiesti, vedi campi evidenziati</span>
1032 </div>
1033 <div v-if="orderAlreadyPresent" class="col-12 mt-4 text-center">
1034 <span style="color:red;">Attenzione: questo programma risulta già ordinato dal tuo account per lo stesso partecipante.</span>
1035 </div>
1036
1037 <div class="col-12">
1038 <div class="card void mt-3 mt-lg-5 mb-0">
1039 <div class="card-row">
1040 <div class="autofit-col autofit-col-expand">
1041 <section class="autofit-section text-left">
1042 <button @click="gotoStep('prev')" class="btn btn-outline-dark py-2 px-3 px-lg-4">
1043 Indietro
1044 </button>
1045 </section>
1046 </div>
1047 <div class="autofit-col autofit-col-expand">
1048 <section class="autofit-section text-right">
1049 <button @click="gotoStep('next')" class="btn btn-gradient py-2 px-3 px-lg-4" :disabled="!moduloValid || orderAlreadyPresent">
1050 Avanti
1051 </button>
1052 </section>
1053 </div>
1054 </div>
1055 </div>
1056 </div>
1057 </div>
1058 </div>
1059
1060 <#-- STEP 8: PAGAMENTO -->
1061
1062 <div class="tab-pane fade" id="chose_payment" :class="{'show active': currentStep == 8}" v-if="signedIn" role="tabpanel">
1063 <div class="row">
1064 <div class="d-none d-lg-block col-12 mb-4">
1065 <p class="text-dark display-5 font-weight-light" style="line-height: 3rem !important;">Conferma l'acquisto scegliendo il metodo di pagamento</p>
1066 </div>
1067
1068 <#-- SET ACCONTO -->
1069 <template v-for="(type, index) in selectedPackage.paymentType">
1070 <template v-if="type.type == 'cartaCreditoAcconto' && type.amount != 0">
1071 <p :set="acconto=1"></p>
1072 </template>
1073 </template>
1074
1075 <template v-if="!_.isEmpty(selectedPackage) && acconto != 0">
1076 <div class="col-12 col-xl-6 br-light pr-xl-5">
1077
1078 <template v-for="(type, index) in selectedPackage.paymentType">
1079 <template v-if="type.type == 'cartaCreditoAcconto' && type.amount != 0">
1080 <p class="text-dark h4">Scegli modalità pagamento acconto</p>
1081 <p class="custom-control-label-text pl-0">Importo acconto: {{ type.amount | money }}</p>
1082
1083 </template>
1084 </template>
1085
1086 <#-- ACCONTO -->
1087 <ul class="list-group mb-lg-4">
1088 <template v-for="(type, index) in selectedPackage.paymentType">
1089 <li v-if="type.type == 'cartaCredito' || type.type == 'bonifico' || type.type == 'cartaCreditoAcconto'" :key="'type-' + index" class="list-group-item">
1090 <div class="card-row flex-column flex-lg-row">
1091 <div class="autofit-col autofit-col-expand">
1092 <section class="autofit-section my-auto">
1093 <div class="custom-control custom-radio">
1094 <label>
1095 <input @change="checkRadio('paymentMethod')" class="custom-control-input" type="radio" name="paymentMethod" v-model="selectedPayment" :value="type" />
1096 <span class="custom-control-label">
1097 <span class="custom-control-label-text">
1098 {{ getPaymentLabel(type.type) }}
1099 </span>
1100 </span>
1101 </label>
1102 </div>
1103 </section>
1104 </div>
1105 <div class="autofit-col autofit-col-expand">
1106 <section class="autofit-section text-right my-auto">
1107 <img src="${images_folder}/bonifico.png" height="60" alt="bonifico" v-if="type.type == 'bonifico'">
1108 <img src="${images_folder}/visa-mastercard.png" height="60" alt="visa-mastercard" v-if="type.type == 'cartaCredito'">
1109 <img src="${images_folder}/visa-mastercard.png" height="60" alt="visa-mastercard" v-if="type.type == 'cartaCreditoAcconto'">
1110 </section>
1111 </div>
1112 </div>
1113
1114 <p v-if="type.type == 'bonifico'" class="card-subtitle" style="display: block; margin-left: 1.5rem;">
1115 Intestato a Zainetto Verde srl - IBAN IT42L0100513700000000002639
1116 </p>
1117 </li>
1118 </template>
1119 </ul>
1120
1121
1122 </div>
1123
1124 <#-- SALDO -->
1125 <div class="col-12 col-xl-6 pl-xl-5" v-if="!_.isEmpty(selectedPackage)">
1126 <p class="text-dark h4">Scegli come vorrai pagare il saldo</p>
1127 <p class="custom-control-label-text pl-0">Importo saldo: come da preventivo</p>
1128
1129 <ul class="list-group mb-lg-0">
1130 <li class="list-group-item">
1131 <div class="card-row flex-column flex-lg-row">
1132 <div class="autofit-col autofit-col-expand">
1133 <section class="autofit-section my-auto">
1134 <div class="custom-control custom-radio">
1135 <label>
1136 <input class="custom-control-input" @change="checkRadio('paymentBalanceMethod')" type="radio" name="paymentBalanceMethod" v-model="selectedBalance" :value="{ amount: 0, type: 'rateale-zv' }" />
1137 <span class="custom-control-label">
1138 <span class="custom-control-label-text" style="display: block; margin-left: 1rem;">
1139 bonifico come da accordi con ZV, con saldo prima della partenza
1140 </span>
1141 </span>
1142 </label>
1143 </div>
1144 </section>
1145 </div>
1146 </div>
1147 </li>
1148 <li class="list-group-item">
1149 <div class="card-row flex-column flex-lg-row">
1150 <div class="autofit-col autofit-col-expand">
1151 <section class="autofit-section my-auto">
1152 <div class="custom-control custom-radio">
1153 <label>
1154 <input class="custom-control-input" @change="checkRadio('paymentBalanceMethod')" type="radio" name="paymentBalanceMethod" v-model="selectedBalance" :value="{ amount: 0, type: 'rateale' }" />
1155 <span class="custom-control-label">
1156 <span class="custom-control-label-text" style="display: block; margin-left: 1rem;">
1157 Richiesta di finanziamento con possibilità di scegliere il numero delle rate<br/> (pratica on-line, soggetta ad approvazione della finanziaria)
1158 </span>
1159 </span>
1160 </label>
1161 </div>
1162 </section>
1163 </div>
1164 <div class="autofit-col autofit-col-expand">
1165 <section class="autofit-section text-right my-auto">
1166 <#--
1167 <img src="${images_folder}/rateale.png" height="80" alt="rateale">
1168 -->
1169<img src="/documents/383793/2101965/PagoLight+Pro.svg/a66a8c4e-2422-7684-074c-3478d7862d22?t=1709719439418" height="80" width="120" alt="rateale">
1170 </section>
1171 </div>
1172 </div>
1173 </li>
1174
1175 </ul>
1176 </div>
1177 </template>
1178
1179 <#-- SALDO COMPLETO SENZA ACCONTO -->
1180 <template v-if="!_.isEmpty(selectedPackage) && acconto == 0">
1181 <div class="col-12" v-if="!_.isEmpty(selectedPackage)">
1182 <p class="text-dark h4">Scegli come vorrai pagare il saldo</p>
1183 <p class="custom-control-label-text pl-0">Importo saldo: come da preventivo</p>
1184 <ul class="list-group mb-lg-0">
1185 <template v-if="!_.isEmpty(selectedPackage) && acconto == 0">
1186 <template v-for="(type, index) in selectedPackage.paymentType">
1187 <li v-if="type.type == 'cartaCredito'" :key="'type-' + index" class="list-group-item">
1188 <div class="card-row flex-column flex-lg-row">
1189 <div class="autofit-col autofit-col-expand">
1190 <section class="autofit-section my-auto">
1191 <div class="custom-control custom-radio">
1192 <label>
1193 <input @change="checkRadio('paymentMethod')" class="custom-control-input" type="radio" name="paymentMethod" v-model="selectedPayment" :value="type" />
1194 <span class="custom-control-label">
1195 <span class="custom-control-label-text">
1196 {{ getPaymentLabel(type.type) }}
1197 </span>
1198 </span>
1199 </label>
1200 </div>
1201 </section>
1202 </div>
1203 <div class="autofit-col autofit-col-expand">
1204 <section class="autofit-section text-right my-auto">
1205 <img src="${images_folder}/visa-mastercard.png" height="60" alt="visa-mastercard" v-if="type.type == 'cartaCredito'">
1206 </section>
1207 </div>
1208 </div>
1209 </li>
1210 </template>
1211 </template>
1212
1213 <li class="list-group-item">
1214 <div class="card-row flex-column flex-lg-row">
1215 <div class="autofit-col autofit-col-expand">
1216 <section class="autofit-section my-auto">
1217 <div class="custom-control custom-radio">
1218 <label>
1219 <input @change="checkRadio('paymentBalanceMethod')" class="custom-control-input" type="radio" name="paymentBalanceMethod" v-model="selectedPayment" :value="{ amount: 0, type: 'rateale-zv' }" />
1220 <span class="custom-control-label">
1221 <span class="custom-control-label-text" style="display: block; margin-left: 1rem;">
1222 bonifico come da accordi con ZV, con saldo prima della partenza
1223 </span>
1224 </span>
1225 </label>
1226 </div>
1227 </section>
1228 </div>
1229 </div>
1230 </li>
1231 <li class="list-group-item">
1232 <div class="card-row flex-column flex-lg-row">
1233 <div class="autofit-col autofit-col-expand">
1234 <section class="autofit-section my-auto">
1235 <div class="custom-control custom-radio">
1236 <label>
1237 <input @focus="checkRadio('paymentBalanceMethod')" class="custom-control-input" type="radio" name="paymentBalanceMethod" v-model="selectedPayment" :value="{ amount: 0, type: 'rateale' }" />
1238 <span class="custom-control-label">
1239 <span class="custom-control-label-text" style="display: block; margin-left: 1rem;">
1240 Richiesta di finanziamento con possibilità di scegliere il numero delle rate<br/> (pratica on-line, soggetta ad approvazione della finanziaria)
1241 </span>
1242 </span>
1243 </label>
1244 </div>
1245 </section>
1246 </div>
1247 <div class="autofit-col autofit-col-expand">
1248 <section class="autofit-section text-right my-auto">
1249<#--
1250 <img src="${images_folder}/rateale.png" height="80" alt="rateale">
1251-->
1252<img src="/documents/383793/2101965/PagoLight+Pro.svg/a66a8c4e-2422-7684-074c-3478d7862d22?t=1709719439418" height="80" width="120" alt="rateale">
1253 </section>
1254 </div>
1255 </div>
1256 </li>
1257
1258 </ul>
1259 </div>
1260 </template>
1261
1262
1263
1264 <hr class="col-12">
1265
1266 <div class="col-12 col-lg-7">
1267
1268 <p v-if="!attachments.every(att => att.downloaded)" class="mb-3" id="info_accept" style="color:#FF0000;">È necessario scaricare gli allegati per procedere all'accettazione delle condizioni sottostanti</p>
1269
1270 <div class="autofit-section" id="field_att">
1271 <div v-for="(attachment, index) in attachments" :key="'attachment-' + index">
1272 <div class="card-row mb-4 mb-lg-2">
1273 <div class="autofit-col autofit-col-expand">
1274 <section class="autofit-section">
1275 <div class="custom-control custom-checkbox">
1276 <label>
1277 <#-- :disabled="!attachments.every(att => att.downloaded)" -->
1278 <input v-model="policy['condition' + sum(index, 1)]" :id="'condition_' + sum(index, 1)" @change="checkPolicy($event)" class="custom-control-input" type="checkbox" :disabled="!attachments.every(att => att.downloaded)">
1279 <span class="custom-control-label">
1280 <span class="custom-control-label-text">
1281 {{ attachment.title }}
1282 <template v-if="attachment.mandatory">*</template>
1283 </span>
1284 </span>
1285 </label>
1286 </div>
1287 </section>
1288 </div>
1289 <div class="autofit-col">
1290 <section class="autofit-section">
1291 <button v-if="attachment.downloaded" @click="downloadAttachment(attachment)" class="btn btn-link text-aqua p-0 mb-0">
1292 documento scaricato
1293 <i class="fas fa-check ml-1"></i>
1294 </button>
1295 <button v-else @click="downloadAttachment(attachment)" class="btn btn-link p-0 mb-0" style="color:red;">
1296 Scarica il documento
1297 <i class="fas fa-download ml-1"></i>
1298 </button>
1299 </section>
1300 </div>
1301 </div>
1302 <div class="card-row mb-4 mb-lg-2" v-if="index==0">
1303 <div class="autofit-col autofit-col-expand">
1304 <section class="autofit-section">
1305 <div class="custom-control custom-checkbox">
1306 <label>
1307 <input v-model="doppiocheck" class="custom-control-input" id="condition_x" type="checkbox" @change="checkPolicy($event)" :disabled="(!attachments.every(att => att.downloaded))">
1308 <span class="custom-control-label">
1309 <span class="custom-control-label-text">
1310 Per espressa accettazione, ex art. 1341 e 1342 c.c., delle condizioni generali richiamate
1311 <template v-if="attachment.mandatory">*</template>
1312 </span>
1313 </span>
1314 </label>
1315 </div>
1316 </section>
1317 </div>
1318 </div>
1319 </div>
1320 </div>
1321
1322 <p v-if="!_.isEmpty(selectedPackage) && orderResult != ''" class="h4">{{ orderResult }}</p>
1323 </div>
1324
1325 <template v-if="!_.isEmpty(selectedPackage) && acconto == 0">
1326 <div v-if="_.isEmpty(selectedPayment) || !validPolicy" style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;" class="col-12 text-center py-3 mt-3 mt-lg-5">
1327 <p style="color:red;" class="m-0">non sono flaggati tutti i campi richiesti, vedi campi evidenziati in rosso</p>
1328 </div>
1329 </template>
1330 <template v-else>
1331 <div v-if="_.isEmpty(selectedPayment) || !validPolicy || _.isEmpty(selectedBalance)" style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;" class="col-12 text-center py-3 mt-3 mt-lg-5">
1332 <p style="color:red;" class="m-0">non sono flaggati tutti i campi richiesti, vedi campi evidenziati in rosso</p>
1333 </div>
1334 </template>
1335
1336 <div class="col-12">
1337 <div class="card void mt-3 mt-lg-5 mb-0">
1338 <div class="card-row">
1339 <div class="autofit-col autofit-col-expand">
1340 <section class="autofit-section text-left">
1341 <button @click="gotoStep('prev')" class="btn btn-outline-dark py-2 px-3 px-lg-4">
1342 Indietro
1343 </button>
1344 </section>
1345 </div>
1346
1347 <div class="autofit-col autofit-col-expand" v-if="!_.isEmpty(selectedPackage) && acconto == 0">
1348 <section class="autofit-section text-right">
1349 <#-- <button v-if="checkOrderAlreadyPresent() && orderAlreadyPresent" class="btn btn-gradient py-2 px-3 px-lg-4" disabled>
1350 Già ordinato
1351 </button> -->
1352 <button @click="!_.isEmpty(selectedPayment) ? createOrderAndPaymentUrl() : ''" class="btn btn-gradient py-2 px-3 px-lg-4" :disabled="_.isEmpty(selectedPayment) || !validPolicy">
1353 Pagamento
1354 </button>
1355 </section>
1356 </div>
1357
1358 <div class="autofit-col autofit-col-expand" v-else>
1359 <section class="autofit-section text-right">
1360 <#-- <button v-if="orderAlreadyPresent" class="btn btn-gradient py-2 px-3 px-lg-4" disabled>
1361 Già ordinato
1362 </button> -->
1363 <button @click="!_.isEmpty(selectedPayment) && !_.isEmpty(selectedBalance) ? createOrderAndPaymentUrl() : ''" class="btn btn-gradient py-2 px-3 px-lg-4" :disabled="_.isEmpty(selectedPayment) || !validPolicy || _.isEmpty(selectedBalance)">
1364 Pagamento
1365 </button>
1366 </section>
1367 </div>
1368
1369 </div>
1370 </div>
1371 </div>
1372 </div>
1373 </div>
1374
1375 <#-- STEP 9: RINGRAZIAMENTO -->
1376 <div class="tab-pane fade" :class="{'show active': currentStep == 9}" v-if="signedIn" role="tabpanel">
1377 <div class="row">
1378 <div class="d-none d-lg-block col-12 mb-4">
1379 <p class="text-dark display-5 font-weight-light">Grazie per la tua prenotazione</p>
1380 </div>
1381
1382 <div class="col-12 col-lg-7">
1383 <p class="h4 text-dark font-weight-regular mt-5">
1384 Grazie per aver prenotato un pacchetto Zainetto Verde!<br>
1385 Ti è stata inviata una mail di riepilogo e potrai trovare il riepilogo del tuo acquisto anche nella sezione dei tuoi viaggi.
1386 </p>
1387 </div>
1388
1389 <div class="col-12 col-lg-5">
1390 <div class="d-flex h-100 align-items-end justify-content-center">
1391 <button @click="redirectParent('/i-miei-viaggi')" class="btn btn-gradient btn-lg mt-4 mt-lg-0">Vai ai tuoi viaggi</button>
1392 </div>
1393 </div>
1394 </div>
1395 </div>
1396 </div>
1397 </div>
1398 </div>
1399 </div>
1400 </div>
1401</#macro>
1402
1403<#assign
1404 DLAppLocalService = serviceLocator.findService("com.liferay.document.library.kernel.service.DLAppLocalService")
1405 JALS = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")
1406 suggestoMkspAPI = serviceLocator.findService("eu.suggesto.suggestogui.service.SuggestoGuiLocalService")
1407 productServiceAPI = serviceLocator.findService("eu.suggesto.d40.builder.d40.service.ProductLocalService")
1408 saxReaderUtil = staticUtil["com.liferay.portal.kernel.xml.SAXReaderUtil"]
1409
1410 images_folder = themeDisplay.getPathThemeImages()
1411 icons_folder = images_folder + "/icons"
1412 contentId = result.getRequestStringParameter("contentId")
1413 defLocale = localeUtil.fromLanguageId("it_IT")
1414 image = "https://via.placeholder.com/300"
1415 dateSoggiorno = []
1416 packages = []
1417 name = "Placeholder"
1418 prezzo_base = 0
1419 sCatSistemazione = ""
1420/>
1421
1422<#if contentId?has_content>
1423 <#assign
1424 packages = getPackagesByItemId(groupId, groupId, contentId)
1425 article = JALS.getArticle(themeDisplay.getSiteGroupId(), contentId)
1426 document = saxReaderUtil.read(article.getContent())
1427 docTitle=article.getTitle(defLocale)
1428
1429 rootElement = document.getRootElement()
1430 groupedCategories = suggestoMkspAPI.getGroupedArticleCategories(groupId, contentId, locale, defLocale)
1431
1432 xPathDate = saxReaderUtil.createXPath("dynamic-element[@name='data_inizio']")
1433 xPathImage = saxReaderUtil.createXPath("dynamic-element[@name='anteprima']")
1434 xPathName = saxReaderUtil.createXPath("dynamic-element[@name='nome_scuola']/dynamic-content[@language-id='" + themeDisplay.getLocale() + "']")
1435 xPathPrezzo = saxReaderUtil.createXPath("dynamic-element[@name='prezzo_base']/dynamic-content[@language-id='" + themeDisplay.getLocale() + "']")
1436 />
1437
1438 <#if (groupedCategories.length() > 0) >
1439 <#list 0..groupedCategories.length()-1 as i>
1440 <#assign
1441 gc = groupedCategories.getJSONObject(i)
1442 gcCat = gc.getJSONArray("categories")
1443 vacabularyName = gc.getString("vocabularyName")
1444 />
1445
1446 <#if vacabularyName == "Tipo di sistemazione">
1447 <#list 0..gcCat.length()-1 as y>
1448 <#assign
1449 sCat = gcCat.getJSONObject(y)
1450 sCatId = sCat.getString("categoryId")
1451 sCatSistemazione = sCat.getString("name")
1452 sCatIcon = sCat.getString("icon")
1453 />
1454 </#list>
1455 </#if>
1456 </#list>
1457 </#if>
1458
1459 <#if xPathDate.selectNodes(rootElement)??>
1460 <#list xPathDate.selectNodes(rootElement) as node>
1461 <#assign
1462 dataInizio = node.selectSingleNode("dynamic-content[@language-id='" + themeDisplay.getLocale() + "']").getStringValue()?replace("-", "/")
1463 dataFine = node.selectSingleNode("dynamic-element[@name='data_fine']/dynamic-content[@language-id='" + themeDisplay.getLocale() + "']").getStringValue()?replace("-", "/")
1464 dateSoggiorno += [
1465 {
1466 "dataInizio": "${dataInizio}",
1467 "dataFine": "${dataFine}"
1468 }
1469 ]
1470 />
1471 </#list>
1472 </#if>
1473
1474 <#if xPathImage.selectSingleNode(rootElement)??>
1475 <#compress>
1476 <#assign tmpImage = xPathImage.selectSingleNode(rootElement).getStringValue()?trim>
1477 </#compress>
1478
1479 <#if tmpImage?has_content>
1480 <#assign
1481 image = tmpImage
1482 jsonField = jsonFactoryUtil.createJSONObject(image)
1483 fileEntry = DLAppLocalService.getFileEntryByUuidAndGroupId(jsonField.uuid, groupId)
1484 image = "/documents/" + jsonField.groupId + "/" + fileEntry.folderId + "/" + jsonField.title + "/" + jsonField.uuid
1485 />
1486 </#if>
1487 </#if>
1488
1489 <#if xPathName.selectSingleNode(rootElement)??>
1490 <#assign name = xPathName.selectSingleNode(rootElement).getStringValue()?trim?capitalize>
1491 </#if>
1492
1493 <#if xPathPrezzo.selectSingleNode(rootElement)??>
1494 <#assign prezzo_base = xPathPrezzo.selectSingleNode(rootElement).getStringValue()?trim>
1495 </#if>
1496</#if>
1497
1498<@printContent />
1499
1500<script>
1501 document.addEventListener("DOMContentLoaded", function (){
1502 if(!Liferay.ThemeDisplay.getUserEmailAddress().includes("@suggesto.")){
1503 Vue.config.devtools = false;
1504 }
1505
1506 Vue.filter("money", function(value){
1507 var formatter = new Intl.NumberFormat('it-IT', {
1508 style: 'currency',
1509 currency: 'EUR',
1510 });
1511 if(typeof value!="undefined" && value!="" && value!="0")
1512 return formatter.format(parseFloat(value));
1513 else
1514 return "";
1515 });
1516
1517 var pay = new Vue({
1518 el: "#pay",
1519 data: {
1520 isDev: Liferay.ThemeDisplay.getUserEmailAddress().includes("@suggesto") && !Liferay.ThemeDisplay.getUserEmailAddress().includes("studente"),
1521 loading: true,
1522 favourite: false,
1523 contentId: "${contentId}",
1524 image: "${getPrefix(htmlUtil.escape(image), 300, '')}",
1525 currentStep: 1,
1526 totalSteps: 0,
1527 name: "${name}",
1528 signedIn: Liferay.ThemeDisplay.isSignedIn(),
1529 groupId: Liferay.ThemeDisplay.getScopeGroupId(),
1530 userMail: Liferay.ThemeDisplay.getUserEmailAddress(),
1531 defaultLanguage: "it",
1532 defaultCountryId: "8",
1533 packagePrice: 0,
1534 packageDiscount: 0,
1535 acconto: 0,
1536 selectedPackage: {},
1537 selectedAirport: {},
1538 selectedAccomodation: {},
1539 selectedServices: [],
1540 selectedPayment: {},
1541 selectedBalance: {},
1542 paymentLink: "#",
1543 hasAccompagnatorePermission: false,
1544 voucher: "",
1545 voucherDiscount: 0,
1546 voucherValid: false,
1547 oid: "",
1548 packages: [],
1549 attachments: [],
1550 doppiocheck:false,
1551 sameUserOrders:[],
1552 orderAlreadyPresent:false,
1553 calendar: {
1554 ready: false,
1555 initialPage: {
1556 month: null,
1557 year: null
1558 },
1559 periodoSelected: {
1560 start: null,
1561 end: null
1562 },
1563 dataSelected: null,
1564 dataInizio: null,
1565 dataFine: null,
1566 attributes: []
1567 },
1568 policy: {
1569 <#list allegati as allegato>
1570 condition${allegato?counter}: false,
1571 </#list>
1572 },
1573 countryList: [],
1574 regionList: [],
1575 userData: {},
1576 orderResult: "",
1577 msgCodiceFiscale:"",
1578 italianProvinces: [
1579 { code: 'AG', name: 'Agrigento' },
1580 { code: 'AL', name: 'Alessandria' },
1581 { code: 'AN', name: 'Ancona' },
1582 { code: 'AO', name: 'Aosta' },
1583 { code: 'AR', name: 'Arezzo' },
1584 { code: 'AP', name: 'Ascoli Piceno' },
1585 { code: 'AT', name: 'Asti' },
1586 { code: 'AV', name: 'Avellino' },
1587 { code: 'BA', name: 'Bari' },
1588 { code: 'BT', name: 'Barletta-Andria-Trani' },
1589 { code: 'BL', name: 'Belluno' },
1590 { code: 'BN', name: 'Benevento' },
1591 { code: 'BG', name: 'Bergamo' },
1592 { code: 'BI', name: 'Biella' },
1593 { code: 'BO', name: 'Bologna' },
1594 { code: 'BZ', name: 'Bolzano' },
1595 { code: 'BS', name: 'Brescia' },
1596 { code: 'BR', name: 'Brindisi' },
1597 { code: 'CA', name: 'Cagliari' },
1598 { code: 'CL', name: 'Caltanissetta' },
1599 { code: 'CB', name: 'Campobasso' },
1600 { code: 'CI', name: 'Carbonia-Iglesias' },
1601 { code: 'CE', name: 'Caserta' },
1602 { code: 'CT', name: 'Catania' },
1603 { code: 'CZ', name: 'Catanzaro' },
1604 { code: 'CH', name: 'Chieti' },
1605 { code: 'CO', name: 'Como' },
1606 { code: 'CS', name: 'Cosenza' },
1607 { code: 'CR', name: 'Cremona' },
1608 { code: 'KR', name: 'Crotone' },
1609 { code: 'CN', name: 'Cuneo' },
1610 { code: 'EN', name: 'Enna' },
1611 { code: 'FM', name: 'Fermo' },
1612 { code: 'FE', name: 'Ferrara' },
1613 { code: 'FI', name: 'Firenze' },
1614 { code: 'FG', name: 'Foggia' },
1615 { code: 'FC', name: 'Forlì-Cesena' },
1616 { code: 'FR', name: 'Frosinone' },
1617 { code: 'GE', name: 'Genova' },
1618 { code: 'GO', name: 'Gorizia' },
1619 { code: 'GR', name: 'Grosseto' },
1620 { code: 'IM', name: 'Imperia' },
1621 { code: 'IS', name: 'Isernia' },
1622 { code: 'SP', name: 'La Spezia' },
1623 { code: 'AQ', name: "L'Aquila" },
1624 { code: 'LT', name: 'Latina' },
1625 { code: 'LE', name: 'Lecce' },
1626 { code: 'LC', name: 'Lecco' },
1627 { code: 'LI', name: 'Livorno' },
1628 { code: 'LO', name: 'Lodi' },
1629 { code: 'LU', name: 'Lucca' },
1630 { code: 'MC', name: 'Macerata' },
1631 { code: 'MN', name: 'Mantova' },
1632 { code: 'MS', name: 'Massa-Carrara' },
1633 { code: 'MT', name: 'Matera' },
1634 { code: 'VS', name: 'Medio Campidano' },
1635 { code: 'ME', name: 'Messina' },
1636 { code: 'MI', name: 'Milano' },
1637 { code: 'MO', name: 'Modena' },
1638 { code: 'MB', name: 'Monza e della Brianza' },
1639 { code: 'NA', name: 'Napoli' },
1640 { code: 'NO', name: 'Novara' },
1641 { code: 'NU', name: 'Nuoro' },
1642 { code: 'OG', name: 'Ogliastra' },
1643 { code: 'OT', name: 'Olbia-Tempio' },
1644 { code: 'OR', name: 'Oristano' },
1645 { code: 'PD', name: 'Padova' },
1646 { code: 'PA', name: 'Palermo' },
1647 { code: 'PR', name: 'Parma' },
1648 { code: 'PV', name: 'Pavia' },
1649 { code: 'PG', name: 'Perugia' },
1650 { code: 'PU', name: 'Pesaro e Urbino' },
1651 { code: 'PE', name: 'Pescara' },
1652 { code: 'PC', name: 'Piacenza' },
1653 { code: 'PI', name: 'Pisa' },
1654 { code: 'PT', name: 'Pistoia' },
1655 { code: 'PN', name: 'Pordenone' },
1656 { code: 'PZ', name: 'Potenza' },
1657 { code: 'PO', name: 'Prato' },
1658 { code: 'RG', name: 'Ragusa' },
1659 { code: 'RA', name: 'Ravenna' },
1660 { code: 'RC', name: 'Reggio Calabria' },
1661 { code: 'RE', name: 'Reggio Emilia' },
1662 { code: 'RI', name: 'Rieti' },
1663 { code: 'RN', name: 'Rimini' },
1664 { code: 'RM', name: 'Roma' },
1665 { code: 'RO', name: 'Rovigo' },
1666 { code: 'SA', name: 'Salerno' },
1667 { code: 'SS', name: 'Sassari' },
1668 { code: 'SV', name: 'Savona' },
1669 { code: 'SI', name: 'Siena' },
1670 { code: 'SR', name: 'Siracusa' },
1671 { code: 'SO', name: 'Sondrio' },
1672 { code: 'TA', name: 'Taranto' },
1673 { code: 'TE', name: 'Teramo' },
1674 { code: 'TR', name: 'Terni' },
1675 { code: 'TO', name: 'Torino' },
1676 { code: 'TP', name: 'Trapani' },
1677 { code: 'TN', name: 'Trento' },
1678 { code: 'TV', name: 'Treviso' },
1679 { code: 'TS', name: 'Trieste' },
1680 { code: 'UD', name: 'Udine' },
1681 { code: 'VA', name: 'Varese' },
1682 { code: 'VE', name: 'Venezia' },
1683 { code: 'VB', name: 'Verbano-Cusio-Ossola' },
1684 { code: 'VC', name: 'Vercelli' },
1685 { code: 'VR', name: 'Verona' },
1686 { code: 'VV', name: 'Vibo Valentia' },
1687 { code: 'VI', name: 'Vicenza' },
1688 { code: 'VT', name: 'Viterbo' }
1689 ],
1690 sendingMessageError:""
1691 },
1692 created(){
1693 var that = this;
1694
1695 moment.locale(navigator.language.split("-")[0]);
1696
1697 window.addEventListener("keyup", function(e){
1698 if(e.which == 27){
1699 that.closeParentModal("#pay-modal");
1700 }
1701 });
1702
1703 if(this.signedIn){
1704 if(${hasAccompagnatorePerm?c}){
1705 this.hasAccompagnatorePermission = true;
1706 console.log("user has permission");
1707 }else{
1708 console.log("user doesn't have permission");
1709 }
1710 }
1711
1712 this.getPackages();
1713 this.initCalendar();
1714 this.setAttachments();
1715
1716
1717 //$('#payment_step input').each(function(){
1718 // $(this).css({"border":"1px solid orange"});
1719 //});
1720
1721 },
1722 mounted(){
1723 window.addEventListener("message", this.getExternalData.bind(this));
1724
1725 if(this.signedIn){
1726 this.userId = Liferay.ThemeDisplay.getUserId();
1727 this.checkFavourite();
1728 this.getUserData();
1729
1730 this.totalSteps = 9;
1731 }else{
1732 //this.getCountryList();
1733 this.totalSteps = 8;
1734 }
1735
1736 console.log("total steps: " + this.totalSteps);
1737
1738 this.calendar.ready = true;
1739 this.getProgressData();
1740 this.getOrderStatus();
1741 this.loading = false;
1742 },
1743 computed: {
1744 totalPrice: function(){
1745 return this.selectedServices.reduce(function(total, item){
1746 return Number(total) + Number(item.price);
1747 }, Number(this.packagePrice) - Number(this.packageDiscount) + Number(this.selectedAirport.price || 0) + Number(this.selectedAccomodation.price || 0));
1748 },
1749 totalPriceWithVoucher: function(){
1750 return this.selectedServices.reduce(function(total, item){
1751 return Number(total) + Number(item.price);
1752 }, Number(this.packagePrice) - Number(this.packageDiscount) + Number(this.selectedAirport.price || 0) + Number(this.selectedAccomodation.price || 0) - Number(this.voucherDiscount || 0));
1753 },
1754 validPolicy: function(){
1755 var valid = false;
1756
1757 if(
1758 <#list allegati as allegato>
1759 <#assign stringSelector = "dynamic-element[@name='mandatory']/dynamic-content[@language-id = '" + themeDisplay.getLocale() + "']">
1760 <#assign xPathSelector = saxReaderUtil.createXPath(stringSelector)>
1761 <#if xPathSelector.selectSingleNode(allegato)??>
1762 <#assign mandatory = xPathSelector.selectSingleNode(allegato).getData()>
1763 </#if>
1764
1765 <#if mandatory == "true">
1766 <#if !allegato?is_first> && </#if>
1767 this.policy.condition${allegato?counter}
1768 </#if>
1769 </#list>
1770 ){
1771 valid = true;
1772 }
1773 console.log("doppiocheck:"+ this.doppiocheck);
1774 if(this.doppiocheck==false)
1775 return false;
1776 return valid;
1777 },
1778 minimumValid: function(){
1779 var valid = true;
1780
1781 if(this.userData != null){
1782 if(!this.userData.hasOwnProperty("firstName") || typeof this.userData["firstName"] !== "string" || this.userData["firstName"].length == 0){
1783 valid = false;
1784 }
1785 if(!this.userData.hasOwnProperty("lastName") || typeof this.userData["lastName"] !== "string" || this.userData["lastName"].length == 0){
1786 valid = false;
1787 }
1788 if(this.userMail == ""){
1789 valid = false;
1790 }
1791 }else{
1792 valid = false;
1793 }
1794
1795 return valid;
1796 },
1797 moduloValid: function(){
1798 var valid = true;
1799
1800 if(this.userData != {}){
1801 // Tutore/i
1802
1803 if(_.has(this.userData, "tutore.firstName")){
1804 if(typeof this.userData.tutore.firstName !== "string" || this.userData.tutore.firstName.length == 0){
1805 valid = false
1806 }
1807 }else{
1808 valid = false;
1809 }
1810
1811 if(_.has(this.userData, "tutore.lastName")){
1812 if(typeof this.userData.tutore.lastName !== "string" || this.userData.tutore.lastName.length == 0){
1813 valid = false
1814 }
1815 }else{
1816 valid = false;
1817 }
1818
1819 if(_.has(this.userData, "tutore.birthdayPlace")){
1820 if(typeof this.userData.tutore.birthdayPlace !== "string" || this.userData.tutore.birthdayPlace.length == 0){
1821 valid = false
1822 }
1823 }else{
1824 valid = false;
1825 }
1826
1827 if(_.has(this.userData, "tutore.birthday")){
1828 if(typeof this.userData.tutore.birthday !== "string" || this.userData.tutore.birthday.length != 10 || ! this.dateFormat(this.userData.tutore.birthday) ){
1829 valid = false
1830 }
1831 }else{
1832 valid = false;
1833 }
1834
1835 if(_.has(this.userData, "tutore.gender")){
1836 if(typeof this.userData.tutore.gender !== "string" || this.userData.tutore.gender.length == 0){
1837 valid = false
1838 }
1839 }else{
1840 valid = false;
1841 }
1842
1843 if(_.has(this.userData, "tutore.nazione")){
1844 if(typeof this.userData.tutore.nazione !== "string" || this.userData.tutore.nazione.length == 0){
1845 valid = false
1846 }
1847 }else{
1848 valid = false;
1849 }
1850
1851 if(_.has(this.userData, "tutore.address")){
1852 if(typeof this.userData.tutore.address !== "string" || this.userData.tutore.address.length == 0){
1853 valid = false
1854 }
1855 }else{
1856 valid = false;
1857 }
1858
1859 if(_.has(this.userData, "tutore.citta")){
1860 if(typeof this.userData.tutore.citta !== "string" || this.userData.tutore.citta.length == 0){
1861 valid = false
1862 }
1863 }else{
1864 valid = false;
1865 }
1866
1867 if(_.has(this.userData, "tutore.cap")){
1868 if(typeof this.userData.tutore.cap !== "string" || this.userData.tutore.cap.length == 0){
1869 valid = false
1870 }
1871 }else{
1872 valid = false;
1873 }
1874
1875 if(_.has(this.userData, "tutore.provincia")){
1876 if(typeof this.userData.tutore.provincia !== "string" || this.userData.tutore.provincia.length == 0){
1877 valid = false
1878 }
1879 }else{
1880 valid = false;
1881 }
1882
1883 if(_.has(this.userData, "tutore.codiceFiscale")){
1884 if(typeof this.userData.tutore.codiceFiscale !== "string" || this.userData.tutore.codiceFiscale.length == 0 ||
1885 this.controllaCF(this.userData.tutore.codiceFiscale).length!=0){
1886 valid = false
1887 }
1888 else
1889 this.userData.tutore.codiceFiscale=this.userData.tutore.codiceFiscale.toUpperCase();
1890 }else{
1891 valid = false;
1892 }
1893
1894 if(_.has(this.userData, "tutore.cellulare")){
1895 if(typeof this.userData.tutore.cellulare !== "string" || this.userData.tutore.cellulare.length == 0 ||
1896 ((/^[0-9]+$/.test(this.userData.tutore.cellulare))==false )
1897
1898 ){
1899 valid = false
1900 }
1901 }else{
1902 valid = false;
1903 }
1904
1905 if(_.has(this.userData, "tutore.email")){
1906 if(typeof this.userData.tutore.email !== "string" || this.userData.tutore.email.length == 0){
1907 valid = false
1908 }else{
1909 if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(this.userData.tutore.email)) {
1910 } else {
1911 valid = false;
1912 }
1913 }
1914 }else{
1915 valid = false;
1916 }
1917
1918 //Tutore2
1919 if(_.has(this.userData, "tutore2.cellulare")){
1920 if(typeof this.userData.tutore2.cellulare !== "string" || this.userData.tutore2.cellulare.length == 0 ||
1921 ((/^[0-9]+$/.test(this.userData.tutore2.cellulare))==false )
1922 ){
1923 valid = false
1924 }
1925 }else{
1926 valid = false;
1927 }
1928
1929 if(_.has(this.userData, "tutore2.email")){
1930 if(typeof this.userData.tutore2.email !== "string" || this.userData.tutore2.email.length == 0){
1931 valid = false
1932 }else{
1933 if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(this.userData.tutore2.email)) {
1934 } else {
1935 valid = false;
1936 }
1937 }
1938 }else{
1939 valid = false;
1940 }
1941
1942 if(_.has(this.userData, "tutore2.telefono")){
1943 if(typeof this.userData.tutore2.telefono !== "string" || this.userData.tutore2.telefono.length == 0 ||
1944 ((/^[0-9]+$/.test(this.userData.tutore2.telefono))==false )
1945 ){
1946 valid = false
1947 }
1948 }else{
1949 valid = false;
1950 }
1951
1952 //Studente
1953 if(_.has(this.userData, "firstName")){
1954 if(typeof this.userData.firstName !== "string" || this.userData.firstName.length == 0){
1955 valid = false
1956 }
1957 }else{
1958 valid = false;
1959 }
1960
1961 if(_.has(this.userData, "lastName")){
1962 if(typeof this.userData.lastName !== "string" || this.userData.lastName.length == 0){
1963 valid = false
1964 }
1965 }else{
1966 valid = false;
1967 }
1968
1969 if(_.has(this.userData, "birthPlace")){
1970 if(typeof this.userData.birthPlace !== "string" || this.userData.birthPlace.length == 0){
1971 valid = false
1972 }
1973 }else{
1974 valid = false;
1975 }
1976
1977 if(_.has(this.userData, "birthday")){
1978 if(typeof this.userData.birthday !== "string" || this.userData.birthday.length != 10 || ! this.dateFormat(this.userData.birthday) ){
1979 valid = false
1980 }
1981 }else{
1982 valid = false;
1983 }
1984
1985 if(_.has(this.userData, "gender")){
1986 if(typeof this.userData.gender !== "string" || this.userData.gender.length == 0){
1987 valid = false
1988 }
1989 }else{
1990 valid = false;
1991 }
1992
1993 if(_.has(this.userData, "nazionalita")){
1994 if(typeof this.userData.nazionalita !== "string" || this.userData.nazionalita.length == 0){
1995 valid = false
1996 }
1997 }else{
1998 valid = false;
1999 }
2000
2001 if(_.has(this.userData, "billingStreetAddress")){
2002 if(typeof this.userData.billingStreetAddress !== "string" || this.userData.billingStreetAddress.length == 0){
2003 valid = false
2004 }
2005 }else{
2006 valid = false;
2007 }
2008
2009 if(_.has(this.userData, "billingCity")){
2010 if(typeof this.userData.billingCity !== "string" || this.userData.billingCity.length == 0){
2011 valid = false
2012 }
2013 }else{
2014 valid = false;
2015 }
2016
2017 if(_.has(this.userData, "billingPostalCode")){
2018 if(typeof this.userData.billingPostalCode !== "string" || this.userData.billingPostalCode.length == 0){
2019 valid = false
2020 }
2021 }else{
2022 valid = false;
2023 }
2024
2025 if(_.has(this.userData, "billingRegionCode")){
2026 if(typeof this.userData.billingRegionCode !== "string" || this.userData.billingRegionCode.length == 0){
2027 valid = false
2028 }
2029 }else{
2030 valid = false;
2031 }
2032
2033 if(_.has(this.userData, "problemiSalute")){
2034 if(typeof this.userData.problemiSalute !== "string" || this.userData.problemiSalute.length == 0){
2035 valid = false
2036 }
2037 }else{
2038 valid = false;
2039 }
2040
2041 if(_.has(this.userData, "tipoDocumento")){
2042 if(typeof this.userData.tipoDocumento !== "string" || this.userData.tipoDocumento.length == 0){
2043 valid = false
2044 }
2045 }else{
2046 valid = false;
2047 }
2048
2049 if(_.has(this.userData, "numeroDocumento")){
2050 if(typeof this.userData.numeroDocumento !== "string" || this.userData.numeroDocumento.length == 0){
2051 valid = false
2052 }
2053 }else{
2054 valid = false;
2055 }
2056
2057 if(_.has(this.userData, "cittadinanzaDocumento")){
2058 if(typeof this.userData.cittadinanzaDocumento !== "string" || this.userData.cittadinanzaDocumento.length == 0){
2059 valid = false
2060 }
2061 }else{
2062 valid = false;
2063 }
2064
2065 if(_.has(this.userData, "enteRilascioDocumento")){
2066 if(typeof this.userData.enteRilascioDocumento !== "string" || this.userData.enteRilascioDocumento.length == 0){
2067 valid = false
2068 }
2069 }else{
2070 valid = false;
2071 }
2072
2073 if(_.has(this.userData, "dataRilascioDocumento")){
2074 if(typeof this.userData.dataRilascioDocumento !== "string" || this.userData.dataRilascioDocumento.length != 10 || ! this.dateFormat(this.userData.dataRilascioDocumento) ){
2075 valid = false
2076 }
2077 }else{
2078 valid = false;
2079 }
2080
2081 if(_.has(this.userData, "dataScadenzaDocumento")){
2082 if(typeof this.userData.dataScadenzaDocumento !== "string" || this.userData.dataScadenzaDocumento.length != 10 || ! this.dateFormat(this.userData.dataScadenzaDocumento) ){
2083 valid = false
2084 }
2085 }else{
2086 valid = false;
2087 }
2088
2089 if(_.has(this.userData, "autorizzazioneFotoFiglio")){
2090 if(typeof this.userData.autorizzazioneFotoFiglio !== "string" || this.userData.autorizzazioneFotoFiglio.length == 0){
2091 valid = false
2092 }
2093 }else{
2094 valid = false;
2095 }
2096 }else{
2097 valid = false;
2098 }
2099
2100 return valid;
2101 }
2102 },
2103 methods: {
2104 sum: function(num1, num2){
2105 return Number(num1 + num2);
2106 },
2107 openParentModal: function(id){
2108 window.parent.$(id).modal("show");
2109 },
2110 sendRequestMessage: function() {
2111 var that=this;
2112 that.sendingMessageError="";
2113 var portletNamespace="<@portlet.namespace />";
2114 var requestInfo= {
2115 email: this.userMail,
2116 message: "",
2117 firstName:this.userData.firstName,
2118 lastName:this.userData.lastName,
2119 parameters: {
2120 firstName: this.userData.firstName,
2121 lastName: this.userData.lastName,
2122 phone: this.userData.phone,
2123 program:"",
2124 age: "",
2125 destination: "",
2126 startFrom: "",
2127 duration: "",
2128 fromPageName: "${docTitle?js_string}",
2129 fromPageUrl: window.top.location.href,
2130 },
2131 token: "",
2132 component:"PreventivoProgrammi",
2133 emailParams: {}
2134 };
2135 this.buildMessage(requestInfo);
2136 console.log("sendRequestMessage:",requestInfo);
2137
2138 function cb(status,msg) {
2139 console.log("cb:",status);
2140 if(status==true) {
2141 var nomeEvento="vacanza_studio";
2142 console.log("sending event invio_preventivo", nomeEvento);
2143 that.addEvent('invio_preventivo',nomeEvento);
2144 that.gotoStep('next');
2145 }
2146 else {
2147 that.sendingMessageError="error durante l'invio del preventivo";
2148 }
2149 }
2150 oneInstanceSendRequest(requestInfo,cb);
2151 },
2152 buildMessage: function (requestInfo) {
2153
2154 var that=this;
2155 var msg="";
2156 var rowNomeScuola="";
2157 var rowAcco="";
2158 var rowAirport="";
2159 var rowPackagePrice="";
2160 var rowTotalPrice="";
2161 var rowPackageDiscount="";
2162 var rowsServices=[];
2163 var szRowsServices="";
2164 if(typeof this.selectedPackage=="undefined") {
2165 return;
2166 }
2167 console.log("build message");
2168 var docTitle="${docTitle?js_string}";
2169 if(typeof this.selectedPackage.nome_scuola!="undefined") {
2170 var dtStart=new Date(this.selectedPackage.startDate);
2171 var dtEnd=new Date(this.selectedPackage.endDate);
2172 var szStart=dtStart.getDate() +"-"+(dtStart.getMonth()+1)+"-"+dtStart.getFullYear();
2173 var szEnd=dtEnd.getDate() +"-"+(dtEnd.getMonth()+1)+"-"+dtEnd.getFullYear();
2174 rowNomeScuola="<h2>"+this.selectedPackage.nome_scuola +" dal " +szStart+ " al "+szEnd+"</h2>";
2175 }
2176 if(typeof this.selectedAccomodation!="undefined" && this.selectedAccomodation.lodgingType!="undefined" && this.selectedAccomodation.price!="undefined" )
2177 rowAcco="<tr>"+ "<td>"+this.selectedAccomodation.lodgingType+"</td>" + "<td style='text-align: right;'>"+this.formatPrice(this.selectedAccomodation.price+"")+"</td>"+"</tr>";
2178 if(typeof this.selectedAirport!="undefined" && this.selectedAirport.airport!="undefined") {
2179 var airportPrice="0,00 €";
2180 if(typeof this.selectedAirport.price!="undefined")
2181 airportPrice=this.formatPrice(this.packagePrice);
2182 rowAirport="<tr>"+ "<td>"+this.selectedAirport.airport+"</td>" + "<td style='text-align: right;'>"+airportPrice+"</td>"+"</tr>";
2183 }
2184 if(typeof this.packagePrice!="undefined")
2185 rowPackagePrice="<tr>"+ "<td>Prezzo base</td>" + "<td style='text-align: right;'>"+this.formatPrice(this.packagePrice)+"</td>"+"</tr>";
2186 if(typeof this.packageDiscount!="undefined" && this.packageDiscount!="" )
2187 rowPackageDiscount="<tr>"+ "<td>Sconto applicato</td>" + "<td style='text-align: right;'>"+this.formatPrice(this.packageDiscount)+"</td>"+"</tr>";
2188 if(typeof this.selectedServices!="undefined") {
2189 for(var i=0;i<this.selectedServices.length;i++) {
2190 var row="<tr>"+ "<td>"+this.selectedServices[i].service+"</td>" + "<td style='text-align: right;'>"+this.formatPrice(this.selectedServices[i].price)+"</td>"+"</tr>";
2191 rowsServices.push(row);
2192 }
2193 }
2194 if(typeof this.totalPrice!="undefined")
2195 rowTotalPrice="<tr>"+ "<td style='text-align: right;'><strong>TOTALE PREVENTIVO</strong></td>" + "<td style='text-align: right;'><strong>"+this.formatPrice(this.totalPrice)+"</strong></td>"+"</tr>";
2196
2197 for(var i=0;i<rowsServices.length;i++) {
2198 szRowsServices=szRowsServices+rowsServices[i];
2199 }
2200 msg = "<h1>Preventivo</h1>";
2201 msg = msg+ rowNomeScuola;
2202 msg=msg+ '<table>' +
2203 '<thead>' +
2204 '<tr>' +
2205 '<th scope="col">Servizio</th>' +
2206 '<th scope="col" style="text-align: right;">Prezzo</th>' +
2207 '</tr>' +
2208 '</thead>' +
2209 '<tbody>' +
2210 rowPackagePrice+
2211 rowPackageDiscount+
2212 rowAcco+
2213 rowAirport +
2214 szRowsServices +
2215 '<tr style=""><td> </td><td> </td></tr>'+
2216 rowTotalPrice +
2217 '</tbody>' +
2218 '</table>';
2219
2220
2221 requestInfo.message="<p>"+requestInfo.message+"</p>"+"<p>"+msg+"</p>";
2222
2223 requestInfo.message=requestInfo.message + "<p>" + "Ai sensi dell'art.13 del GDPR 679/16, vi informiamo che i dati utilizzati nel presente documento, da voi forniti, saranno utilizzati per le finalità di definizione del rapporto contrattuale in corso di negoziato. Per l'informativa completa si rinvia al sito <a href='https://www.iubenda.com/privacy-policy/20606989/legal'>www.zainettoverde.it</a>, alla sezione privacy"+ "</p>";
2224
2225 },
2226 formatPrice: function(price) {
2227 if(typeof price!="undefined" && price!="") {
2228 var formatter = new Intl.NumberFormat('it-IT', {
2229 style: 'currency',
2230 currency: 'EUR',
2231 });
2232 return formatter.format(parseFloat(price)) ;
2233 }
2234
2235 },
2236 formatServicePrice: function(service) {
2237 console.log("::"+service.price+"::");
2238 if(typeof service !="undefined" && typeof service.price!="undefined" && service.price.trim()!="" && service.price.trim()!="undefined") {
2239 var formatter = new Intl.NumberFormat('it-IT', {
2240 style: 'currency',
2241 currency: 'EUR',
2242 });
2243 return formatter.format(parseFloat(service.price.trim())) ;
2244 }
2245 else
2246 return "";
2247
2248
2249 },
2250 closeParentModal: function(id){
2251 window.parent.$(id).modal("hide");
2252 },
2253 redirectParent: function(url){
2254 window.top.location = "${themeDisplay.getPortalURL()}" + url;
2255 },
2256 needsPermission: function(item){
2257 if(item.marketingGroups.some(mg => mg.name == "accompagnatori")){
2258 return true;
2259 }else{
2260 return false;
2261 }
2262 },
2263 gotoStep: function(step){
2264 this.checkOrderAlreadyPresent();
2265 if(typeof(step) == "number"){
2266 this.currentStep = step;
2267 }else{
2268 if(step == "next"){
2269 this.currentStep++;
2270 }
2271 if(step == "prev"){
2272 this.currentStep--;
2273 }
2274 }
2275 if(5 == this.currentStep){
2276 oneInstanceRefreshCaptcha();
2277 }
2278
2279 if(7 == this.currentStep){
2280 setTimeout(function(){
2281 $('#payment_step input').each(function(){
2282 if ($(this).attr("id") != "allergie" && $(this).attr("id") != "inCameraCon") {
2283 if("" == $(this).val())
2284 {
2285 $(this).css({"border":"1px solid red"});
2286 }
2287 }
2288 });
2289 }, 500);
2290
2291 setTimeout(function(){
2292 $('#payment_step input[type=radio]').each(function(){
2293 $(this).parent().find('.custom-control-label-text').css({
2294 "color":"red"
2295 });
2296 });
2297 }, 500);
2298
2299 setTimeout(function(){
2300 $('#payment_step select').each(function(){
2301 $(this).css({"border-color":"red"});
2302 });
2303 }, 500);
2304 }
2305
2306 if(8 == this.currentStep){
2307 setTimeout(function(){
2308 $('#chose_payment input[type=radio]').each(function(){
2309 $(this).parent().find('.custom-control-label-text').css({
2310 "color":"red"
2311 });
2312 });
2313 }, 500);
2314 }
2315
2316 $('html, body').animate({
2317 scrollTop: $("#pay").offset().top
2318 }, 0);
2319 },
2320 getCity: function(fullString){
2321 return fullString.substr(0, fullString.indexOf('(') === -1 ? fullString.length : fullString.indexOf('('));
2322 },
2323 isBefore: function(data){
2324 return moment(data).isBefore(new Date());
2325 },
2326 isAfter: function(data){
2327 return moment(data).isAfter(new Date());
2328 },
2329 getExternalData: function(message){
2330 var strExtData = JSON.parse(JSON.stringify(message.data));
2331
2332 if(strExtData.source == null){
2333 var extData = JSON.parse(strExtData);
2334 console.log("dati ricevuti da iframe");
2335
2336 if(extData.key == "packageId"){
2337 if(_.isEmpty(this.selectedPackage)){
2338 this.selectPackage(extData.data);
2339
2340 this.calendar.periodoSelected.start = moment(this.selectedPackage?.startDate).format("DD MMMM YYYY");
2341 this.calendar.periodoSelected.end = moment(this.selectedPackage?.endDate).format("DD MMMM YYYY");
2342 //this.currentStep = 2;
2343
2344 console.log("selected packageIndex: " + extData.data);
2345 }else{
2346 if(this.selectedPackage._id.$oid != extData.data){
2347 console.log("Getting other package");
2348
2349 this.selectPackage(extData.data);
2350 }else{
2351 console.log("Package already selected");
2352 }
2353 }
2354 }
2355 }
2356 },
2357 setAttachments: function(){
2358 <#list allegati as allegato>
2359 <#assign stringSelector = "dynamic-element[@name='testo']/dynamic-content[@language-id = '" + themeDisplay.getLocale() + "']">
2360 <#assign xPathSelector = saxReaderUtil.createXPath(stringSelector)>
2361 <#if xPathSelector.selectSingleNode(allegato)??>
2362 <#assign text = xPathSelector.selectSingleNode(allegato).getData()>
2363 </#if>
2364
2365 <#assign stringSelector = "dynamic-element[@name='mandatory']/dynamic-content[@language-id = '" + themeDisplay.getLocale() + "']">
2366 <#assign xPathSelector = saxReaderUtil.createXPath(stringSelector)>
2367 <#if xPathSelector.selectSingleNode(allegato)??>
2368 <#assign mandatory = xPathSelector.selectSingleNode(allegato).getData()>
2369 </#if>
2370
2371 <#assign stringSelector = "dynamic-element[@name='documento']/dynamic-content[@language-id = '" + themeDisplay.getLocale() + "']">
2372 <#assign xPathSelector = saxReaderUtil.createXPath(stringSelector)>
2373 <#if xPathSelector.selectSingleNode(allegato)??>
2374 <#assign document = jsonFactoryUtil.createJSONObject(xPathSelector.selectSingleNode(allegato).getData())>
2375 </#if>
2376
2377 var newAttachment = {
2378 title: "${text}",
2379 mandatory: ${mandatory},
2380 fileName: "${document.getString('title')}",
2381 file: "${'/documents/' + document.getString('groupId') + '/0/' + document.getString('title') + '/' + document.getString('uuid')}",
2382 downloaded: false
2383 }
2384
2385 this.attachments.push(newAttachment);
2386 </#list>
2387 },
2388 downloadAttachment: function(attachment){
2389 var that = this,
2390 config = {
2391 headers: {
2392 "Access-Control-Allow-Origin": "*"
2393 },
2394 responseType: "blob"
2395 };
2396
2397 axios.get(attachment.file, config).then(function(res){
2398 var downLink = window.URL.createObjectURL(new Blob([res.data]));
2399 var link = document.createElement("a");
2400 link.href = downLink;
2401 link.setAttribute("download", attachment.fileName);
2402 document.body.appendChild(link);
2403 link.click();
2404 that.attachments.find(att => att.fileName == attachment.fileName).downloaded = true;
2405 }).catch(function(err){
2406 console.error("Error getting attachment: ", err);
2407 });
2408
2409 setTimeout(function(){
2410 $('#field_att input[type=checkbox]').not(':disabled').each(function(){
2411 $(this).parent().find('.custom-control-label-text').attr('style','color:red');
2412 });
2413 }, 5000);
2414
2415
2416 if($('.fa-download').length == 0){
2417 $('#info_accept').attr('style','color:#000 !important');
2418 }
2419 },
2420 getOrderStatus: function(){
2421 var that = this;
2422
2423 if(this.signedIn){
2424 const mongoQry = {
2425 "userId": this.userId,
2426 "orderParameters.selectedPackage.itemId": this.contentId
2427 }
2428
2429 var curId = this.contentId;
2430 Liferay.Service(
2431 '/destinazione.order/get-orders-by-user-id',
2432 {
2433 groupId: this.groupId,
2434 userId: this.userId
2435 },
2436 function (res) {
2437 if (res.success) {
2438
2439 if (res.data?.length > 0) {
2440 that.sameUserOrders=res.data;
2441 }
2442 }
2443 else
2444 console.log("UNSUCCESS");
2445 }
2446 );
2447
2448 }
2449 },
2450 checkOrderAlreadyPresent: function(){
2451 this.orderAlreadyPresent=false;
2452 console.log("checkOrderAlreadyPresent");
2453 if (this.sameUserOrders?.length > 0) {
2454 let i = 0;
2455 while (i < this.sameUserOrders?.length) {
2456 if (this.sameUserOrders[i].itemId == this.contentId)
2457 {
2458 if (this.sameUserOrders[i].orderStatus == "INSERTED" || this.sameUserOrders[i].orderStatus == "PAYED")
2459 {
2460 if(this.sameUserOrders[i].orderParameters.userData.lastName==this.userData.lastName &&
2461 this.sameUserOrders[i].orderParameters.userData.firstName==this.userData.firstName &&
2462 this.sameUserOrders[i].orderParameters.selectedPackage.startDate ==this.selectedPackage.startDate) {
2463 console.log("order already present is true");
2464 this.orderAlreadyPresent=true;
2465 return true;
2466 }
2467 }
2468 }
2469 i++;
2470 }
2471 }
2472 return false;
2473 },
2474 getUserData: function(){
2475 var that = this;
2476
2477 Liferay.Service("/destinazione.d40user/get-user-data", {
2478 groupId: this.groupId,
2479 userId: this.userId
2480 }, function(res){
2481 console.log("Get user data: ", res);
2482
2483 if(res.success){
2484 that.userData = {
2485 tutore: {},
2486 tutore2: {},
2487 ...res.data
2488 };
2489 that.getCountryList();
2490 }else{
2491 console.log("Error getting user data");
2492 }
2493 }).catch(function(err){
2494 console.error("Error getting userData: ", err);
2495 });
2496 },
2497 getCountryList: function(){
2498 var that = this;
2499
2500 Liferay.Service("/destinazione.d40user/get-country-list", {
2501 language: this.defaultLanguage
2502 }, function(res){
2503 console.log("Get country list: ", res);
2504
2505 if(res.success){
2506 that.countryList = res.data;
2507
2508 if(that.userData.billingCountryId == "0" || that.userData.billingCountryId == null){
2509 that.userData.billingCountryId = that.countryList.find(country => country.ID === that.defaultCountryId).ID;
2510 }else{
2511 that.userData.billingCountryId = that.defaultCountryId;
2512 }
2513
2514 that.getRegionList();
2515 }
2516 }).catch(function(err){
2517 console.error("Error getting countryList: ", err);
2518 });
2519 },
2520 getRegionList: function(){
2521 var that = this,
2522 idToUse = this.defaultCountryId;
2523
2524 if(this.userData.hasOwnProperty("billingCountryId") && typeof this.userData["billingCountryId"] === "string" && this.userData["billingCountryId"].length){
2525 idToUse = this.userData.billingCountryId;
2526 }
2527
2528 Liferay.Service("/destinazione.d40user/get-region-list", {
2529 countryId: idToUse
2530 }, function(res){
2531 console.log("Get region list: ", res);
2532
2533 if(res.success){
2534 that.regionList = res.data;
2535
2536 if(that.userData.billingRegionId == "0" || that.userData.billingRegionId == null){
2537
2538 }
2539 }
2540 }).catch(function(err){
2541 console.error("Error getting regionList: ", err);
2542 });
2543 },
2544 getPackages: function(){
2545 var that = this,
2546 tempPackages = [],
2547 packagesObj = ${jsonFactoryUtil.looseSerialize(packages)};
2548
2549 packagesObj.data.items.forEach(function(pacchetto){
2550 pacchetto.airportsAndPrices = JSON.parse(pacchetto.airportsAndPrices);
2551 pacchetto.lodgingTypesAndPrices = JSON.parse(pacchetto.lodgingTypesAndPrices.replace(/lodgingPrice/g, "price"));
2552 pacchetto.servicesAndPrices = JSON.parse(pacchetto.servicesAndPrices);
2553
2554 pType = pacchetto.paymentType;
2555 pacchetto.paymentType = [];
2556
2557 if (JSON.parse(pType) instanceof Array) {
2558 console.log("paymentType: array");
2559
2560 var types = JSON.parse(pType);
2561 var acconto=0;
2562 types.forEach(function(type){
2563 if(typeof type === 'object'){
2564 var newPaymentType = {
2565 "type": type.type,
2566 "amount": Number(type.amount)
2567 }
2568 if(type.type=="cartaCreditoAcconto")
2569 acconto= Number(type.amount);
2570 }else{
2571 console.log(typeof type);
2572
2573 var newPaymentType = {
2574 "type": type,
2575 "amount": 0
2576 }
2577 }
2578
2579 pacchetto.paymentType.push(newPaymentType);
2580 });
2581 /* correggo un errore di backoffice, se acconto è zero metto come acconto quello di credit card */
2582 for(var i =0;i<pacchetto.paymentType.length;i++) {
2583 var payment=pacchetto.paymentType[i];
2584 if(payment.amount==0)
2585 payment.amount=acconto;
2586 }
2587 console.log("tipo di pagamento corretto",pacchetto.paymentType);
2588
2589 } else {
2590 var types = {
2591 "type": JSON.parse(pType),
2592 "amount": 0
2593 }
2594
2595 pacchetto.paymentType = types;
2596 }
2597
2598 pacchetto.purchaseBeforeDiscount = JSON.parse(pacchetto.purchaseBeforeDiscount);
2599 pacchetto.endDate = moment(pacchetto?.startDate).add(pacchetto.numNights, "days").toDate();
2600 pacchetto.show = true;
2601
2602 if(pacchetto?.startDate.indexOf("2030-")<0)
2603 tempPackages.push(pacchetto);
2604 });
2605
2606 tempPackages.sort(function(a, b){
2607 return new Date(a?.startDate) - new Date(b?.startDate);
2608 });
2609
2610 this.packages = tempPackages;
2611 },
2612
2613 resetSelections: function(){
2614 this.selectedAccomodation = {};
2615 this.selectedAirport = {};
2616 this.selectedPayment = {};
2617 this.selectedBalance = {};
2618 this.selectedServices = [];
2619 this.paymentLink = "#";
2620 this.voucher = "";
2621 this.packagePrice = 0;
2622 this.currentStep = 1;
2623 },
2624 selectPackage: function(packageId){
2625 var that = this;
2626 this.resetSelections();
2627 console.log("select package with id " + packageId);
2628<#-- added adriano
2629
2630 if(typeof this.selectedPackage!== "undefined" && typeof this.selectedPackage._id!="undefined" && packageId!=this.selectedPackage._id.$oid) {
2631 this.selectedAirport={};
2632
2633 }
2634fine added adriano -->
2635
2636 this.selectedPackage = this.packages.find(function(package){
2637 return package._id.$oid == packageId
2638 });
2639
2640 this.packagePrice = this.selectedPackage.basePrice;
2641 this.packageDiscount = 0;
2642
2643 this.selectedPackage.purchaseBeforeDiscount.forEach(function(sconto){
2644 if(that.isDiscountValid(sconto) && sconto.discount != 0){
2645 that.packageDiscount = Number(sconto.discount);
2646 }
2647 });
2648
2649 this.setMandatoryServices();
2650 },
2651 select: function(name, obj){
2652 if(name == "airport"){
2653 this.selectedAirport = obj;
2654 }
2655 if(name == "accomodation"){
2656 this.selectedAccomodation = obj;
2657 }
2658 },
2659 checkFavourite: function(){
2660 var that = this;
2661
2662 Liferay.Service('/destinazione.favorite/get-wish-list', {
2663 groupId: Liferay.ThemeDisplay.getScopeGroupId(),
2664 sessionId: String(Liferay.ThemeDisplay.getSessionId()),
2665 userId: String(Liferay.ThemeDisplay.getUserId()),
2666 }, function(res){
2667 console.log("getWishList response: ", res);
2668 if(res.success){
2669 res.data.forEach(function(obj){
2670 if(obj.itemId == that.contentId){
2671 that.favourite = true;
2672 that.oid = obj._id.$oid;
2673 }
2674 });
2675 }
2676 }).catch(function(err){
2677 console.error("Error getting wishlist: ", err);
2678 });
2679 },
2680 checkVoucher: function(){
2681 var that = this,
2682 endPoint = "/servicefeed?p_p_id=Configurable&p_p_lifecycle=2&p_p_resource_id=json&_Configurable_jsonParams=",
2683 params = {
2684 "fn": "validate",
2685 "email": this.userMail,
2686 "articleId": this.contentId,
2687 "nomeTariffa": this.selectedPackage.title,
2688 "vc": this.voucher,
2689 "packageId": this.selectedPackage._id.$oid,
2690 "amount": this.totalPrice * 100
2691 }
2692
2693 axios.get(endPoint + JSON.stringify(params)).then(function(res){
2694 if(res.data.result.data.valid && res.data.result.data.order.total_discount_amount){
2695 console.log("Voucher res: ", res.data.result.data);
2696 that.voucherValid = true;
2697 that.voucherDiscount = res.data.result.data.order.total_discount_amount / 100;
2698 }else{
2699 console.error("Something went wrong with voucher: ", res.data);
2700 alert("Voucher non valido");
2701 }
2702 }).catch(function(err){
2703 console.error("Error validating voucher: ", err);
2704 });
2705 },
2706 createOrderAndPaymentUrl: function(){
2707 var that = this;
2708
2709 // this.addEvent("stampa_preventivo");
2710
2711 var orderPrice = 0,
2712 orderParams = {
2713 selectedPackage: this.selectedPackage,
2714 selectedAccomodation: this.selectedAccomodation,
2715 selectedAirport: this.selectedAirport,
2716 selectedServices: this.selectedServices,
2717 selectedPayment: this.selectedPayment,
2718 selectedBalance: this.selectedBalance,
2719 packagePrice: this.packagePrice,
2720 packageDiscount: this.packageDiscount,
2721 totalPrice: this.totalPrice,
2722 voucherDiscount: this.voucherDiscount,
2723 userData: this.userData,
2724 policy:this.policy,
2725 doppioCheck:this.doppiocheck
2726 };
2727
2728 if(this.selectedPayment.amount == 0 || this.selectedPayment.amount === undefined){
2729 orderPrice = this.totalPrice;
2730 }else{
2731 orderPrice = this.selectedPayment.amount;
2732 }
2733
2734 console.log("orderPrice is " + orderPrice);
2735
2736 if(this.selectedPayment.type != "bonifico" && this.selectedPayment.type != "rateale" && this.selectedPayment.type != "rateale-zv"){
2737 var iframe = window.open("/", "_blank");
2738 }
2739
2740 Liferay.Service("/destinazione.order/add-order-and-get-payment-url", {
2741 groupId: this.groupId,
2742 userId: this.userId,
2743 itemGroupId: Liferay.ThemeDisplay.getScopeGroupId(),
2744 itemId: this.contentId,
2745 totalPrice: this.totalPrice,
2746 params: JSON.stringify(orderParams),
2747 currency: "EUR",
2748 priceToPay: orderPrice,
2749 userEmail: this.userMail,
2750 languageId: "ITA",
2751 description: this.name,
2752 session_id: String(Liferay.ThemeDisplay.getSessionId()),
2753 cart_id: "12",
2754 baseUrl: Liferay.ThemeDisplay.getURLHome().split("/web/")[0],
2755 locsz: ""
2756 }, function(res){
2757 console.log("Create order and payment url res: ", res);
2758
2759 // Sezione redemption voucher
2760 if(that.voucherValid){
2761 var endPoint = "/servicefeed?p_p_id=Configurable&p_p_lifecycle=2&p_p_resource_id=json&_Configurable_jsonParams=",
2762 params = {
2763 "fn": "redemption",
2764 "email": that.userMail,
2765 "articleId": that.contentId,
2766 "nomeTariffa": that.selectedPackage.title,
2767 "vc": that.voucher,
2768 "packageId": that.selectedPackage._id.$oid,
2769 "amount": that.totalPrice * 100
2770 }
2771
2772 axios.get(endPoint + JSON.stringify(params)).then(function(vRes){
2773 console.log("vRes is ", vRes);
2774 }).catch(function(vErr){
2775 console.error("Error during voucher redemption: ", vErr);
2776 });
2777 }
2778
2779 if(res.success){
2780 that.addEvent("stampa_preventivo")
2781
2782 if(that.selectedPayment.type != "bonifico" && that.selectedPayment.type != "rateale" && that.selectedPayment.type != "rateale-zv"){
2783 console.log("redirecting...");
2784 iframe.location = res.data.url;
2785 that.closeParentModal("#pay-modal");
2786 }else{
2787 that.currentStep++;
2788 console.log("ordine immesso con bonifico, non ridireziono l'utente");
2789 }
2790
2791 that.orderResult = "Ordine inserito con successo";
2792 }else{
2793 that.orderResult = "C'è stato un problema con l'inserimento dell'ordine. Contattare Zainetto Verde se il problema persiste.";
2794 }
2795 }).catch(function(err){
2796 console.error("Error: ", err);
2797
2798 that.orderResult = "C'è stato un problema con l'inserimento dell'ordine. Contattare Zainetto Verde se il problema persiste.";
2799 });
2800 },
2801 setFavourite: function(){
2802 var that = this;
2803
2804 if(this.signedIn){
2805 Liferay.Service('/destinazione.favorite/add-to-wish-list', {
2806 groupId: Liferay.ThemeDisplay.getScopeGroupId(),
2807 sessionId: String(Liferay.ThemeDisplay.getSessionId()),
2808 userId: String(Liferay.ThemeDisplay.getUserId()),
2809 itemGroupId: 11,
2810 itemId: this.contentId
2811 }, function(res){
2812 if(res.success){
2813 console.log("addToWishList response: ", res);
2814 that.favourite = true;
2815 }
2816 }).catch(function(err){
2817 console.error("Error adding to wishlist: ", err);
2818 });
2819 }else{
2820 this.redirect("login?contentId=${contentId}");
2821 }
2822 },
2823 removeFavourite: function(){
2824 var that = this;
2825
2826 Liferay.Service('/destinazione.favorite/delete-item-from-wish-list', {
2827 oid: this.oid
2828 }, function(res) {
2829 console.log("deleteFromWishList response: ", res);
2830 that.favourite = false;
2831 that.checkFavourite();
2832 }).catch(function(err){
2833 console.error("Error removing from wishlist: ", err);
2834 });
2835 },
2836 saveData: function(){
2837 console.log("todo save data");
2838 },
2839 getPaymentLabel: function(type){
2840 if(type == "bonifico")
2841 return "Acconto con bonifico bancario";
2842 if(type == "cartaCredito")
2843 return "Carta di credito";
2844 if(type == "cartaCreditoAcconto")
2845 return "Acconto con carta di credito";
2846 },
2847 setCustomStyle: function(){
2848 var that = this,
2849 style = document.createElement('style');
2850
2851 style.type = 'text/css';
2852
2853 this.packages.forEach(function(package, index){
2854 if(index > 0){
2855 if(moment(package?.startDate).isSame(that.packages[index-1]?.endDate)){
2856 console.log("la data " + package?.startDate + " combacia");
2857
2858 var dateClass = ".id-" + moment(package?.startDate).format("YYYY-MM-DD");
2859 style.innerHTML += dateClass + ' .vc-highlights .vc-day-layer { box-shadow: none !important; }';
2860 }
2861 }
2862 });
2863
2864 if(style.innerHTML != ""){
2865 document.getElementsByTagName('head')[0].appendChild(style);
2866 console.log("custom style for calendar injected");
2867 }
2868 },
2869 initCalendar: function(){
2870 var that = this;
2871 this.calendar.dataInizio = moment(this.packages[0]?.startDate).toDate();
2872 this.calendar.initialPage.month = moment(this.calendar.dataInizio).month() + 1;
2873 this.calendar.initialPage.year = moment(this.calendar.dataInizio).year();
2874 this.calendar.dataFine = moment(this.packages[this.packages.length - 1]?.endDate).toDate();
2875
2876 this.packages.forEach(function(package, index){
2877 var periodo = {
2878 key: package.itemId + "_" + index,
2879 highlight: true,
2880 dates: [{
2881 "start": moment(package?.startDate).toDate(),
2882 "end": moment(package?.endDate).toDate()
2883 }],
2884 order: index
2885 };
2886
2887 that.calendar.attributes.push(periodo);
2888 });
2889
2890 this.setCustomStyle();
2891 },
2892 selectDate: function(value){
2893 var that = this;
2894
2895 console.log("Data scelta: ", value)
2896 this.calendar.dataSelected = value.date;
2897
2898 this.packages.forEach(function(package){
2899 if(moment(value.date).isBetween(package?.startDate, package?.endDate)){
2900 console.log(value.date + " è compresa");
2901 package.show = true;
2902 }
2903 });
2904 },
2905 resetDates: function(){
2906 this.calendar.dataSelected = null;
2907 this.packages.forEach(function(package){
2908 package.show = true;
2909 });
2910 },
2911 showResults: function(data){
2912 var that = this;
2913
2914 this.packages.forEach(function(package){
2915 package.show = false;
2916
2917 if(moment(data).isBetween(package?.startDate, package?.endDate)){
2918 console.log(data + " è compresa");
2919 package.show = true;
2920 }
2921 });
2922 },
2923 setMandatoryServices: function(){
2924 var that = this;
2925
2926 this.selectedServices = [];
2927
2928 this.selectedPackage.servicesAndPrices.forEach(function(service){
2929 if(service.mandatory){
2930 that.selectedServices.push(service);
2931 }
2932 });
2933 },
2934 setProgressData: function(){
2935 localStorage.removeItem("progressData");
2936 console.log("removed old progress data");
2937
2938 var progressData = {
2939 url: window.top.location.href,
2940 selectedAccomodation: this.selectedAccomodation,
2941 selectedAirport: this.selectedAirport,
2942 selectedPackage: this.selectedPackage,
2943 selectedPayment: this.selectedPayment,
2944 selectedBalance: this.selectedBalance,
2945 selectedServices: this.selectedServices,
2946 packagePrice: this.packagePrice,
2947 packageDiscount: this.packageDiscount,
2948 totalPrice:this.totalPrice,
2949 userData: this.userData,
2950 userMail: this.userMail
2951
2952 }
2953
2954 localStorage.setItem("progressData", JSON.stringify(progressData));
2955 console.log("progressData saved");
2956 },
2957 getProgressData: function(){
2958 if(localStorage.getItem("progressData") !== null){
2959 console.log("previous data exists, getting it");
2960
2961 if(JSON.parse(localStorage.getItem("progressData")).url == window.top.location.href){
2962 console.log("previous data is form actual page, restoring it...");
2963
2964 var previousData = JSON.parse(localStorage.getItem("progressData"));
2965
2966 this.selectedAccomodation = previousData.selectedAccomodation;
2967 this.selectedAirport = previousData.selectedAirport;
2968 this.selectedPackage = previousData.selectedPackage;
2969 this.selectedPayment = previousData.selectedPayment;
2970 this.selectedBalance = previousData.selectedBalance;
2971 this.selectedServices = previousData.selectedServices;
2972 this.packagePrice = previousData.packagePrice;
2973 this.packageDiscount = previousData.packageDiscount;
2974 this.userData=previousData.userData;
2975 this.userMail=previousData.userMail;
2976
2977 console.log("previous data restored");
2978 localStorage.removeItem("progressData");
2979
2980 this.currentStep = 6;
2981
2982 this.openParentModal("#pay-modal");
2983 }else{
2984 console.log("ProgressData is from a different page");
2985 }
2986 }else{
2987 console.log("no previous data exists");
2988 }
2989 },
2990 isBefore: function(data){
2991 return moment(data).isBefore(new Date());
2992 },
2993 isAfter: function(data){
2994 return moment(data).isAfter(new Date());
2995 },
2996 isDiscountValid: function(sconto){
2997 var today = new Date(),
2998 valid = false;
2999
3000 if(moment(today).isSameOrAfter(sconto.date) && moment(today).isSameOrBefore(sconto.dateEnd)){
3001 valid = true;
3002 }
3003
3004 return valid;
3005 },
3006 checkEmpty: function(e){
3007 const element = e.target;
3008 if("" != element.value)
3009 {
3010 $('#'+element.id).css({"border":"1px solid #e7e7ed"});
3011 }else{
3012 $('#'+element.id).css({"border":"1px solid red"});
3013 }
3014 },
3015 dateFormat: function (szDate) {
3016 const pattern = /^\d{2}\/\d{2}\/\d{4}$/;
3017 return pattern.test(szDate);
3018 },
3019 checkDateLength: function(e){
3020 const element = e.target;
3021 if("" != element.value && element.value.length==10 && this.dateFormat(element.value) )
3022 {
3023 $('#'+element.id).css({"border":"1px solid #e7e7ed"});
3024 }else{
3025 $('#'+element.id).css({"border":"1px solid red"});
3026 }
3027 },
3028 restrictDigitInput: function(e) {
3029 const element = e.target;
3030 const allowedCharacters = /[0-9]/; // Caratteri consentiti: numeri
3031 const stringValue=element.value;
3032 if(e.key=='Backspace' || e.key=='ArrowLeft' || e.key=='ArrowRight' || e.key=='Tab')
3033 return;
3034 if (!allowedCharacters.test(e.key)) {
3035 e.preventDefault();
3036 return;
3037 }
3038 },
3039 restrictDateInput: function(e) {
3040 const element = e.target;
3041 const allowedCharacters = /[0-9]/; // Caratteri consentiti: numeri
3042 const stringValue=element.value;
3043 if(e.key=='Backspace' || e.key=='ArrowLeft' || e.key=='ArrowRight' || e.key=='Tab')
3044 return;
3045 var curPos=e.target.selectionStart;
3046 switch( curPos ) {
3047 case 0: case 1:
3048 if (!allowedCharacters.test(e.key)) {
3049 e.preventDefault();
3050 }
3051 break;
3052 case 2:
3053 if(e.key!="/") {
3054 e.preventDefault();
3055 }
3056 break;
3057 case 3: case 4:
3058 if (!allowedCharacters.test(e.key)) {
3059 e.preventDefault();
3060 }
3061 break;
3062 case 5:
3063 if(e.key!="/")
3064 e.preventDefault();
3065 break;
3066 case 6: case 7: case 8: case 9:
3067 if (!allowedCharacters.test(e.key)) {
3068 e.preventDefault();
3069 }
3070 break;
3071
3072 default:
3073 e.preventDefault();
3074 }
3075
3076 },
3077 checkSelect: function(e){
3078 const element = e.target;
3079 if("" != element.value)
3080 {
3081 $('#'+element.id).css({"border":"1px solid #e7e7ed"});
3082 }else{
3083 $('#'+element.id).css({"border":"1px solid red"});
3084 }
3085 },
3086 checkEmail: function(e){
3087 const mail_el = e.target;
3088 if("" != mail_el.value)
3089 {
3090 if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(mail_el.value)) {
3091 $('#'+mail_el.id).css({"border":"1px solid #e7e7ed"});
3092 } else {
3093 $('#'+mail_el.id).css({"border":"1px solid red"});
3094 }
3095 }else{
3096 $('#'+mail_el.id).css({"border":"1px solid red"});
3097 }
3098 },
3099 checkTelefono: function(e) {
3100 const tel_el = e.target;
3101 if("" != tel_el.value)
3102 {
3103 if (/^[0-9]+$/.test(tel_el.value)) {
3104 $('#'+tel_el.id).css({"border":"1px solid #e7e7ed"});
3105 } else {
3106 $('#'+tel_el.id).css({"border":"1px solid red"});
3107 }
3108 }else{
3109 $('#'+tel_el.id).css({"border":"1px solid red"});
3110 }
3111 },
3112 checkCodiceFiscale: function(e) {
3113 const cf_el = e.target;
3114 var cf= cf_el.value;
3115 if(""!= cf) {
3116 // se corretto ok, altrimenti border
3117 var ret=this.controllaCF(cf);
3118 console.log(ret);
3119 if(ret=="") {
3120 this.msgCodiceFiscale=ret;
3121 $('#'+cf_el.id).css({"border":"1px solid #e7e7ed"});
3122 }
3123 else {
3124 this.msgCodiceFiscale=ret;
3125 $('#'+cf_el.id).css({"border":"1px solid red"});
3126
3127 }
3128 }
3129 else{
3130 this.msgCodiceFiscale="codice fiscale non valido";
3131 $('#'+cf_el.id).css({"border":"1px solid red"});
3132 }
3133 },
3134 controllaCF: function (cf) {
3135 console.log(cf);
3136 var validi, i, s, set1, set2, setpari, setdisp;
3137 if (cf == '') return '';
3138 cf = cf.toUpperCase();
3139 if (cf.length != 16)
3140 return "La lunghezza del codice fiscale non è\n"
3141 + "corretta: il codice fiscale dovrebbe essere lungo\n"
3142 + "esattamente 16 caratteri.\n";
3143 validi = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
3144 for (i = 0; i < 16; i++) {
3145 if (validi.indexOf(cf.charAt(i)) == -1)
3146 return "Il codice fiscale contiene un carattere non valido `" +
3147 cf.charAt(i) +
3148 "'.\nI caratteri validi sono le lettere e le cifre.\n";
3149 }
3150 set1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
3151 set2 = "ABCDEFGHIJABCDEFGHIJKLMNOPQRSTUVWXYZ";
3152 setpari = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
3153 setdisp = "BAKPLCQDREVOSFTGUHMINJWZYX";
3154 s = 0;
3155 for (i = 1; i <= 13; i += 2)
3156 s += setpari.indexOf(set2.charAt(set1.indexOf(cf.charAt(i))));
3157 for (i = 0; i <= 14; i += 2)
3158 s += setdisp.indexOf(set2.charAt(set1.indexOf(cf.charAt(i))));
3159 if (s % 26 != cf.charCodeAt(15) - 'A'.charCodeAt(0))
3160 return "Il codice fiscale non è corretto:\n" +
3161 "il codice di controllo non corrisponde.\n";
3162 return "";
3163 },
3164 checkRadio: function(radio_name){
3165 console.log('blur radio');
3166 if ($('input[name='+radio_name+']:checked').length > 0) {
3167 $('input[name='+radio_name+']').each(function(){
3168 $(this).parent().find('.custom-control-label-text').css({
3169 "color":"initial"
3170 })
3171 });
3172 }else{
3173 $('input[name='+radio_name+']').each(function(){
3174 $(this).parent().find('.custom-control-label-text').css({
3175 "color":"red"
3176 })
3177 });
3178 }
3179 },
3180 checkPolicy: function(e){
3181 const check_el = e.target;
3182 console.log('test_change');
3183 if ($('#'+check_el.id).is(':checked')){
3184 $('#'+check_el.id).parent().find('.custom-control-label-text').attr('style','color:initial');
3185 }else{
3186 $('#'+check_el.id).parent().find('.custom-control-label-text').attr('style','color:red');
3187 }
3188 },
3189 checkRadioPayment: function(){
3190 $('#chose_payment input[type=radio]').each(function(){
3191 if($(this).is(':checked')){
3192 $('#chose_payment input[type=radio]').each(function(){
3193 $(this).parent().find('.custom-control-label-text').css({
3194 "color":"initial"
3195 })
3196 });
3197 }
3198 });
3199 },
3200 addEvent: function(eventName){
3201 window.dataLayer = window.parent.dataLayer || [];
3202 dataLayer.push({
3203 "event": eventName
3204 });
3205 }
3206 }
3207 });
3208
3209 });
3210</script>
3211
3212<#function getPackagesByItemId groupId itemGroupId itemId>
3213 <#return productServiceAPI.getAvailPackagesByItemId(groupId?number, itemGroupId?number, itemId, "", 0, 100)>
3214</#function>
3215
3216<#function getPrefix img width height>
3217 <#assign
3218 baseUrl = "https://d28r45jypu6nt9.cloudfront.net/o/d40/img/"
3219 siteUrl = themeDisplay.getURLPortal()?replace("://", ".")
3220 w = width
3221 h = height
3222 />
3223 <#if height?is_string>
3224 <#assign prefix = baseUrl + "w_" + w + "/" + siteUrl>
3225 <#else>
3226 <#assign prefix = baseUrl + "w_" + w + ",h_" + h + "/" + siteUrl>
3227 </#if>
3228
3229 <#if !img?contains("/documents/")>
3230 <#assign prefix = "">
3231 </#if>
3232
3233 <#return prefix + img>
3234</#function>