Se ha producido un error al procesar la plantilla.
The following has evaluated to null or missing:
==> categoryResponse[0]  [in template "62757443695457#32456#108258" at line 10, column 27]

----
Tip: It's the final [] step that caused this error, not those before it.
----
Tip: If the failing expression is known to 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: #assign categoryId = categoryResponse...  [in template "62757443695457#32456#108258" at line 10, column 5]
----
1<#assign contents = []> 
2<#assign categoryName = ""> 
3<#assign peti = "/headless-delivery/v1.0/sites/" + groupId + "/content-structures?filter=name eq 'Hotel Card'"/> 
4<#assign structures = restClient.get("/headless-delivery/v1.0/sites/" + groupId + "/content-structures?filter=name eq 'Hotel Card'").items/> 
5<#if (structures?size > 0)> 
6    <#assign categoryName = (shortName.getData()!"")> 
7    <#assign vocabularyResponse = restClient.get("/headless-admin-taxonomy/v1.0/sites/" + groupId + "/taxonomy-vocabularies?filter=name eq 'Destinations'").items> 
8    <#assign vocabularyId = vocabularyResponse[0].id> 
9    <#assign categoryResponse = restClient.get("/headless-admin-taxonomy/v1.0/taxonomy-vocabularies/" + vocabularyId + "/taxonomy-categories?filter=name eq '" + categoryName + "'").items> 
10    <#assign categoryId = categoryResponse[0].id> 
11 
12    <#assign response = restClient.get("/headless-delivery/v1.0/content-structures/" + structures[0].id + "/structured-contents?filter=taxonomyCategoryIds/any(t:t eq " + categoryId + ")&pageSize=100")> 
13    <#assign contents = response.items> 
14</#if> 
15<#if (contents?size >0)> 
16    <section class="mp-max-width-section"> 
17        <div class="our-accomodations__wrapper" id="hotelesDestino"> 
18            <h2 class="mp-title-section mp-text-center"> 
19                 
20								<#if containsCircuits?? && getterUtil.getBoolean(containsCircuits.getData())>     
21										Información adicional y alojamientos en ${categoryName?lower_case?cap_first} 
22								<#elseif containCruises?? && getterUtil.getBoolean(containCruises.getData())> 
23								    Información adicional y tipos de camarotes en ${categoryName?lower_case?cap_first} 
24								<#else> 
25                    Nuestros alojamientos en ${categoryName?lower_case?cap_first} 
26                </#if> 
27 
28            </h2> 
29            <div class="swiper"> 
30                <ul class="cards-list__wrapper swiper-wrapper" aria-label="Carousel"> 
31                    <#list contents as content> 
32 
33                    <li class="swiper-slide"> 
34                        <a href="/viajes/${content.friendlyUrlPath}"> 
35                            <div class="card-2__wrapper card-2__wrapper--resume"> 
36                                <div class="image-container"> 
37                                    <#assign imageField = getFieldByName(content.contentFields, "images")> 
38                                    <#if imageField?has_content && imageField.contentFieldValue.image?has_content> 
39                                        <img src="${imageField.contentFieldValue.image.contentUrl}" 
40                                             alt="${imageField.contentFieldValue.image.description}" 
41                                             loading="lazy"> 
42                                    </#if> 
43                                </div> 
44                                <div class="data__wrapper"> 
45                                    <#assign nameField = getFieldByName(content.contentFields, "name")> 
46                                    <#if nameField?has_content> 
47                                        <h3>${nameField.contentFieldValue.data}</h3> 
48                                    </#if> 
49                                    <#assign categoryField = getFieldByName(content.contentFields, "category")> 
50                                    <#if categoryField?has_content> 
51                                        <#assign category = categoryField.contentFieldValue.data> 
52                                        <#attempt> 
53                                            <#assign stars = category?split("*")[0]?number> 
54                                            <#recover> 
55                                                <#assign stars = 0> 
56                                        </#recover> 
57                                        <#if (stars > 0)> 
58                                            <ul class="stars__wrapper" role="img" aria-label="Rating: ${stars} de 5 estrellas"> 
59                                                <#list 1..stars as i> 
60                                                    <li aria-hidden="true"> 
61                                                        <svg width="16" height="16" viewBox="0 0 16 16" data-icon="star"> 
62                                                            <symbol id="ai:local:star"> 
63                                                                <path fill="currentColor" d="m8 12.689-3.89 2.346a.72.72 0 0 1-.436.107.79.79 0 0 1-.396-.147.84.84 0 0 1-.273-.332.648.648 0 0 1-.03-.453l1.032-4.417L.573 6.82a.737.737 0 0 1-.245-.388.702.702 0 0 1 .027-.428.845.845 0 0 1 .233-.34.807.807 0 0 1 .416-.171l4.532-.396L7.296.925a.68.68 0 0 1 .291-.344.819.819 0 0 1 .825 0 .68.68 0 0 1 .291.344l1.76 4.172 4.533.396a.807.807 0 0 1 .415.172.846.846 0 0 1 .233.34.703.703 0 0 1 .028.427.737.737 0 0 1-.245.388l-3.435 2.973 1.033 4.417a.648.648 0 0 1-.031.453.839.839 0 0 1-.273.332.79.79 0 0 1-.396.147.72.72 0 0 1-.435-.107L8 12.689Z"></path> 
64                                                            </symbol> 
65                                                            <use xlink:href="#ai:local:star"></use> 
66                                                        </svg> 
67                                                    </li> 
68                                                </#list> 
69                                            </ul> 
70                                        </#if> 
71                                    </#if> 
72                                    <div class="info__description"> 
73                                        <svg width="24" height="24" viewBox="0 0 12 20" data-icon="distance"> 
74                                            <symbol id="ai:local:distance"> 
75                                                <path fill="currentColor" 
76                                                      d="M6.441 19.5c-1.612 0-2.932-.231-3.96-.693C1.456 18.345.942 17.742.942 17c0-.391.168-.749.504-1.073.336-.324.8-.605 1.394-.842l.287.957c-.347.148-.619.303-.813.467-.195.163-.315.327-.36.491.114.446.598.808 1.452 1.085.854.276 1.866.415 3.036.415 1.158 0 2.168-.139 3.03-.415.862-.277 1.35-.639 1.465-1.085-.045-.164-.165-.325-.36-.482a3.956 3.956 0 0 0-.813-.476l.305-.957c.594.237 1.055.518 1.382.842.328.324.491.682.491 1.073 0 .742-.513 1.345-1.54 1.807-1.027.462-2.347.693-3.96.693Zm0-5.137c.3-.588.656-1.188 1.066-1.8.41-.613.831-1.198 1.263-1.755.643-.839 1.157-1.601 1.543-2.288.385-.686.578-1.543.578-2.57 0-1.228-.434-2.277-1.303-3.146C8.718 1.934 7.67 1.5 6.44 1.5c-1.228 0-2.277.435-3.146 1.304-.869.87-1.304 1.918-1.304 3.146 0 1.027.197 1.884.589 2.57a22.38 22.38 0 0 0 1.533 2.288c.432.557.853 1.142 1.263 1.755.41.612.765 1.212 1.065 1.8Zm0 1.522a.603.603 0 0 1-.403-.163 1.077 1.077 0 0 1-.287-.399c-.435-1.055-.924-1.94-1.47-2.658l-1.565-2.06a12.42 12.42 0 0 1-1.224-2.043c-.334-.707-.5-1.577-.5-2.612 0-1.526.526-2.815 1.58-3.87C3.626 1.028 4.916.5 6.442.5c1.525 0 2.815.527 3.869 1.58 1.053 1.055 1.58 2.344 1.58 3.87 0 1.035-.162 1.905-.488 2.612a10.973 10.973 0 0 1-1.237 2.044c-.482.656-1 1.343-1.552 2.06-.554.716-1.048 1.602-1.482 2.657a1.09 1.09 0 0 1-.287.4.603.603 0 0 1-.404.162Zm0-8.406c.43 0 .792-.148 1.087-.442.295-.295.442-.658.442-1.087 0-.43-.147-.792-.442-1.087a1.477 1.477 0 0 0-1.087-.442c-.43 0-.791.148-1.086.442a1.477 1.477 0 0 0-.442 1.087c0 .43.147.792.442 1.087a1.48 1.48 0 0 0 1.086.442Z"></path> 
77                                            </symbol> 
78                                            <use xlink:href="#ai:local:distance"></use> 
79                                        </svg> 
80                                        <#assign streetField = getFieldByName(content.contentFields, "street")> 
81                                        <#if streetField?has_content> 
82                                            <p>${streetField.contentFieldValue.data}</p> 
83                                        </#if> 
84                                    </div> 
85                                    <#assign codeField = getFieldByName(content.contentFields, "code")> 
86                                    <#assign dataHotel = ""> 
87                                    <#if codeField?has_content> 
88                                        <#assign dataHotel = "data-hotel='" + codeField.contentFieldValue.data + "'"> 
89                                        <div class="data__wrapper__footer d-none"> 
90                                            <p class="data__wrapper__footer__price"> 
91                                                <span class="price-line"> 
92                                                  Desde 
93                                                  <span ${dataHotel} class="price"></span> 
94                                                </span> 
95                                                 
96																								<#-- asigno subtitulo del precio --> 
97                                                 <#assign subtitleForPriceField = getFieldByName(content.contentFields, "subtitleForPrice")> 
98                                                 <#if subtitleForPriceField.contentFieldValue.data?has_content> 
99                                                     <#-- muestro subtitulo del precio (por defecto muestra "por persona") --> 
100                                                     <span class="extra-fees">${subtitleForPriceField.contentFieldValue.data!"por persona"}</span> 
101                                                 <#else> 
102                                                     <span class="extra-fees">por persona</span> 
103                                                 </#if> 
104                                            </p> 
105                                        </div> 
106                                    </#if> 
107                                </div> 
108                            </div> 
109                        </a> 
110                    <li> 
111                        </#list> 
112                </ul> 
113            </div> 
114        </div> 
115    </section> 
116</#if> 
117 
118<#function getFieldByName contentFields, name> 
119    <#list contentFields as field> 
120        <#if field.name == name> 
121            <#return field> 
122        </#if> 
123    </#list> 
124    <#return ""> 
125</#function> 
126 
127<script> 
128(function () { 
129    let hotelElements = [ 
130        <#list contents as content> 
131        { 
132            <#assign nameField = getFieldByName(content.contentFields, "name")> 
133            <#if nameField?has_content> 
134                <#assign title = nameField.contentFieldValue.data> 
135            </#if> 
136            'title': '${title!""}', 
137 
138            <#assign codeField = getFieldByName(content.contentFields, "code")> 
139            <#if codeField?has_content> 
140                <#assign code = codeField.contentFieldValue.data> 
141            </#if> 
142            'code': '${code!""}', 
143            'price': 0, 
144            'index': ${content?index + 1}, 
145            <#assign categoryField = getFieldByName(content.contentFields, "category")> 
146            <#if categoryField?has_content> 
147                <#assign category = categoryField.contentFieldValue.data> 
148                <#attempt> 
149                    <#assign stars = category?split("*")[0]?number> 
150                <#recover> 
151                    <#assign stars = 0> 
152                </#recover> 
153            </#if> 
154            'stars': ${stars}, 
155            <#assign isCircuitField = getFieldByName(content.contentFields, "isCircuit")> 
156            <#if isCircuitField?has_content> 
157                <#assign isCircuit = isCircuitField.contentFieldValue.data> 
158            </#if> 
159            'isCircuit': ${isCircuit!""}, 
160						<#assign isCruiseField = getFieldByName(content.contentFields, "isCruise")> 
161            <#if isCruiseField?has_content> 
162            <#assign isCruise = isCruiseField.contentFieldValue.data> 
163            </#if> 
164            'isCruise': ${isCruise!""}, 
165						<#assign cruiseFeeDiscountField = getFieldByName(content.contentFields, "cruiseFeeDiscount")> 
166            <#assign cruiseFeeDiscountValue = 0> 
167            <#if cruiseFeeDiscountField?has_content> 
168                <#attempt> 
169                    <#assign cruiseFeeDiscountValue = cruiseFeeDiscountField.contentFieldValue.data?number> 
170                <#recover> 
171                    <#assign cruiseFeeDiscountValue = 0> 
172                </#recover> 
173            </#if> 
174            'cruiseFeeDiscount': ${cruiseFeeDiscountValue?int?abs}, 
175        }, 
176        </#list> 
177    ]; 
178    console.log(hotelElements); 
179    //let currentDestination = undefined; 
180		 
181  new Swiper(".our-accomodations__wrapper .swiper", { 
182    direction: 'horizontal', 
183    spaceBetween: 0, 
184    slidesPerView: 'auto', 
185    centeredSlides: true, 
186    breakpoints: { 
187      768: { 
188        allowTouchMove: false, 
189      } 
190    }, 
191    navigation: { 
192      nextEl: '.swiper-button-next', 
193      prevEl: '.swiper-button-prev', 
194    }, 
195    pagination: { 
196      el: '.swiper-pagination', 
197    }, 
198    keyboard: { 
199      enabled: true, 
200      onlyInViewport: true, 
201    }, 
202  }); 
203 
204  async function fetchLiferayDocument(url) { 
205      return fetchLiferayApi("documents/d/guest/" + url); 
206  } 
207 
208  function numberWithCommas (x){ 
209      return x.toFixed(Number.isInteger(x) ? 0 : 2).toString().replace(".", ",").replace(/\B(?=(\d{3})+(?!\d))/g, "."); 
210  } 
211 
212  /* Ajustar el precio para cruceros para descontar las tasas que vienen incluidas en el datos desde API */ 
213  function getPriceExcludingCruiseFees(hotelApiData){ 
214    /*  
215      busco en los elementos globales el elemento [hotelElements] (hotel, circuito o crucero) que  
216      tenga el mismo código que el hotelApiData  
217    */ 
218    const code = +hotelApiData.code; 
219    const hotel = hotelElements.find(h => +h.code === code); 
220    const price = Number(hotelApiData.bestPrice); 
221    const cruiseFeeDiscount = Math.abs(Number(hotel?.cruiseFeeDiscount || 0)); 
222 
223    // Si no se encuentra hotel, no es crucero o el precio no es numerico, devolvemos el precio del API sin tocar 
224    if (!hotel || !hotel.isCruise || !Number.isFinite(price) ) return hotelApiData.bestPrice; 
225     
226    // Cruceros: el API trae tasas incluidas, las descontamos 
227    return price - cruiseFeeDiscount; 
228  } 
229	 
230  async function loadHotelsPrice() { 
231      const hotelsResult = await fetchLiferayDocument("hotels"); 
232      const hotelsJson = await hotelsResult.json(); 
233 
234      const hotelElementsDom = document.querySelectorAll("span[data-hotel]"); 
235      hotelElementsDom.forEach(hotelElement => { 
236          const hotelCode = hotelElement.dataset.hotel; 
237          const hotel = hotelsJson.find(hotel => hotel.code === +hotelCode); 
238          if (!!hotel && !!hotel.bestPrice) { 
239              let updatedPrice = getPriceExcludingCruiseFees(hotel); 
240              hotelElement.innerText = numberWithCommas(updatedPrice) + "€"; 
241              //hotelElement.innerText = numberWithCommas(hotel.bestPrice) + "€"; 
242 
243              const parent = hotelElement.closest(".data__wrapper__footer"); 
244              parent.classList.remove("d-none"); 
245          } 
246      }) 
247  } 
248 
249  loadHotelsPrice(); 
250	 
251})(); //IIFE 
252 
253</script> 

Conoce La Ruta De Carlomagno

Descargar itinerario

Salidas desde Barcelona, Bilbao y Madrid. Consultar salidas desde otros aeropuertos.

La ruta de Carlomagno te invita a seguir los pasos que realizó el emperador Carlomagno en su campaña por la creación del Sacro Imperio Romano Germánico en los siglos VIII y IX. Recorrerás el corazón de Europa pasando por: Bélgica, Alemania y Luxemburgo en una ruta que te acercará a la historia de Europa en la Edad Media a través de las maravillas arquitectónicas y monumentales de algunas de las ciudades más cautivadoras de Europa.

INFORMACIÓN DE INTERÉS

DOCUMENTACIÓN

Los ciudadanos españoles precisan llevar el documento de identidad válido o pasaporte en vigor.

CAMBIO

La moneda oficial de Luxemburgo, Alemania y Bélgica es el Euro.

VESTUARIO

Calzados cómodos y ropa y ligera, adecuada a la estación en la que viajemos.

ELECTRICIDAD

El voltaje del suministro eléctrico normalizado en estos países es de 220/230 voltios a 50 hz. Los enchufes también son los propios del estándar europeo.

REFERENCIA HORARIA

La hora oficial de Luxemburgo, Alemania, Bélgica es la misma que en España peninsular y Baleares.

TELÉFONO

Código de acceso desde España: Luxemburgo (+352) Alemania (+49) Bélgica (+32) Código de acceso desde Luxemburgo, Alemania, Bélgica: (+34)

LOS "IMPRESCINDIBLES" DE LA RUTA DE CARLOMAGNO

BRUSELAS. Ciudad moderna, pero con el esplendor de una urbe clásica, sus calles están cargadas de encanto y de historia.

BRUJAS. Declarada Patrimonio de la Humanidad en el año 2.000, es la ciudad medieval por excelencia. Los canales caracterizan su trazado urbano medieval y gracias a ellos, Brujas es conocida con el sobrenombre de la Venecia del Norte.

DINANT. Encajonada entre el río Mosa y unos acantilados de vértigo, es maravillosa y la convierten en una de las postales más bellas de Valonia.

DURBUY. Conocida como la ciudad más pequeña en la tierra hasta 1977, es también una de las más bonitas en un entorno natural extraordinario.

AQUISGRÁN. Situada en el centro de un triángulo fronterizo, Aquisgrán ha estado comprometida con las raíces espirituales, valores e ideales del continente, tiene un núcleo de gran interés histórico, vinculado estrechamente a la vida de Carlomagno.

COLONIA. Es una de las ciudades más cosmopolita y liberales de Alemania. Cuenta con numerosos atractivos históricos y culturales.

EL VALLE DEL RHIN. Es una zona fértil a cuyas orillas se asoman algunos de los más bellos castillos del país sobre un paisaje pintado de viña y encantadoras villas medievales.

FRANKFURT. Situada en el centro de Alemania a las orillas del rio Main, es una de las metrópolis de referencia de nuestro continente y una de las más importantes histórica y económicamente de todo el país.

LA RUTA ROMÁNTICA. Es una de las rutas vacacionales más populares del país. Y con razón, sus 460 kilómetros aguardan pueblos medievales, iglesias y palacios barrocos, paisajes bucólicos y monumentos únicos como el Palacio de Neuschwanstein.

TRÉVERIS. Fundada en el año 16 a. C. no solo se la conoce como la ciudad más antigua de Alemania, sino que también es una conglomeración importantísima de monumentos arquitectónicos de la antigüedad.

LUXEMBURGO. La ciudad de Luxemburgo es atravesada por los ríos Alzette y Petrusse. Conserva un casco histórico peculiar y un recinto de murallas y fortificaciones único en Europa, Patrimonio de la Humanidad de la UNESCO desde 1994.