Error parsing template "Designs/Junget2026/_parsed/PageShopList.parsed.cshtml"
Line 487: (486:1) - The if block is missing a closing "}" character.  Make sure you have a matching "}" character for all the "{" characters within this block, and that none of the "}" characters are being interpreted as markup.

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 2 @{ 3 bool isLocalHost = Dynamicweb.Context.Current.Request.Url.Host.Contains("local.dynamicweb.dk"); 4 string cultureName = Pageview.Area.Culture.Split('-')[0]; 5 } 6 <!doctype html> 7 <html> 8 <head> 9 <script id="CookieConsent" src="https://policy.app.cookieinformation.com/uc.js" 10 data-culture="@cultureName.ToUpper()" data-gcm-version="2.0" type="text/javascript"></script> 11 12 @RenderPartial("/Designs/Junget2026/Master/Partials/Meta.cshtml") 13 14 @if (!isLocalHost) 15 { 16 var masterStyles = Dynamicweb.VestjyskMarketing.Helpers.Utilities.CacheBuster("/Assets/Junget2026/dist/main.css"); 17 <link href="@masterStyles" rel="stylesheet"> 18 } 19 20 @Pageview.Area.Item["HeaderScripts"] 21 22 <script async type="text/plain" data-cookieconsent="marketing" 23 src="https://static.klaviyo.com/onsite/js/klaviyo.js?company_id=W7NjJj"></script> 24 25 @RenderSnippet("GATracking") 26 </head> 27 28 <body class="@(Pageview.User != null ? "signed-in" : "")" data-url-prefix="@Pageview.Area.Culture"> 29 @Pageview.Area.Item["AfterBodyScripts"] 30 31 <div id="MainContent" class="container-fluid bg-white"> 32 @RenderPartial("/Designs/Junget2026/Master/Partials/LanguageRedirector.cshtml") 33 34 @RenderPartial("/Designs/Junget2026/Master/Partials/GlobalMessage.cshtml") 35 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 36 @using Dynamicweb.Frontend.Navigation; 37 @{ 38 var mainUserInHeader = Pageview.User?.CurrentSecondaryUser != null ? Pageview.User.CurrentSecondaryUser : Pageview.User; 39 40 string webshopLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("Webshop"); 41 string logoPath = Model.Area.Item.GetString("Logo"); 42 bool showLanguageSelector = Model.Area.Item.GetBoolean("ShowLanguageSelector"); 43 string cartIconPath = "/Assets/Junget2026/Images/Icons/cart-shopping-sharp-light-full.svg"; 44 string chevronDownIconPath = "/Assets/Junget2026/Images/Icons/chevron-down-sharp-light-full.svg"; 45 var cartQty = Model.Cart.TotalProductsCount; 46 // Salespersons never see a quantity, but must still be able to open the cart aside 47 bool cartAlwaysClickable = mainUserInHeader != null && mainUserInHeader.HasGroup(24); 48 if (cartAlwaysClickable) 49 { 50 cartQty = 0; 51 } 52 string cartAlwaysClickableAttribute = cartAlwaysClickable ? "true" : "false"; 53 string cartButtonStateClasses = cartQty > 0 || cartAlwaysClickable ? "cursor-pointer" : "pointer-events-none cursor-default"; 54 string rootCultureName = Pageview.Area.Culture; 55 string cartLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("CartPage"); 56 var currentAreaId = Dynamicweb.Frontend.PageView.Current().AreaID; 57 var isJunget = new[] { 1, 14, 8, 13 }.Contains(currentAreaId); 58 59 var languages = isJunget 60 ? new[] 61 { 62 new { AreaId = 13, Url = "/", Flag = "da-dk", Label = Translate("Dansk") }, 63 new { AreaId = 14, Url = "/en-gb", Flag = "en-gb", Label = Translate("Engelsk") }, 64 new { AreaId = 8, Url = "/nb-no", Flag = "nb-no", Label = Translate("Norsk") }, 65 } 66 : new[] 67 { 68 new { AreaId = 12, Url = "", Flag = "da-dk", Label = Translate("Dansk") }, 69 new { AreaId = 11, Url = "", Flag = "en-gb", Label = Translate("Engelsk") }, 70 new { AreaId = 9, Url = "", Flag = "nb-NO", Label = Translate("Norsk") }, 71 new { AreaId = 10, Url = "", Flag = "sv-se", Label = Translate("Svensk") }, 72 }; 73 74 string myProfilePageLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("MyJungetPage"); 75 76 // Logo must point at the frontpage of the current language (Danish is the root "/") 77 var currentLanguage = languages.FirstOrDefault(l => l.AreaId == currentAreaId); 78 string logoLink = currentLanguage != null && !string.IsNullOrEmpty(currentLanguage.Url) ? currentLanguage.Url : "/"; 79 } 80 <header class="overflow-hidden lg:overflow-visible lg:py-2"> 81 <div class="container mx-auto"> 82 <div class="flex h-[100px] items-center justify-between lg:h-[70px]"> 83 <div class="m-auto flex-shrink-0 text-center lg:m-0 lg:text-left" data-name="Logo"> 84 <a href="@logoLink" class="no-underline"> 85 <img src="@logoPath" alt="@Translate("Logo")" class="h-[37px] w-[170px]" /> 86 </a> 87 </div> 88 89 <!-- Search Bar. Typeahead results HTML in footer --> 90 <div class="mx-auto hidden max-w-[570px] flex-1 px-4 lg:block"> 91 @RenderPartial("/Designs/Junget2026/Master/Partials/SearchInput.cshtml") 92 </div> 93 94 <!-- Top Right: Utility Links, Language, Cart --> 95 <div class="flex hidden items-center gap-4 lg:flex"> 96 97 <div class="hidden items-center gap-5 md:flex"> 98 99 @if (Model.Area.Item.GetLink("LoginLink") != null) 100 { 101 if (Pageview.User != null) 102 { 103 <a class="text-center font-light text-[12px] text-black" 104 href="@myProfilePageLink">@Translate("HeaderProfileButton", "Mit Junget")</a> 105 <a class="text-center font-light text-[12px] text-black" 106 href="/Admin/Public/ExtranetLogoff.aspx?ID=@Model.ID">@Translate("Log ud")</a> 107 } 108 else 109 { 110 bool showLoginAside = GetPageIdByNavigationTag("ForgotPassword") != Model.ID && GetPageIdByNavigationTag("CustomerPasswordCreate") != Model.ID; 111 112 if (showLoginAside) 113 { 114 <a href="javascript:void(0)" class="text-center font-light text-[12px] text-black" 115 data-aside-open="login-aside">@Translate("Log ind")</a> 116 } 117 else 118 { 119 string loginLink = "/Default.aspx?ID=" + Model.Area.Item.GetLink("LoginLink").PageId; 120 121 <a href="@loginLink" 122 class="text-center font-light text-[12px] text-black">@Translate("Log ind")</a> 123 } 124 } 125 } 126 127 @if (Model.Area.Item.GetItems("HeaderQuicklinks").Any()) 128 { 129 foreach (var quickLink in Model.Area.Item.GetItems("HeaderQuicklinks")) 130 { 131 <a href="@quickLink.GetString("Link")" class="text-center font-light text-[12px] text-black">@quickLink.GetString("Name")</a> 132 } 133 } 134 </div> 135 136 @if (showLanguageSelector) 137 { 138 <div class="group relative"> 139 <button class="flex cursor-pointer items-center gap-1.5 border-0 bg-transparent px-2 py-1 transition-opacity hover:opacity-80" 140 type="button" 141 id="languageDropdown" 142 aria-haspopup="true" 143 aria-expanded="false"> 144 <img src="/Assets/Junget2026/Images/Icons/Flags/@(rootCultureName).svg" width="20" height="15" alt="@Translate("Sprog")" class="block" data-name="Flags" /> 145 <img src="@chevronDownIconPath" alt="Dropdown" class="h-[12px] w-[12px]" /> 146 </button> 147 148 <div class="absolute right-0 top-full h-2 w-full"></div> 149 <div class="invisible absolute right-0 top-full z-50 min-w-[150px] rounded border border-gold/20 bg-white py-2 pt-2 shadow-xl group-hover:visible hover:visible" aria-labelledby="languageDropdown"> 150 @foreach (var lang in languages) 151 { 152 var area = new Dynamicweb.Content.AreaService().GetArea(lang.AreaId); 153 var domainLock = area?.DomainLock ?? ""; 154 var href = !string.IsNullOrEmpty(domainLock) 155 ? "//" + domainLock 156 : (!string.IsNullOrEmpty(lang.Url) ? lang.Url : "#"); 157 var isActive = Pageview.AreaID == lang.AreaId; 158 <a class="flex items-center px-4 py-2 transition-colors duration-200 hover:bg-gold/10 hover:text-gold @(isActive ? "text-gold font-medium" : "")" 159 href="@href"> 160 <img width="20" height="15" src="/Assets/Junget2026/Images/Icons/Flags/@(lang.Flag).svg" alt="@lang.Label" class="mr-2" /> 161 @lang.Label 162 </a> 163 } 164 </div> 165 </div> 166 } 167 168 </div> 169 </div> 170 </div> 171 172 173 <nav class="hidden bg-white lg:block"> 174 <div class="container mx-auto"> 175 <div class="flex h-[65px] items-center justify-between"> 176 177 @{ 178 var navigationSettings = new NavigationSettings() 179 { 180 StartLevel = 1, 181 StopLevel = 3, 182 ExpandMode = ExpandMode.All 183 }; 184 var navigationTemplate = "Navigation/HeaderNav.cshtml"; 185 } 186 @Navigation.RenderNavigation(navigationTemplate, navigationSettings) 187 188 <div class="flex items-center gap-3"> 189 @if (GetPageIdByNavigationTag("Webshop") > 0) 190 { 191 <a href="@webshopLink" class="btn btn-gold btn-md"> 192 @Translate("Webshop") 193 </a> 194 } 195 @if (GetPageIdByNavigationTag("minicartpageid") > 0) 196 { 197 <div class="relative"> 198 <div class="pointer-events-none absolute -right-2 -top-2 flex h-5 w-5 items-center justify-center rounded-full bg-[#948257] text-xs font-bold text-white @(cartQty > 0 ? "" : "hidden")" id="js-cart-count"> 199 @cartQty 200 </div> 201 <button data-aside-open="cart-aside" data-cart-always-clickable="@cartAlwaysClickableAttribute" class="js-cart-button block leading-none no-underline @cartButtonStateClasses" aria-label="@Translate("Indkøbskurv")"> 202 <img src="@cartIconPath" alt="@Translate("Indkøbskurv")" class="w-[22px]" /> 203 </button> 204 </div> 205 } 206 </div> 207 </div> 208 </div> 209 </nav> 210 </header> 211 212 213 @if (Pageview.Page.ID == GetPageIdByNavigationTag("Frontpage") && !isLocalHost) 214 { 215 @RenderPartial("/Designs/Junget2026/Master/Partials/App.cshtml") 216 } 217 218 219 @using Dynamicweb.Frontend.Devices 220 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 221 222 223 224 @RenderPartial("/Designs/Junget2026/Partials/DeliveryBlock.cshtml", Model) 225 226 @if (string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["ProductId"])) 227 { 228 @RenderPartial("/Designs/Junget2026/Partials/TopContent.cshtml", Model) 229 } 230 231 @Model.Placeholder("content", "Content") 232 233 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 234 @using Dynamicweb.Security.UserManagement 235 @using Dynamicweb.Frontend.Navigation; 236 @{ 237 // Footer-specific URLs (reusing common ones from Header if they exist) 238 string footerProfileLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("MyJungetPage"); 239 string footerContactLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("contactpage"); 240 241 // Footer-specific icons (reusing common ones from Header if they exist) 242 string footerPhoneIconPath = "/Assets/Junget2026/Images/Icons/phone-sharp-light-full.svg"; 243 string footerUserIconPath = "/Assets/Junget2026/Images/Icons/user-sharp-light-full.svg"; 244 string footerBarsIconPath = "/Assets/Junget2026/Images/Icons/bars-sharp-light-full.svg"; 245 string footerSearchIconPath = "/Assets/Junget2026/Images/Icons/magnifying-glass-sharp-light-full.svg"; 246 string footerCartIconPath = "/Assets/Junget2026/Images/Icons/cart-shopping-sharp-light-full.svg"; 247 248 string footerColOne = Model.Area.Item.GetString("FooterColumn1Text"); 249 string footerColTwo = Model.Area.Item.GetString("FooterColumn2Text"); 250 string footerColThree = Model.Area.Item.GetString("FooterColumn3Text"); 251 var footerIcons = Model.Area.Item.GetItems("FooterSocialMediaLinks"); 252 var paymentMethodPictures = Model.Area.Item.GetItems("Payment_Methods_Picture"); 253 254 string co2NeutralPicture = Model.Area.Item.GetString("Co2_Neutralt_Picture"); 255 string co2NeutralLink = Model.Area.Item.GetString("Co2_Neutralt_Link"); 256 int miniCartParagraphId = 0; 257 if (Model.Area.Item.GetLink("MinicartLink") != null) 258 { 259 miniCartParagraphId = Model.Area.Item.GetLink("MinicartLink").ParagraphId; 260 } 261 262 User mainUserHeader = Pageview.User?.CurrentSecondaryUser != null ? Pageview.User.CurrentSecondaryUser : Pageview.User; 263 if (mainUserHeader != null && mainUserHeader.HasGroup(24) && Model.Area.Item.GetLink("SalesmanMiniCart") != null) 264 { 265 miniCartParagraphId = Model.Area.Item.GetLink("SalesmanMiniCart").ParagraphId; 266 } 267 268 int loginParagraphId = 0; 269 270 if (Model.Area.Item.GetLink("LoginLink") != null) 271 { 272 loginParagraphId = Model.Area.Item.GetLink("LoginLink").ParagraphId; 273 } 274 275 //Dont render login aside markup if already on login page 276 bool showLoginAsideMarkup = (GetPageIdByNavigationTag("ForgotPassword") != Model.ID && GetPageIdByNavigationTag("CustomerPasswordCreate") != Model.ID) && loginParagraphId > 0; 277 278 int favoriteServiceParagraphId = 0; 279 280 281 if (Model.Area.Item.GetLink("FavoriteService") != null) 282 { 283 favoriteServiceParagraphId = Model.Area.Item.GetLink("FavoriteService").ParagraphId; 284 } 285 286 287 } 288 289 @helper RenderFooterNavItem(string href, string iconPath, string label, bool isButton = false, string dataASide = "", string appendClasses = "") 290 { 291 appendClasses += " min-w-[40px]"; 292 if (isButton) 293 { 294 <button type="button" class="js-mobile-menu-toggle flex cursor-pointer flex-col items-center justify-center border-0 bg-transparent py-2 text-white @appendClasses"> 295 <img src="@iconPath" alt="@label" class="pointer-events-none mb-1 w-[20px] brightness-0 invert" /> 296 <p class="footer-nav-label pointer-events-none">@label</p> 297 </button> 298 } 299 else 300 { 301 string dataASideAttr = (dataASide.Length > 0) ? "data-aside-open='" + dataASide + "' data-close-on-reclick='true'" : ""; 302 if (dataASide.Length > 0) 303 { 304 href = "javascript:void(0)"; 305 } 306 307 <a @dataASideAttr href="@href" class="flex flex-col items-center justify-center py-2 text-white no-underline @appendClasses"> 308 <img src="@iconPath" alt="@label" class="pointer-events-none mb-1 w-[20px] brightness-0 invert" /> 309 <p class="footer-nav-label pointer-events-none">@label</p> 310 </a> 311 } 312 } 313 314 315 <footer class="overflow-hidden bg-white"> 316 317 <!-- Desktop Footer --> 318 <div class="rounded-t-default footer rounded-b-default relative mb-24 mt-8 bg-sand text-primary lg:mb-0 lg:block lg:rounded-b-none @(Model.Area.FirstPage.ID == Model.ID ? "hidden lg:block" : "")" "> 319 <div class="container mx-auto py-8 lg:py-16"> 320 <div class="pointer-events-none absolute bottom-0 right-0 top-16 flex hidden w-[276px] items-center justify-center lg:block"> 321 <div class="rotate-180"> 322 <img src="/Assets/Junget2026/Images/Icons/circle.svg" alt="" class="h-[436px] w-[276px] object-contain" /> 323 </div> 324 </div> 325 326 <div class="relative z-10 flex flex-col gap-10 lg: lg:flex-row lg:gap-14"> 327 <div class="flex w-[250px] flex-col gap-6"> 328 <div> 329 @footerColOne 330 </div> 331 332 <!-- Payment Logos --> 333 <div class="absolute bottom-0 flex items-center gap-2 lg:relative"> 334 @if (paymentMethodPictures.Count > 0) 335 { 336 foreach (var paymentMethodPicture in paymentMethodPictures) 337 { 338 <a href="@paymentMethodPicture.GetString("Link")"> 339 <img src="@paymentMethodPicture.GetString("Icon")" alt="@paymentMethodPicture.GetString("ImageAltTag")" class="h-[19px] object-contain" /> 340 </a> 341 } 342 } 343 </div> 344 </div> 345 346 <div class="flex w-[250px] flex-col gap-8"> 347 <div> 348 @footerColTwo 349 </div> 350 351 <div> 352 <h4>@Translate("Følg med")</h4> 353 <div class="leading-[20px] flex flex-col gap-2 text-[16px] lg:flex-row lg:gap-8"> 354 @if (footerIcons.Count > 0) 355 { 356 foreach (var footerItem in footerIcons) 357 { 358 <a href="@footerItem.GetString("Link")" class="items flex items-center gap-2 text-primary hover:text-gold"> 359 @if (footerItem.GetString("Icon").EndsWith("svg")) 360 { 361 @Dynamicweb.VestjyskMarketing.Helpers.ImageHelper.GetSVG(footerItem.GetString("Icon"), "w-[15px] fill-gold"); 362 } 363 else 364 { 365 <img src="@footerItem.GetString("Icon")" alt="@footerItem.GetString("ImageAltTag")" class="h-[15px] w-[15px]" style="fill: #D4AF37;" /> 366 } 367 <span>@footerItem.GetString("ImageAltTag")</span> 368 </a> 369 } 370 } 371 </div> 372 </div> 373 </div> 374 375 <div class="flex w-[270px] flex-col justify-between"> 376 <div> 377 @footerColThree 378 </div> 379 380 <div class="mb-14 mt-8 lg:absolute lg:bottom-0 lg:right-0 lg:mb-0 lg:mt-auto"> 381 <a href="@co2NeutralLink" target="_blank"> 382 <img src="@co2NeutralPicture" alt="@Translate("CO2 neutralt website")" 383 class="w-[200px] object-contain" /> 384 </a> 385 </div> 386 </div> 387 </div> 388 </div> 389 </div> 390 391 <!-- Mobile Menu Overlay --> 392 <div id="mobileMenu" class="js-mobile-menu-toggle z-[60] fixed inset-0 hidden bg-black bg-opacity-50 transition-opacity duration-300 lg:hidden"> 393 <!-- Menu Panel --> 394 <div class="z-[60] fixed bottom-[70px] left-0 right-0 max-h-[80vh] translate-y-full transform overflow-y-auto rounded-t-[20px] border-t border-gold/20 bg-white shadow-2xl transition-transform duration-300" 395 id="mobileMenuPanel" onclick="event.stopPropagation()"> 396 <div class="px-6 pb-8 pt-6"> 397 <!-- Menu Header --> 398 <div class="mb-6 flex items-center justify-between"> 399 <h2 class="text-[20px] text-primary">@Translate("Menu")</h2> 400 <button class="js-mobile-menu-toggle btn btn-gold-hover x-mark"></button> 401 </div> 402 403 @{ 404 var footerSettings = new NavigationSettings() 405 { 406 StartLevel = 1, 407 StopLevel = 3, 408 ExpandMode = ExpandMode.All 409 }; 410 } 411 @Navigation.RenderNavigation("Navigation/FooterNav.cshtml", footerSettings) 412 </div> 413 </div> 414 </div> 415 416 417 <!-- Bottom Navigation Bar --> 418 <div class="z-[70] fixed bottom-0 left-0 right-0 flex h-[70px] items-center justify-around bg-primary px-4 lg:hidden" data-node-id="61:1252"> 419 <!-- Menu --> 420 @RenderFooterNavItem("#", footerBarsIconPath, Translate("Menu"), true, "") 421 422 <!-- Søg (Search) --> 423 @RenderFooterNavItem("javascript:void(0)", footerSearchIconPath, Translate("Søg"), false, "", "js-mobile-open-search") 424 425 <!-- Kontakt (Contact) - Highlighted Gold Button with Blue Circle --> 426 <div class="relative flex flex-col items-center justify-center" data-node-id="156:2045"> 427 <!-- Blue outer circle --> 428 <div class="absolute -top-[35px] z-10 flex h-[60px] w-[60px] items-center justify-center rounded-full bg-primary" data-node-id="156:2046"> 429 <!-- Gold inner circle --> 430 <div class="shadow-default flex h-[52px] w-[52px] items-center justify-center rounded-full bg-gold"> 431 <a href="@footerContactLink" class="flex h-full w-full items-center justify-center no-underline" data-node-id="61:1261"> 432 <img src="@footerPhoneIconPath" alt="@Translate("Kontakt")" class="w-[22px] brightness-0 invert" /> 433 </a> 434 </div> 435 </div> 436 <p class="footer-nav-label mt-6">@Translate("Kontakt")</p> 437 </div> 438 439 <!-- Profil (Profile) --> 440 @if (loginParagraphId > 0) 441 { 442 if (Pageview.User != null) 443 { 444 @RenderFooterNavItem(footerProfileLink, footerUserIconPath, @Translate("HeaderProfileButton", "Mit Junget"), false) 445 } 446 else 447 { 448 @RenderFooterNavItem("", footerUserIconPath, Translate("Login"), false, "login-aside") 449 } 450 } 451 452 <!-- Kurv (Cart) --> 453 @if (miniCartParagraphId > 0) 454 { 455 @RenderFooterNavItem("", footerCartIconPath, Translate("Kurv"), false, "cart-aside") 456 } 457 </div> 458 </footer> 459 460 <!-- Typeahead search. used in header and mobile --> 461 <div class="js-typeahead-results container absolute left-0 right-0 z-50 mx-auto hidden bg-white pt-12 lg:rounded-default lg:mt-1 lg:border lg:border-gray-300 lg:pt-2 lg:shadow-xl"> 462 <div class="lg:hidden"> 463 @{ 464 var searchInput = new Dictionary<string, object>(); 465 searchInput.Add("isMobile", true); 466 @RenderPartial("/Designs/Junget2026/Master/Partials/SearchInput.cshtml", Model, searchInput); 467 } 468 </div> 469 470 <div class="js-typeahead-spinner flex hidden justify-center py-4"> 471 <div class="h-10 w-10 animate-spin rounded-full border-2 border-gray-300 border-t-gray-600 lg:h-5 lg:w-5"></div> 472 </div> 473 <div class="js-typeahead-content grid grid-cols-1 gap-12 lg:grid-cols-2 lg:gap-0 lg:divide-x lg:divide-gray-200"></div> 474 </div> 475 476 <!-- Asides --> 477 @if (miniCartParagraphId > 0) 478 { 479 var modelAsideModel = new Website.CustomCode.ViewModels.Templates.AsideOverlayViewModel(); 480 modelAsideModel.ClassesContent = "mt-12"; 481 modelAsideModel.paragraphId = miniCartParagraphId; 482 modelAsideModel.AsideId = "cart-aside"; 483 @RenderPartial("/Designs/Junget2026/Partials/AsideOverlay.cshtml", modelAsideModel); 484 } 485 486 487 @if (showLoginAsideMarkup) 488 { 489 var modelAsideModel = new Website.CustomCode.ViewModels.Templates.AsideOverlayViewModel(); 490