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