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