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