1<#assign layoutLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.LayoutLocalService")/>
2<#assign journalArticleService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")/>
3<#assign ddmFieldLocalService = serviceLocator.findService("com.liferay.dynamic.data.mapping.service.DDMFieldLocalService")/>
4
5<#assign assetEntryLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetEntryLocalService") />
6
7<#if entries?has_content>
8
9 <div class="py-6 py-lg-11">
10 <div class="c-carrusel-packs container" id="carrusel-number-${entries?size}">
11 <div class="c-carrusel-packs__track" id="carrusel-packs-suelto">
12 <#list entries as curEntry>
13 <#assign assetRenderer = curEntry.getAssetRenderer()/>
14 <#assign journalArticle = assetRenderer.getAssetObject() />
15 <#assign ddmStructure = journalArticle.getDDMStructure() />
16 <#assign ddmForm = ddmStructure.getDDMForm()/>
17 <#assign ddmFormValues = ddmFieldLocalService.getDDMFormValues(ddmForm, journalArticle.getId()) />
18 <#assign ddmFormFieldValues = ddmFormValues.getDDMFormFieldValues() />
19 <#assign classPK=curEntry.getClassPK()>
20 <#assign assetEntry = assetEntryLocalService.getEntry("com.liferay.journal.model.JournalArticle", classPK) />
21 <#assign assetCategories = assetEntry.getCategories() />
22 <#assign contentId = .vars["journalArticle"].getArticleId() />
23 <#assign landingPageURL = "" />
24
25 <#if journalArticle??>
26 <#-- Inicializar las variables -->
27 <#assign trainName = "" />
28 <#assign routeOrigin = "" />
29 <#assign routePrices = "" />
30 <#assign routeDate = "" />
31 <#assign routeInclude = [] />
32 <#assign routeIncludeList = [] />
33 <#assign imageUrl = "" />
34
35 <#-- Extrae campos DDM -->
36 <#assign ddmStructure = journalArticle.getDDMStructure() />
37 <#assign ddmForm = ddmStructure.getDDMForm() />
38 <#assign ddmFormValues = ddmFieldLocalService.getDDMFormValues(ddmForm, journalArticle.getId())?default({}) />
39 <#assign ddmFormFieldValues = ddmFormValues.getDDMFormFieldValues()?default([]) />
40
41 <#list ddmFormFieldValues as field>
42 <#switch field.getFieldReference()>
43 <#case "trainName">
44 <#assign trainName = field.getValue().getString(locale)!''>
45 <#break>
46 <#case "routeOrigin">
47 <#assign routeOrigin = field.getValue().getString(locale)!''>
48 <#break>
49 <#case "routeDate">
50 <#assign routeDate = field.getValue().getString(locale)!''>
51 <#break>
52 <#case "routePrices">
53 <#assign routePrices = field.getValue().getString(locale)!''>
54 <#break>
55
56 <#case "landingPageURL">
57 <#assign landingPageURL = "" />
58 <#assign layoutJson = field.getValue().getString(locale)!"" />
59
60 <#if layoutJson?has_content>
61 <#assign layoutData = layoutJson?eval />
62
63 <#assign groupId = layoutData.groupId?number />
64 <#assign layoutUuid = layoutData.id!layoutData.value />
65
66 <#if layoutUuid?has_content>
67 <#assign layout = layoutLocalService.getLayoutByUuidAndGroupId(layoutUuid, groupId, false) />
68 <#assign landingPageURL = themeDisplay.getPortalURL() + layout.getFriendlyURL() />
69 </#if>
70 </#if>
71 <#break>
72
73 <#case "routeInclude">
74 <#assign routeIncludeList = routeIncludeList + [field.getValue().getString(locale)!''] />
75 <#break>
76 <#case "origenIDs">
77 <#assign origenIDs = field.getValue().getString(locale)!''>
78 <#assign isUnavailable = !origenIDs?has_content>
79 <#break>
80 <#case "destinationID">
81 <#assign destinationID = field.getValue().getString(locale)!''>
82 <#break>
83 <#case "trainDateStart">
84 <#assign trainDateStart = field.getValue().getString(locale)!''>
85 <#break>
86
87 <#case "trainDateFinish">
88 <#assign trainDateFinish = field.getValue().getString(locale)!''>
89 <#break>
90 <#case "trainType">
91 <#assign searchType = field.getValue().getString(locale)!''>
92 <#break>
93 <#case "trainImage">
94 <#assign imageJSON = field.getValue().getString(locale)!''>
95 <#if imageJSON?has_content>
96 <#assign imageData = imageJSON?eval>
97 <#assign imageUrl = imageData.url!''>
98 </#if>
99 <#break>
100
101
102 <#default>
103 </#switch>
104 </#list>
105
106 <#-- Creacion de URL: -->
107 <#assign baseURL = "/checkout" />
108 <#assign params = {} />
109
110 <#if contentId?has_content>
111 <#assign params = params + {"reference": contentId} />
112 </#if>
113
114 <#if origenIDs?has_content>
115 <#assign params = params + {"origins": origenIDs} />
116 </#if>
117
118 <#if destinationID?has_content>
119 <#assign params = params + {"destination": destinationID} />
120 </#if>
121
122 <#if searchType?has_content>
123 <#assign params = params + {"searchType": searchType} />
124 </#if>
125
126 <#if trainDateStart?has_content>
127 <#assign params = params + {"trainDateStart": trainDateStart} />
128 </#if>
129
130 <#if trainDateFinish?has_content>
131 <#assign params = params + {"trainDateFinish": trainDateFinish} />
132 </#if>
133
134 <#assign queryString = "" />
135
136 <#if params?size gt 0>
137 <#assign first = true />
138 <#list params?keys as key>
139 <#if first>
140 <#assign queryString = "?" + key + "=" + params[key] />
141 <#assign first = false />
142 <#else>
143 <#assign queryString = queryString + "&" + key + "=" + params[key] />
144 </#if>
145 </#list>
146 </#if>
147
148 <#-- FIN - Creacion de URL: -->
149
150 </#if>
151
152 <div class="c-card-pack">
153 <#if imageUrl?has_content>
154 <img class="c-card-pack__image" src="${imageUrl}" alt="" />
155 </#if>
156 <div class="c-card-pack__content">
157 <#if trainName?has_content>
158 <h3 class="c-card-pack__title">${trainName} </h3>
159 </#if>
160 <#if routeOrigin?has_content>
161 <p class="c-card-pack__description">${routeOrigin}</p>
162 </#if>
163 <ul class="c-list-icon c-list-icon--card-pack">
164 <li class="c-list-icon__item">
165 <i class="c-list-icon__icon alsa-tt-icon-ticket"></i>
166 <p class="c-list-icon__text"><@liferay.language key="adt.include"/></p>
167 <#if routeIncludeList?has_content>
168 <ul class="c-list-icon__sublist">
169 <#list routeIncludeList as cur_routeInclude>
170 <li class="c-list-icon__sublist-item">
171 ${cur_routeInclude}
172 </li>
173 </#list>
174 </ul>
175 </#if>
176 </li>
177
178 <#if routePrices?has_content>
179 <li class="c-list-icon__item">
180 <i class="c-list-icon__icon alsa-tt-icon-enjin-coin-enj"></i>
181 <div class="c-list-icon__text">${routePrices}</div>
182
183 </li>
184 </#if>
185 <#if routeDate?has_content>
186 <li class="c-list-icon__item">
187 <i class="c-list-icon__icon alsa-tt-icon-calendar-1"></i>
188 <p class="c-list-icon__text">${routeDate}</p>
189 </li>
190 </#if>
191 </ul>
192
193
194 <#if isUnavailable>
195 <div class="c-card-pack__buttons justify-content-center">
196 <button class="c-button c-button--blue c-button--large" disabled><@liferay.language key="adt.soon"/></button>
197 <#else>
198 <div class="c-card-pack__buttons">
199 <button class="c-button c-button--blue c-button--large"
200 onclick="window.location.href='${baseURL}${queryString}'"><@liferay.language key="adt.book"/></button>
201 <a href="${landingPageURL!""}" class="c-link c-link--blue">${trainName!'<@liferay.language key="adt.information"/>'}</a>
202 </#if>
203
204 </div>
205 </div>
206 </div>
207
208 </#list>
209 </div>
210
211 <div class="c-carrusel-packs__controls">
212 <button type="button" class="c-carrusel-packs__button" id="carrusel-packs-suelto-prev-button" aria-label='<@liferay.language key="adt.previous.slide"/>'>
213 <i class="alsa-tt-icon-arrow-left"></i>
214 </button>
215 <button type="button" class="c-carrusel-packs__button" id="carrusel-packs-suelto-next-button" aria-label='<@liferay.language key="adt.next.slide"/>'>
216 <i class="alsa-tt-icon-arrow-right-1"></i>
217 </button>
218 </div>
219
220 </div>
221 </div>
222</#if>
223
224<script>
225 $(document).ready(function() {
226 //Slider packs o rutas del tren
227 var $sliderPacks = $('#carrusel-packs-suelto');
228 var $items = $sliderPacks.find('.col-12, .col-md-6, .col-lg-4');
229
230 function applyColumnClasses(activeCarousel) {
231 if (activeCarousel) {
232 $items.removeClass('col-md-6 col-lg-4').addClass('col-12');
233 } else {
234 $items.removeClass('col-12').addClass('col-12 col-md-6 col-lg-4');
235 }
236 }
237
238 var $cards = $sliderPacks.find('.c-card-pack');
239 var entriesCount = $cards.length;
240 // Botones del slider
241 var $prevButton = $('#carrusel-packs-suelto-prev-button');
242 var $nextButton = $('#carrusel-packs-suelto-next-button');
243
244 // Función para aplicar estilos responsive si hay solo 1 tarjeta
245 function applySingleCardStyles() {
246 if (entriesCount === 1) {
247 $sliderPacks.css({
248 'display': 'flex',
249 'justify-content': 'center'
250 });
251
252 if (window.innerWidth < 768) {
253 $cards.css({
254 'width': '100%',
255 'max-width': 'none'
256 });
257 } else {
258 $cards.css({
259 'width': '100%',
260 'max-width': '330px'
261 });
262 }
263
264 // Ocultar botones
265 $prevButton.hide();
266 $nextButton.hide();
267 }
268 }
269
270 // Ejecutar al cargar
271 applySingleCardStyles();
272
273 // Ejecutar al redimensionar
274 $(window).on('resize', function() {
275 applySingleCardStyles();
276 });
277
278 // Inicializar slick solo si hay más de 1 tarjeta
279 if (entriesCount > 1) {
280 // Mostrar botones en caso de haber sido ocultos anteriormente
281 $prevButton.show();
282 $nextButton.show();
283
284 $sliderPacks.slick({
285 dots: false,
286 infinite: false,
287 speed: 300,
288 slidesToShow: 4,
289 slidesToScroll: 1,
290 appendDots: $('.c-carrusel-packs__controls'), // aquí van los dots
291 arrows: true,
292 prevArrow: $('#carrusel-packs-suelto-prev-button'),
293 nextArrow: $('#carrusel-packs-suelto-next-button'),
294 responsive: [
295 {
296 breakpoint: 1440,
297 settings: {
298 slidesToShow: 3
299 }
300 },
301 {
302 breakpoint: 992,
303 settings: {
304 slidesToShow: 2,
305 dots: true,
306 arrows: false
307 }
308 },
309 {
310 breakpoint: 575,
311 settings: {
312 slidesToShow: 1,
313 dots: true,
314 arrows: false
315 }
316 }
317 ]
318 });
319 }
320
321 function setMaxSlideHeightPacks() {
322 var maxHeight = 0;
323
324 $sliderPacks.find('.slick-slide').each(function () {
325 var h = $(this).outerHeight(true);
326 if (h > maxHeight) maxHeight = h;
327 });
328
329 $sliderPacks.find('.slick-track').css('height', maxHeight + 'px');
330 }
331
332
333 // --- EJECUTAR CUANDO EL SLIDER CAMBIA ---
334 $sliderPacks.on('setPosition afterChange init', function () {
335 setMaxSlideHeightPacks();
336 });
337
338 // --- FORZAR CÁLCULO AL INICIALIZAR ---
339 $sliderPacks.trigger('init');
340
341 // --- ACTUALIZAR AL REDIMENSIONAR VENTANA ---
342 $(window).on('resize', function () {
343 setMaxSlideHeightPacks();
344 });
345
346 // Quitar el after al último visible
347 $sliderPacks.on('afterChange init', function(){
348 const $active = $sliderPacks.find('.slick-slide.slick-active');
349 $active.removeClass('is-last-active');
350 $active.last().addClass('is-last-active');
351 });
352 $sliderPacks.trigger('init');
353
354 // --- Recalcular altura al redimensionar ---
355 $(window).on('resize', function() {
356 setTimeout(setMaxSlideHeightPacks, 100);
357 });
358
359 });
360</script>