Varmelegemer

376 produkter
Ingen filtre er tilgængelig
Error executing template "/Designs/Swift/Paragraph/Swift_ProductListGridView_Custom.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_f915ccc7df0242f09977df71f2e89eb9.<RenderProductList>b__6_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\smartpage\vmelektro.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListGridView_Custom.cshtml:line 510
   at CompiledRazorTemplates.Dynamic.RazorEngine_f915ccc7df0242f09977df71f2e89eb9.Execute() in D:\dynamicweb.net\Solutions\smartpage\vmelektro.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListGridView_Custom.cshtml:line 47
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 4 @using System.Linq 5 @using Dynamicweb.Core 6 7 @functions 8 { 9 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsLazyLoadingForProductInfoEnabled; 10 string liveInfoClass = ""; 11 string productInfoFeed = ""; 12 13 string showPricesWithVat = ""; 14 bool neverShowVat = false; 15 16 ProductListViewModel productList = new ProductListViewModel(); 17 } 18 @{ 19 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 20 { 21 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 22 } 23 24 showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 25 neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 26 27 if (isLazyLoadingForProductInfoEnabled) 28 { 29 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 30 { 31 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 32 if (!string.IsNullOrEmpty(productInfoFeed)) 33 { 34 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 35 } 36 } 37 liveInfoClass = "js-live-info"; 38 } 39 40 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 41 string themePadding = theme != string.Empty ? "p-3" : string.Empty; 42 } 43 44 @if (!string.IsNullOrEmpty(theme)) 45 { 46 <div class="h-100@(theme) @themePadding item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 47 @RenderProductList() 48 </div> 49 } 50 else 51 { 52 <div class="pt-3 item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 53 @RenderProductList() 54 </div> 55 } 56 57 @helper RenderProductList () 58 { 59 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 60 bool anonymousUser = Pageview.User == null; 61 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && !Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsWebServiceConnectionAvailable(); 62 63 string detailsPageLink = Dynamicweb.Context.Current.Items["DetailsPageLink"] != null ? Dynamicweb.Context.Current.Items["DetailsPageLink"].ToString() : ""; 64 string productTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ProductTheme")) ? " theme " + Model.Item.GetRawValueString("ProductTheme").Replace(" ", "").Trim().ToLower() : string.Empty; 65 string productThemePadding = productTheme != string.Empty ? "p-3" : string.Empty; 66 67 string url = Pageview.SearchFriendlyUrl; 68 url = url.LastIndexOf("?") != -1 ? url.Substring(0, url.LastIndexOf("?")) : url; 69 70 //Fix for non-friendly urls 71 if (Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") != null) 72 { 73 string groupId = Dynamicweb.Context.Current.Request.QueryString.Get("GroupID"); 74 url += "?GroupID=" + groupId; 75 } 76 77 bool hideFavoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("HideFavoritesSelector")) ? Model.Item.GetBoolean("HideFavoritesSelector") : false; 78 string staticVariantsLayout = Model.Item.GetRawValueString("StaticVariantsLayout", "hide"); 79 80 var badgeParms = new Dictionary<string, object>(); 81 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 82 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 83 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 84 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 85 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 86 87 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 88 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 89 90 var favoriteParameters = new Dictionary<string, object>(); 91 if (!anonymousUser && !hideFavoritesSelector) 92 { 93 int defaultFavoriteListId = 0; 94 95 IEnumerable<FavoriteList> favoreiteLists = Pageview.User.GetFavoriteLists(); 96 if (favoreiteLists.Count() == 1) { 97 foreach (FavoriteList list in favoreiteLists) { 98 defaultFavoriteListId = list.ListId; 99 } 100 } 101 102 favoriteParameters.Add("ListId", defaultFavoriteListId); 103 } 104 105 if (productList.TotalProductsCount > 0) { 106 int pageSizeSetting = 30; 107 int pageSize = productList.PageSize; 108 pageSize += pageSizeSetting; 109 110 int loadedProducts = productList.PageSize > productList.TotalProductsCount ? productList.TotalProductsCount : productList.PageSize; 111 112 <div class="grid grid-2 grid-lg-3"> 113 @foreach (ProductViewModel product in productList.Products) 114 { 115 var defaultGroupId = product.PrimaryOrDefaultGroup.Id; 116 var selectedDetailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(defaultGroupId)?.Meta.PrimaryPage ?? string.Empty; 117 118 string link = string.IsNullOrEmpty(selectedDetailPage) ? $"{detailsPageLink}&groupid={defaultGroupId}" : selectedDetailPage; 119 link += "&productid=" + product.Id; 120 link += !string.IsNullOrEmpty(product.VariantId) ? "&variantid=" + product.VariantId : ""; 121 122 string imagePath = product?.DefaultImage?.Value ?? ""; 123 imagePath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 124 125 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 126 ratio = ratio != "0" ? ratio : ""; 127 string ratioCssClass = ratio != "" ? " ratio" : ""; 128 string ratioVariable = ratio != "" ? "--bs-aspect-ratio: " + ratio : ""; 129 130 string imagePathXs = "/Admin/Public/GetImage.ashx?width=" + 480 + "&image=" + imagePath + "&format=webp"; 131 string imagePathS = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 132 string imagePathFallBack = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 133 134 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 135 string imageThemePadding = imageTheme != string.Empty ? "p-3" : string.Empty; 136 string imageOutlineStyle = imageTheme == string.Empty ? "style=\"border: 1px solid transparent\"" : string.Empty; 137 138 string imageId = "ProductImage_" + product.Id + product.VariantId; 139 string priceId = "ProductPrice_" + product.Id + product.VariantId; 140 141 bool isDiscontinued = product.Discontinued; 142 if(isDiscontinued) 143 { 144 hidePrice = true; 145 } 146 else 147 { 148 hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && !Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsWebServiceConnectionAvailable(); 149 } 150 151 @* Alternative image *@ 152 var supportedImageFormats = new string[] { ".jpg", ".webp", ".png", ".gif" }; 153 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 154 var selectedAssetCategories = Model.Item.GetRawValueString("AlternativeImageAssets"); 155 IEnumerable<MediaViewModel> alternativeImagesList = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 156 157 if (alternativeImagesList.FirstOrDefault() != null) { 158 alternativeImagesList = alternativeImagesList.OrderByDescending(x => x.Value.Equals(defaultImage)); 159 160 if (alternativeImagesList.First().Value == defaultImage) { 161 alternativeImagesList = alternativeImagesList.Skip(1); 162 } 163 } 164 165 string alternativeImage = alternativeImagesList.FirstOrDefault() != null ? alternativeImagesList.FirstOrDefault().Value : ""; 166 alternativeImage = !string.IsNullOrEmpty(alternativeImage) ? "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + alternativeImage + "&format=webp" : ""; 167 168 @* Badges *@ 169 DateTime createdDate = product.Created.Value; 170 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 171 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 172 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 173 174 @* Main features *@ 175 IEnumerable<string> selectedDisplayGroups = Model.Item.GetRawValueString("MainFeatures").Split(',').ToList(); 176 List<CategoryFieldViewModel> mainFeatures = new List<CategoryFieldViewModel>(); 177 178 foreach (var selection in selectedDisplayGroups) 179 { 180 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) 181 { 182 if (selection == group.Id) { 183 mainFeatures.Add(group); 184 } 185 } 186 } 187 188 189 <article class="position-relative@(productTheme) product-list-item product @liveInfoClass" data-product-id="@product.Id" itemscope> 190 @if (!anonymousUser && !hideFavoritesSelector && product.VariantInfo.VariantInfo == null) { 191 <div class="position-absolute top-0 end-0 my-3" style="z-index: 2"> 192 @RenderPartial("Components/ToggleFavorite.cshtml", product, favoriteParameters) 193 </div> 194 } 195 196 @if (showBadges) { 197 <div class="position-absolute top-0 left-0 p-1 p-lg-2 ps-0 ps-lg-0" style="z-index: 2"> 198 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 199 </div> 200 } 201 202 <div class="d-flex flex-column d-block h-100"> 203 <a href="@link" class="text-decoration-none"> 204 <div class="overflow-hidden@(imageTheme)" @imageOutlineStyle> 205 <div class="ratio" style="@(ratioVariable)"> 206 <div class="d-flex justify-content-center align-items-center"> 207 @if (string.IsNullOrEmpty(alternativeImage)) { 208 <img 209 id="@imageId" 210 srcset=" 211 @imagePathXs 480w, 212 @imagePathS 640w" 213 sizes="(min-width: 992px) 33vw, 50vw" 214 src="@imagePathFallBack" 215 loading="lazy" 216 decoding="async" 217 class="mw-100 mh-100 @imageThemePadding" 218 alt="@product.Name"> 219 } else { 220 <img 221 id="@imageId" 222 src="@imagePathFallBack" 223 loading="lazy" 224 decoding="async" 225 class="mw-100 mh-100 @imageThemePadding" 226 alt="@product.Name" 227 onmouseover="this.src='@alternativeImage'" 228 onmouseout="this.src='@imagePathFallBack'"> 229 } 230 </div> 231 </div> 232 233 234 <div class="position-relative"> 235 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "images") { 236 int variantGroupCount = 0; 237 int showMaxVariantGroups = 2; 238 int showMaxVariants = 3; 239 var productVariantTheme = productTheme != "" ? productTheme : "bg-white"; 240 241 <div 242 class="static-variants w-100 d-none d-lg-block position-absolute left-0 bottom-0 @productTheme" 243 id="StaticVariants_@product.Id" 244 style="pointer-events: none;"> 245 246 @foreach (var variantGroup in product.VariantGroups()) 247 { 248 int variantsCount = 0; 249 250 <div class="d-flex gap-2 mb-2"> 251 @foreach (var variant in variantGroup.Options) 252 { 253 if (variantGroupCount < showMaxVariantGroups) 254 { 255 var optionsCount = variantGroup.Options.Count(); 256 257 if (variantsCount < showMaxVariants) 258 { 259 string optionWidth = !string.IsNullOrEmpty(variant.Color) ? "w-25" : ""; 260 261 <article class="static-variants-option @optionWidth @(productVariantTheme)" title="@product.Name @variant.Name" style="pointer-events: initial;"> 262 @if (!string.IsNullOrEmpty(variant.Color)) 263 { 264 string defaultProductImage = Dynamicweb.Context.Current.Server.UrlEncode(product.DefaultImage.Value); 265 string variantImage = Dynamicweb.Context.Current.Server.UrlEncode(variant.Image.Value); 266 string defaultPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 267 string variantPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 268 269 if (isLazyLoadingForProductInfoEnabled) 270 { 271 <figure class="figure w-100 d-block m-0" data-price-formatted="" onmouseover="switchVariantProduct('@product.Id', this.getAttribute('data-price-formatted'), '@variantImage')" onmouseout="switchVariantProduct('@product.Id', this.getAttribute('data-price-formatted'), '@defaultProductImage')"> 272 <div class="d-flex align-items-center justify-content-center"> 273 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 274 </div> 275 </figure> 276 } 277 else 278 { 279 <figure class="figure w-100 d-block m-0" onmouseover="switchVariantProduct('@product.Id', '@defaultPrice', '@variantImage')" onmouseout="switchVariantProduct('@product.Id', '@variantPrice', '@defaultProductImage')"> 280 <div class="d-flex align-items-center justify-content-center"> 281 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 282 </div> 283 </figure> 284 } 285 } 286 else 287 { 288 <div class="d-flex align-items-center justify-content-center"> 289 @variant.Name 290 </div> 291 } 292 <div class="visually-hidden"> 293 <h4>@Translate("Variant Name")</h4> 294 <p>@product.Name, @variant.Name</p> 295 @if (!hidePrice) { 296 <h4>@Translate("Variant Price")</h4> 297 if (isLazyLoadingForProductInfoEnabled) 298 { 299 <p><span class="text-price js-text-price"></span></p> 300 } 301 else 302 { 303 <p><span class="text-price">@product.Price.PriceFormatted</span></p> 304 } 305 } 306 </div> 307 </article> 308 } 309 310 variantsCount++; 311 312 if (variantsCount == showMaxVariants && optionsCount != showMaxVariants) 313 { 314 int left = optionsCount - showMaxVariants; 315 <div class="variant-option ms-1 d-flex justify-content-center align-items-center"> 316 <span>+@left</span> 317 </div> 318 } 319 } 320 } 321 322 </div> 323 324 variantGroupCount++; 325 } 326 </div> 327 } 328 </div> 329 </div> 330 <div class="@productThemePadding"> 331 <div class="flex-grow-1"> 332 <h3 class="h6 mb-0 text-break">@product.Name @if (!string.IsNullOrEmpty(product.VariantName)) 333 {<text>(@product.VariantName)</text>}</h3> 334 335 @if (!Model.Item.GetBoolean("HideProductNumber")) 336 { 337 <p class="fs-7 opacity-85 mb-2">@product.Number</p> 338 } 339 @if (mainFeatures.Count > 0) 340 { 341 <ul class="p-0 lh-sm opacity-75" style="list-style-position: inside"> 342 @foreach (CategoryFieldViewModel mainFeatureGroup in mainFeatures) 343 { 344 foreach (var field in mainFeatureGroup.Fields) 345 { 346 @RenderField(field.Value) 347 } 348 } 349 </ul> 350 } 351 352 @if (isDiscontinued) 353 { 354 <div class="w-100"> 355 <div class="fw-bold w-100 text-danger">@Translate("Sorry, this product is no longer available").</div> 356 @if (product.ReplacementProduct != null && product.DiscontinuedAction != 0 && !string.IsNullOrWhiteSpace(product?.ReplacementProduct.ProductId)) 357 { 358 List<ProductInfoViewModel> replacementProductList = new List<ProductInfoViewModel>(); 359 replacementProductList.Add(product.ReplacementProduct); 360 var replacementProduct = replacementProductList.GetProducts().FirstOrDefault(); 361 362 var replacementProductDefaultGroupId = replacementProduct.PrimaryOrDefaultGroup.Id; 363 var replacementProductSelectedDetailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(replacementProductDefaultGroupId)?.Meta.PrimaryPage ?? string.Empty; 364 var detailsPageId = GetPageIdByNavigationTag("ProductDetailPage"); 365 string replacementProductLink = string.IsNullOrEmpty(replacementProductSelectedDetailPage) ? $"/Default.aspx?ID={detailsPageId}&groupid={replacementProductDefaultGroupId}" : replacementProductSelectedDetailPage; 366 replacementProductLink += "&productid=" + replacementProduct.Id; 367 replacementProductLink += !string.IsNullOrEmpty(replacementProduct.VariantId) ? "&variantid=" + replacementProduct.VariantId : ""; 368 369 370 <div>@Translate("We recommend this replacement product instead"):</div> 371 372 <a href="@replacementProductLink" class="btn btn-primary w-100">@Translate("Go to the replacement")</a> 373 } 374 </div> 375 } 376 </div> 377 378 @if (!hidePrice) { 379 string priceMin = ""; 380 string priceMax = ""; 381 382 <div> 383 <div> 384 <span content="@product.Price.CurrencyCode" class="d-none"></span> 385 386 @if (showPricesWithVat == "false" && !neverShowVat) { 387 if (isLazyLoadingForProductInfoEnabled) 388 { 389 <span content="" class="d-none"></span> 390 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 391 } 392 else 393 { 394 string beforePrice = product.PriceBeforeDiscount.PriceWithoutVatFormatted; 395 <span content="@product.Price.PriceWithoutVat" class="d-none"></span> 396 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 397 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 398 } 399 } 400 401 } else { 402 403 if (isLazyLoadingForProductInfoEnabled) 404 { 405 <span content="" class="d-none"></span> 406 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 407 } 408 else 409 { 410 string beforePrice = product.PriceBeforeDiscount.PriceFormatted; 411 412 <span content="@product.Price.Price" class="d-none"></span> 413 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 414 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 415 } 416 } 417 } 418 419 @if (showPricesWithVat == "false" && !neverShowVat) { 420 if (isLazyLoadingForProductInfoEnabled) 421 { 422 <span class="text-price js-text-price"><div class="spinner-border" role="status"></div></span> 423 } 424 else 425 { 426 string price = product.Price.PriceWithoutVatFormatted; 427 if (product?.VariantInfo?.VariantInfo != null) { 428 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVatFormatted : ""; 429 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVatFormatted : ""; 430 } 431 if (priceMin != priceMax) { 432 price = priceMin + " - " + priceMax; 433 } 434 <span class="text-price">@price</span> 435 } 436 } else { 437 if (isLazyLoadingForProductInfoEnabled) 438 { 439 <span class="text-price js-text-price"><div class="spinner-border" role="status"></div></span> 440 } 441 else 442 { 443 string price = product.Price.PriceFormatted; 444 if (product?.VariantInfo?.VariantInfo != null) { 445 priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? product.VariantInfo.PriceMin.PriceFormatted : ""; 446 priceMax = product?.VariantInfo?.PriceMax?.PriceFormatted != null ? product.VariantInfo.PriceMax.PriceFormatted : ""; 447 } 448 if (priceMin != priceMax) { 449 price = priceMin + " - " + priceMax; 450 } 451 <span class="text-price">@price</span> 452 } 453 } 454 </div> 455 @if (showPricesWithVat == "false" && !neverShowVat) { 456 if (isLazyLoadingForProductInfoEnabled) 457 { 458 <div class="fs-7 opacity-85 text-price js-text-price-with-vat d-none" data-suffix="@Translate("Incl. VAT")"></div> 459 } 460 else 461 { 462 string price = product.Price.PriceWithVatFormatted; 463 if (product?.VariantInfo?.VariantInfo != null) { 464 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : ""; 465 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : ""; 466 } 467 if (priceMin != priceMax) { 468 price = priceMin + " - " + priceMax; 469 } 470 <div class="fs-7 opacity-85 text-price">@price @Translate("Incl. VAT")</div> 471 } 472 } 473 </div> 474 } 475 476 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "swatches") { 477 var optionCount = product.VariantInfo.VariantInfo.Count(); 478 var showMaxVariants = 5; 479 480 <div class="d-flex flex-row gap-1 align-items-center"> 481 @foreach (VariantInfoViewModel variant in product.VariantInfo.VariantInfo.Take(showMaxVariants)) 482 { 483 <span class="colorbox colorbox-sm rounded-circle border me-1" style="background-color: @variant.OptionColor"></span> 484 } 485 @if (optionCount > showMaxVariants) 486 { 487 int left = optionCount - showMaxVariants; 488 <span class="ms-2">+@left</span> 489 } 490 </div> 491 } 492 </div> 493 </a> 494 </div> 495 </article> 496 } 497 </div> 498 499 <div class="my-3" id="LoadMoreButton"> 500 <div class="text-center d-flex flex-column gap-3"> 501 <div class="opacity-85">@loadedProducts @Translate("out of") @productList.TotalProductsCount @Translate("products")</div> 502 @if (productList.PageCount != 1) { 503 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? "Relevance"; 504 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 505 506 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 507 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 508 509 <form method="get" action="@url" data-response-target-element="content" class="w-100"> 510 @foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 511 { 512 foreach (FacetViewModel facetItem in facetGroup.Facets) 513 { 514 foreach (FacetOptionViewModel facetOption in facetItem.Options) 515 { 516 if (facetOption.Selected) 517 { 518 <input type="hidden" name="@facetItem.QueryParameter" value="[@facetOption.Value]" /> 519 } 520 } 521 } 522 } 523 524 <input type="hidden" name="PageSize" value="@pageSize" /> 525 <input type="hidden" name="SortBy" value="@sortBySelection" /> 526 <input type="hidden" name="RequestType" value="UpdateList" /> 527 528 @if (!string.IsNullOrEmpty(searchQuery)) { 529 <input type="hidden" name="q" value="@searchQuery" /> 530 <input type="hidden" name="SearchLayout" value="@searchLayout" /> 531 } 532 533 @{ 534 string nextPageLink = "/Default.aspx?ID=" + Pageview.Page.ID + "&PageSize=" + pageSize + "&SortBy=" + sortBySelection; 535 536 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 537 { 538 foreach (FacetViewModel facetItem in facetGroup.Facets) 539 { 540 foreach (FacetOptionViewModel facetOption in facetItem.Options) 541 { 542 if (facetOption.Selected) 543 { 544 nextPageLink += "&" + facetItem.QueryParameter + "=[" + facetOption.Value + "]"; 545 } 546 } 547 } 548 } 549 550 nextPageLink += productList?.Group?.Id != null ? "&GroupID=" + productList.Group.Id : ""; 551 nextPageLink += !string.IsNullOrEmpty(searchQuery) ? "&q=" + searchQuery : ""; 552 } 553 554 <a href="@nextPageLink" class="btn btn-primary" type="button" onclick="swift.ProductList.Update(event)" id="LoadMoreButton_@Model.ID">@Translate("Load more products")</a> 555 </form> 556 } 557 </div> 558 </div> 559 560 <script> 561 function switchVariantProduct(id, price, imagesrc) { 562 var productImageElement = document.querySelector("#ProductImage_" + id); 563 var productPriceElement = document.querySelector("#ProductPrice_" + id + " .text-price"); 564 565 if (productPriceElement) { 566 productPriceElement.innerText = price; 567 } 568 569 if (productImageElement) { 570 productImageElement.src = imagesrc; 571 572 var imageSrcset = productImageElement.srcset; 573 imageSrcset = imageSrcset.replace(/image=.*?&/g, 'image=' + imagesrc + "&"); 574 575 productImageElement.srcset = imageSrcset; 576 } 577 } 578 </script> 579 } else { 580 if (!Pageview.IsVisualEditorMode) { 581 <div class="alert alert-dark m-0"> 582 @Translate("We did not find anything matching your search result") 583 </div> 584 } else { 585 <div class="alert alert-dark m-0" role="alert"> 586 <span>@Translate("Product list: The list will be shown here, if any")</span> 587 </div> 588 } 589 } 590 } 591 592 @helper RenderField(FieldValueViewModel field) { 593 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 594 595 if (fieldValue != "") { 596 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 597 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 598 599 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) { 600 fieldValue = ""; 601 602 foreach (FieldOptionValueViewModel option in field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) { 603 fieldValue = option.Name; 604 } 605 } 606 607 bool isColor = false; 608 if (fieldValue.Contains("#") && (Translate(field.Name) == Translate("Color") || Translate(field.Name) == Translate("Colour"))) { 609 isColor = true; 610 } 611 612 if (!string.IsNullOrEmpty(fieldValue)) { 613 if (!isColor) { 614 <li>@(field.Name): @fieldValue</li> 615 } else { 616 <li class="position-relative"> 617 <span class="colorbox-sm" style="background-color: @fieldValue"></span> 618 </li> 619 } 620 } 621 } 622 } 623