Egenproduktion af genbrugsplastEgenproduktion af genbrugsplast
Bestil før kl. 14.00 - så sender vi i dagBestil før kl. 14.00 - så sender vi i dag
Lagerførende på varer til akutopgaverLagerførende på varer til akutopgaver
Gratis beregning og dimensioneringGratis beregning og dimensionering
Error executing template "Designs/Rapido/eCom/Product/NZProductView.cshtml"
System.ArgumentException: Illegal characters in path.
   at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional)
   at System.IO.Path.GetFileName(String path)
   at System.IO.FileInfo.Init(String fileName, Boolean checkHost)
   at System.IO.FileInfo..ctor(String fileName)
   at S_DW_Lauridsen.CustomCode.DocumentInfo.FileInformation(String docCol)
   at CompiledRazorTemplates.Dynamic.RazorEngine_5d36719a92fb4797a60065a1214ff9ca.Execute() in E:\Solutions\S_DW_Lauridsen\lauridsen-live\Files\Templates\Designs\Rapido\eCom\Product\NZProductView.cshtml:line 37
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.DynamicWrapperService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at RazorEngine.Templating.RazorEngineServiceExtensions.RunCompile(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.RunCompile(IRazorEngineService service, ITemplateSource templateSource, String name, Type modelType, Object model, DynamicViewBag viewBag)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2 @using Dynamicweb.Extensibility 3 @using Dynamicweb.Content 4 @using System; 5 @using System.Globalization; 6 @using System.Linq 7 @using System.IO 8 @using Dynamicweb.Core 9 @using System.Web 10 @using Dynamicweb.Ecommerce 11 @using Dynamicweb.Ecommerce.Discounts 12 @using Dynamicweb.Ecommerce.Orders.Discounts 13 @using Dynamicweb.Ecommerce.Products 14 @using Dynamicweb.Ecommerce.Prices 15 @using NLog; 16 @using S_DW_Lauridsen.CustomCode 17 @using Dynamicweb.Security.UserManagement 18 @using NuGet.Versioning 19 @{ 20 21 string favoritPage = String.Format("/Default.aspx?ID={0}&CC20=CreateFormList", GetPageIdByNavigationTag("CustomerFavorites").ToString()); 22 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 23 string productId = GetString("Ecom:Product.ID"); 24 string uniqueId = GetString("Ecom:Product.ID") + GetString("Ecom:Product.VariantID"); 25 // Stock status 26 int stockAmount = GetInteger("Ecom:Product.AvailableAmount"); 27 string currentPrice = GetString("Ecom:Product.Discount.Price.PriceFormatted") == GetString("Ecom:Product.Price.PriceFormatted") ? GetString("Ecom:Product.Price.PriceFormatted") : GetString("Ecom:Product.Discount.Price.PriceFormatted"); 28 string hideHelpText = ""; 29 string requestQuery = GetGlobalValue("Global:Request.Query"); 30 string variantId = HttpContext.Current.Request.QueryString.Get("variantId"); 31 string feedId = pageId + "&ProductID=" + productId + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 32 //CFP bool 33 bool cfp = GetBoolean("Ecom:Product:Field.CFP"); 34 35 // Documents 36 string documentValue = GetString("Ecom:Product:Field.PDF_Path"); 37 var results = DocumentInfo.FileInformation(documentValue); 38 39 40 string externalLink = GetValue("Ecom:Product:Field.ExternalLinks.Value").ToString(); 41 var testList = externalLink.Split(new string[] { "</p>" }, StringSplitOptions.RemoveEmptyEntries).ToList(); 42 43 44 45 int featuresCount = 0; 46 string brand = GetString("Ecom:Product:Field.brand"); 47 bool onlyPreview = Converter.ToBoolean(Pageview.Area.Item["OnlyPreviewForAnonymous"]) && Pageview.User == null; 48 49 foreach (LoopItem customField in GetLoop("CustomFieldValues")) 50 { 51 if (!String.IsNullOrEmpty(customField.GetString("Product.CustomField.Value.Clean")) && customField.GetString("Product.CustomField.Name") != "CustomSticker") 52 { 53 featuresCount++; 54 } 55 } 56 57 foreach (LoopItem customField in GetLoop("ProductCategories")) 58 { 59 foreach (LoopItem field in customField.GetLoop("ProductCategoryFields")) 60 { 61 if (!String.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Value"))) 62 { 63 featuresCount++; 64 } 65 } 66 } 67 68 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 69 { 70 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 71 { 72 if (variantoption.GetBoolean("Ecom:VariantOption.Selected")) 73 { 74 hideHelpText = "u-hidden"; 75 } 76 } 77 } 78 79 int relatedProductsPageSize = 4; 80 int relatedProductsColumnWidth = 3; 81 82 if (Pageview.Device.ToString() == "Mobile") 83 { 84 relatedProductsPageSize = 1; 85 relatedProductsColumnWidth = 12; 86 } 87 88 if (Pageview.Device.ToString() == "Tablet") 89 { 90 relatedProductsPageSize = 3; 91 relatedProductsColumnWidth = 4; 92 } 93 94 string pageNavTag = GetPageIdByNavigationTag("ProductsPage").ToString(); 95 string feedFullUrl = String.Format("/Default.aspx?ID={0}&PageSize={1}&ProdID={2}&feed=true", pageNavTag, relatedProductsPageSize, productId); 96 string relatedProductsFeed = String.Format("/Default.aspx?ID={0}&PageSize={1}&ProdID={2}&feed=true&RelateredeProdukter=", pageNavTag, relatedProductsPageSize, productId); 97 string productContainerId = "Product" + productId; 98 string video = GetString("Ecom:Product:Field.video"); 99 string siteURL = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host; 100 Dynamicweb.Ecommerce.Products.Product currentProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(GetString("Ecom:Product.ID"), GetString("Ecom:Product.VariantID"), GetString("Ecom:Product.LanguageID")); 101 var imagePathValue = Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(currentProduct, "ImagePath"); 102 string imagePath = !string.IsNullOrWhiteSpace(imagePathValue.ToString()) ? "/Files/Images/Ecom/LHI_Products/Images/" + imagePathValue + ".jpg" : ""; 103 string productImage = !string.IsNullOrWhiteSpace(imagePath) ? imagePath : GetString("Ecom:Product.ImageLarge.Default.Clean"); 104 string canonicalURL = GetString("Ecom:Product.Canonical"); 105 string vismaUnitName = !string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.Enhed")) ? GetString("Ecom:Product:Field.Enhed")?.ToLower() : Translate("UnitPriceTextStk"); 106 107 //gallery 108 int imagesCount = 1; 109 List<string> galleryImages = new List<string>(); 110 111 galleryImages.Add(productImage); 112 if (!string.IsNullOrWhiteSpace(video)) 113 { 114 foreach (var image in video.Split('|')) 115 { 116 string videoThumb = String.Format("https://img.youtube.com/vi/{0}/0.jpg", image); 117 galleryImages.Add(videoThumb); 118 imagesCount++; 119 } 120 } 121 122 foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 123 { 124 if (!String.IsNullOrEmpty(alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"))) 125 { 126 string fullImage = "/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 127 galleryImages.Add(fullImage); 128 imagesCount++; 129 } 130 } 131 132 foreach (LoopItem detail in GetLoop("Details")) 133 { 134 string fullImage = "/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + detail.GetString("Ecom:Product:Detail.Image.Clean"); 135 136 if (!String.IsNullOrEmpty(fullImage)) 137 { 138 galleryImages.Add(fullImage); 139 imagesCount++; 140 } 141 } 142 143 string firstImage = galleryImages.FirstOrDefault(); 144 string galleryImagesArray = string.Join(", ", galleryImages); 145 } 146 147 @* Set product canonical URL *@ 148 @SnippetStart("canonical") 149 @{ 150 string host = GetGlobalValue("Global:Request.Host"); 151 string url = GetGlobalValue("Global:Pageview.Url"); 152 int queryIndex = url.IndexOf("?", StringComparison.Ordinal); 153 if (queryIndex > -1) 154 { 155 url = url.Substring(0, queryIndex); 156 } 157 } 158 <link rel="canonical" href="https://@host@url"> 159 @SnippetEnd("canonical") 160 <!-- Trigger for the gallery modal --> 161 <input type="checkbox" id="GalleryModalTrigger" class="modal-trigger" /> 162 163 <!-- Gallery modal --> 164 <div class="modal-container"> 165 <label for="GalleryModalTrigger" id="GalleryModalOverlay" class="modal-overlay"></label> 166 <div class="modal modal--lg modal--full modal-no-bg" id="GalleryModal"> 167 <div class="modal__body"> 168 <div class="gallery-slider js-gallery-slider" data-total-images="@imagesCount" data-images="@galleryImagesArray"> 169 <div class="gallery-slider__image" data-icon-nz="play"> 170 <img id="FullImage" src="@firstImage" class="w-100 js-video-button js-gallery-image" /> 171 </div> 172 <div class="gallery-slider__image-counter" id="FullImage_counter"> 173 </div> 174 <label class="gallery-slider__close-btn" for="GalleryModalTrigger"></label> 175 176 @if (imagesCount > 1) 177 { 178 <button class="gallery-slider__previous-btn" id="FullImage_prev" onclick="Gallery.prevImage('FullImage')"></button> 179 <button class="gallery-slider__next-btn" id="FullImage_next" onclick="Gallery.nextImage('FullImage')"></button> 180 } 181 182 </div> 183 </div> 184 </div> 185 </div> 186 187 <div class="paragraph-container__grid--bleed-x paragraph-container__grid--bleed-y product-view"> 188 <div class="grid product js-product" id="productGrid"> 189 @* Image block with optional thumbs *@ 190 @if (!String.IsNullOrEmpty(productImage)) 191 { 192 <div class="grid__col-md-6 grid__col-sm-6"> 193 <div class="grid grid--bleed product-slider"> 194 @{ 195 int thumbCounter = 0; 196 } 197 <div class="grid__col-2 product-slider__thumbnails dw-mod "> 198 <div class="carousel js-carousel-container u-max-h500px dw-mod"> 199 <div class="thumb-list carousel__container dw-mod m-0"> 200 <div class="carousel__container__slide carousel__container__slide--vertical product-slider__inner dw-mod"> 201 202 @*Main image thumb*@ 203 <div class="carousel__container__slide product-slider__slide dw-mod"> 204 <div class="thumb-list__item thumb-list__item--active dw-mod js-thumb js-thumb-btn js-gallery" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" data-image="/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&DoNotUpscale=true&amp;Compression=75&amp;image=@productImage"> 205 <label for="GalleryModalTrigger"> 206 <img src="/Admin/Public/GetImage.ashx?width=100&amp;height=100&amp;crop=5&amp;DoNotUpscale=true&amp;Compression=75&amp;image=@productImage" class="js-gallery" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="@thumbCounter" onclick="Gallery.openImage(this)" data-image="/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&DoNotUpscale=true&amp;Compression=75&amp;image=@productImage"> 207 </label> 208 </div> 209 </div> 210 211 @{ thumbCounter++; } 212 213 @foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 214 { 215 if (!String.IsNullOrEmpty(alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"))) 216 { 217 string image = "/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 218 string thumb = "/Admin/Public/GetImage.ashx?width=100&amp;height=100&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 219 220 <div class="carousel__container__slide product-slider__slide dw-mod"> 221 <div class="thumb-list__item dw-mod js-thumb-btn js-thumb js-gallery" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" data-image="@image"> 222 <label for="GalleryModalTrigger"> 223 <img src="@thumb" class="js-gallery" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="@thumbCounter" onclick="Gallery.openImage(this)" data-image="@image" data-src="@image"> 224 </label> 225 </div> 226 </div> 227 thumbCounter++; 228 } 229 } 230 231 @foreach (var youtubeLink in video.Split('|')) 232 { 233 if (!String.IsNullOrEmpty(youtubeLink)) 234 { 235 string image = String.Format("https://img.youtube.com/vi/{0}/0.jpg", youtubeLink.Split('?')); 236 string thumb = String.Format("https://img.youtube.com/vi/{0}/0.jpg", youtubeLink.Split('?')); 237 238 <div class="carousel__container__slide product-slider__slide dw-mod"> 239 <a class="d-block thumb-list__item has-video dw-mod js-thumb js-thumb-btn js-video-button js-gallery" data-icon-nz="play" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" data-image="@image" href="@youtubeLink" data-type="youtube" data-toggle="modal"> 240 <label for="GalleryModalTrigger"> 241 <img src="@thumb" class="js-gallery" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="@thumbCounter" onclick="Gallery.openImage(this)" data-image="@image" data-src="@image" data-cookieconsent="ignore"> 242 </label> 243 </a> 244 </div> 245 thumbCounter++; 246 } 247 } 248 249 @foreach (LoopItem detail in GetLoop("Details")) 250 { 251 if (!String.IsNullOrEmpty(detail.GetString("Ecom:Product:Detail.Image.Clean"))) 252 { 253 string image = "/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + detail.GetString("Ecom:Product:Detail.Image.Clean"); 254 string thumb = "/Admin/Public/GetImage.ashx?width=100&amp;height=100&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + detail.GetString("Ecom:Product:Detail.Image.Clean"); 255 256 <div class="carousel__container__slide product-slider__slide dw-mod"> 257 <div class="thumb-list__item dw-mod js-thumb-btn js-thumb js-gallery" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" data-image="@image"> 258 <label for="GalleryModalTrigger"> 259 <img src="@thumb" class="js-gallery" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="@thumbCounter" onclick="Gallery.openImage(this)" data-image="@image" data-src="@image"> 260 </label> 261 </div> 262 </div> 263 thumbCounter++; 264 } 265 } 266 </div> 267 </div> 268 269 <div class="js-carousel-data" data-total-slides="@(imagesCount + 1)" data-carousel-slide-time="0" data-current-slide="0" data-direction="vertical" data-sliding-type="items" slides-in-view="6"> 270 <div class="carousel-prev-btn carousel-prev-btn--vertical dw-mod" onclick="Carousel.GetPreviousSlide(this)"></div> 271 <div class="carousel-next-btn carousel-next-btn--vertical dw-mod" onclick="Carousel.GetNextSlide(this)"></div> 272 </div> 273 274 </div> 275 </div> 276 277 <div class="grid__col-10 product-slider__large-image"> 278 <div class="stickers-container dw-mod"> 279 @{ 280 if (Converter.ToBoolean(Pageview.Area.Item["EnableSaleTags"])) 281 { 282 string contentType = Pageview.Area.Item["EcommerceSaleTagContentType"].ToString(); 283 string text = ""; 284 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 285 286 switch (contentType) 287 { 288 case "Name": 289 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 290 { 291 text = discount.GetString("Ecom:Product.Discount.Name"); 292 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 293 } 294 break; 295 case "Amount": 296 if (GetLoop("ProductDiscounts").Count > 0) 297 { 298 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, GetDouble("Ecom:Product.Discount.Price.Price") - GetDouble("Ecom:Product.Price.Price")); 299 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 300 } 301 break; 302 case "Percents": 303 double percents = 0; 304 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 305 { 306 if (discount.GetDouble("Ecom:Product.Discount.ProductQuantity").Equals(1)) 307 { 308 percents = discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 309 } 310 } 311 if (percents > 0) 312 { 313 text = Math.Round(percents, 0) + "%"; 314 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 315 } 316 break; 317 case "Amount and percents": 318 double amount = 0; 319 double percent = 0; 320 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 321 { 322 if (discount.GetString("Ecom:Product.Discount.Type") == "PERCENT") 323 { 324 percent += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 325 } 326 else if (discount.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 327 { 328 amount += discount.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 329 } 330 } 331 if (percent > 0) 332 { 333 text = percent + "%"; 334 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 335 } 336 if (amount > 0) 337 { 338 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 339 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 340 } 341 break; 342 default: 343 if (GetLoop("ProductDiscounts").Count > 0) 344 { 345 text = Translate("Sale!"); 346 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 347 } 348 break; 349 } 350 } 351 352 if (Converter.ToBoolean(Pageview.Area.Item["NewStickersEnable"]) && GetDate("Ecom:Product.Created").AddDays(Converter.ToDouble(Pageview.Area.Item["NewStickersExpiration"])) > DateTime.Now) 353 { 354 <div class="stickers-container__tag stickers-container__tag--new dw-mod">@Translate("New!")</div> 355 } 356 357 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.CustomSticker.Value"))) 358 { 359 <div class="stickers-container__tag stickers-container__tag--custom dw-mod">@GetString("Ecom:Product:Field.CustomSticker.Value")</div> 360 } 361 } 362 </div> 363 364 <label for="GalleryModalTrigger" class="product__image-container"> 365 <img class="thumb-image-view product__image-container__image js-gallery-slider js-video-button dw-mod" src="/Admin/Public/GetImage.ashx?crop=5&width=550&height=550&Compression=75&image=@productImage" data-current-image="0" data-total-images="@imagesCount" data-images="@galleryImagesArray" data-src="/Admin/Public/GetImage.ashx?crop=5&width=550&height=550&Compression=75&image=@productImage" alt="@GetString("Ecom:Product.Name")" id="Image_@productId" data-for="FullImage" data-number="0" onclick="Gallery.openImageByNum(this)" /> 366 </label> 367 368 </div> 369 </div> 370 </div> 371 } 372 373 @* Primary product informations *@ 374 <div class="grid__col-12 grid__col-md-6 product__info dw-mod"> 375 <div> 376 <h1 class="product__title u-no-margin">@GetString("Ecom:Product.Name") @GetString("Ecom:Product.SelectedVariantComboName")</h1> 377 <small class="x-small text-gray-light font-weight-light">@(!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.Brand")) ? String.Format("{0}: {1}", Translate("Manufacturer"), GetString("Ecom:Product:Field.Brand")) : "") @Translate("product number"): @GetString("Ecom:Product.Number") @(!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.VVSNumber")) ? String.Format("{0}: {1}", Translate("VVS nr."), GetString("Ecom:Product:Field.VVSNumber")) : "") @(!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.DBN")) ? String.Format("{0}: {1}", Translate("DB nr."), GetString("Ecom:Product:Field.DBN")) : "") </small> 378 <div> 379 @* Delivery + stock information *@ 380 @if (onlyPreview) 381 { 382 <div> 383 <h5 class="mb-2">@Translate("LoginText", "Login")</h5> 384 <label for="SignInModalTrigger" class="btn btn--primary u-no-margin sign-in-modal-trigger-button dw-mod" onclick="setTimeout(function() { document.getElementById('LoginUsername').focus() }, 10)">@Translate("Sign in")</label> 385 </div> 386 } 387 388 @* Variants *@ 389 @*@if (GetLoop("VariantGroups").Count > 0) 390 { 391 string containerId = "Variants" + productId; 392 393 <div> 394 <div id="@containerId" data-product-id="@productId"> 395 @foreach (LoopItem variantGoup in GetLoop("VariantGroups")) 396 { 397 <div> 398 <div class="u-bold">@variantGoup.GetString("Ecom:VariantGroup.Name")</div> 399 <div> 400 @foreach (LoopItem variantOption in variantGoup.GetLoop("VariantAvailableOptions")) 401 { 402 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 403 404 if (!string.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.ImgSmall.Clean"))) 405 { 406 <img src="/Admin/Public/GetImage.ashx?width=100&amp;height=50&amp;crop=5&amp;Compression=75&amp;image=/Images/@variantOption.GetString("Ecom:VariantOption.ImgSmall.Clean")" title="@variantOption.GetString("Ecom:VariantOption.Name")" id="@productId@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-product-id="@productId" onclick="Variants.UpdateVariants(this, false, true)" class="btn btn--tag @selected" data-check="@selected" /> 407 } 408 else 409 { 410 <button type="button" data-id="@GetString("Ecom:Product.ID")" id="@productId@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-product-id="@productId" onclick="Variants.UpdateVariants(this, false, true)" class="btn btn--tag @selected" data-check="@selected">@variantOption.GetString("Ecom:VariantOption.Name")</button> 411 } 412 } 413 </div> 414 </div> 415 } 416 </div> 417 <small id="helpText_@productId" class="help-text @hideHelpText">@Translate("Please select variant!")</small> 418 </div> 419 }*@ 420 @if (GetLoop("VariantGroups").Count > 0) 421 { 422 var variantCombinationsObject = new List<Array>(); 423 foreach (LoopItem variantcomb in GetLoop("VariantStockCombinations")) 424 { 425 string[] combinations = variantcomb.GetString("Ecom:VariantStockCombination.VariantID").Split('.'); 426 variantCombinationsObject.Add(combinations); 427 } 428 429 string combinationsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantCombinationsObject).Replace("\"", "\'"); 430 431 var variantGroupsObject = new List<List<String>>(); 432 var selectedItem = new Dictionary<string, string>(); 433 string variantSelection = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("variantId")) ? HttpContext.Current.Request.QueryString.Get("variantId").Replace(".", ",") : ""; 434 435 var selectedText = Translate("Select variant"); 436 437 foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 438 { 439 var variantsObject = new List<String>(); 440 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 441 { 442 variantsObject.Add(variantOption.GetString("Ecom:VariantOption.ID")); 443 444 445 if (variantOption.GetBoolean("Ecom:VariantOption.Selected")) 446 { 447 selectedItem.Add(variantGroup.GetString("Ecom:VariantGroup.ID"), variantOption.GetString("Ecom:VariantOption.Name")); 448 } 449 } 450 variantGroupsObject.Add(variantsObject); 451 } 452 string variantsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantGroupsObject).Replace("\"", "\'"); 453 string productGroupId = HttpContext.Current.Request["GroupId"]; 454 int variantCounter = 0; 455 456 <div class="variants-container"> 457 <div class="js-variants" data-total-variant-groups="@GetLoop("VariantGroups").Count" data-combinations="@combinationsJson" data-variants="@variantsJson" data-selection-complete="UpdatePage" data-page-id="@pageId" data-product-id="@productId" data-group-id="@productGroupId"> 458 @foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 459 { 460 string groupId = variantGroup.GetString("Ecom:VariantGroup.ID"); 461 variantCounter++; 462 <div class="dropdown-container u-margin-bottom--lg"> 463 <div class="product__variant-group-name u-margin-bottom-5px dw-mod">@variantGroup.GetString("Ecom:VariantGroup.Name")</div> 464 <div class="display-value" id="displayValue-@variantCounter" onclick="toggleOptions('selectContainer-@variantCounter')"> 465 <span class="value-text" id="valueText-@variantCounter">@(selectedItem.ContainsKey(variantGroup.GetString("Ecom:VariantGroup.ID")) ? selectedItem[variantGroup.GetString("Ecom:VariantGroup.ID")] : selectedText)</span> 466 <span class="arrow arrow-down" id="arrowControl"></span> 467 </div> 468 <ul tabindex="0" class="select-container" id="selectContainer-@variantCounter" onblur="toggleOptions('selectContainer-@variantCounter')"> 469 @foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 470 { 471 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 472 473 474 475 <li value="@variantOption.GetString("Ecom:VariantOption.ID")" 476 type="button" 477 data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" 478 onclick="MatchVariants.SelectThis(event), selected('@variantOption.GetString("Ecom:VariantOption.Name")','valueText-@variantCounter', 'selectContainer-@variantCounter')" 479 data-variant-group="@groupId" 480 class="btn btn--tag @selected js-variant-option select-option" 481 data-check="@selected">@variantOption.GetString("Ecom:VariantOption.Name")</li> 482 } 483 </ul> 484 </div> 485 } 486 </div> 487 </div> 488 } 489 490 @* BOMProducts *@ 491 @if (GetLoop("BOMProducts").Count > 0) 492 { 493 <h2 class="section-title">@Translate("Including products")</h2> 494 foreach (LoopItem BOMProductItem in GetLoop("BOMProducts")) 495 { 496 string link = "/" + BOMProductItem.GetString("Ecom:Product.LinkGroup.Clean") + (!String.IsNullOrEmpty(BOMProductItem.GetString("Ecom:Product.VariantID")) ? "&VariantID=" + BOMProductItem.GetString("Ecom:Product.VariantID") : ""); 497 <div class="grid__col--border grid"> 498 <div class="grid__cell grid__cell--align-middle-left"> 499 <a href="@link" class="u-pull--left u-margin-right"> 500 <img src="/Admin/Public/GetImage.ashx?width=50&image=@BOMProductItem.GetString("Ecom:Product.ImageSmall.Default.Clean")&Compression=99" /> 501 </a> 502 <a href="@link">@BOMProductItem.GetString("Ecom:Product.Name")</a> 503 </div> 504 </div> 505 } 506 } 507 </div> 508 </div> 509 510 @* Buy block *@ 511 <div class="w-100 mt-5"> 512 <div class="js-handlebars-root dw-mod" id="PriceAndActions" data-template="PricesAndActionsTemplate" data-json-feed="/Default.aspx?ID=@feedId"></div> 513 <input type="hidden" value="@GetString("Ecom:Product.VariantID.Extented")" name="Variant" id="Variant_@GetString("Ecom:Product.ID")" /> 514 </div> 515 <div class="mt-4">@GetString("Ecom:Product:Field.LongDescription")</div> 516 <div class="product-page__specs">@ProductPropertiesMainArea()</div> 517 </div> 518 </div> 519 520 <section class="product-page__product-info"> 521 <div class="grid__col-12 grid__col-lg-9 m-auto"> 522 <div class="nav nav-pills nav-justified"> 523 <a class="nav-item nav-link js-toggle-class js-toggle-retrigger is-active" data-target-retrigger="target-retrigger" data-target=".product-page__content--description">@Translate("Product information")</a> 524 <a class="nav-item nav-link js-toggle-class js-toggle-retrigger" data-target-retrigger="target-retrigger" data-target=".product-page__content--video">@Translate("Documents/Video")</a> 525 <a class="nav-item nav-link js-toggle-class js-toggle-retrigger" data-target-retrigger="target-retrigger" data-target=".product-page__content--accessories">@Translate("Accessories")</a> 526 </div> 527 </div> 528 529 <div class="grid__col-12 grid__col-lg-10 m-auto grid__col--bleed-x"> 530 <div class="grid product-page__content product-page__content--description js-toggle-retrigger is-active"> 531 @* Features lists *@ 532 <div class="grid__col-12 grid__col-md-6 product__features dw-mod"> 533 <h1 class="h3 section-title">@Translate("Product information")</h1> 534 @GetString("Ecom:Product.LongDescription") 535 @GetString("Ecom:Product:Field.description") 536 </div> 537 <div class="grid__col-12 grid__col-md-6 product__features dw-mod"> 538 <h1 class="h3 section-title">@Translate("Product specs")</h1> 539 <div class="product-page__specs">@ProductProperties()</div> 540 </div> 541 </div> 542 <div class="grid product-page__content product-page__content--video js-toggle-retrigger justify-content-center"> 543 <div class="grid__col-12 grid__col-md-8 p-0 p-md-4"> 544 <h1 class="h3 section-title">@Translate("Documents/Video")</h1> 545 <div class="table-responsive small order-list"> 546 <table class="table table-striped product-page-table"> 547 <thead> 548 <tr> 549 <th class="font-weight-bold border-bottom-0" scope="col">@Translate("Name")</th> 550 <th class="font-weight-bold border-bottom-0" scope="col">@Translate("Type")</th> 551 <th class="font-weight-bold border-bottom-0" scope="col">@Translate("Size")</th> 552 </tr> 553 </thead> 554 <tbody> 555 556 @foreach (var documentPath in results) 557 { 558 <tr> 559 <td scope="row"> 560 <a href="@documentPath.FilePath" target="_blank"> 561 <img src="/Files/Images/Lauridsen/icons/icon-pdf.svg" class="product-page-table__icon d-inline-block align-middle mr-3" alt="@documentPath.FileName" /> 562 <span class="d-inline-block align-middle u-underline">@documentPath.FileName</span> 563 </a> 564 </td> 565 <td>@documentPath.FileType.Replace(".pdf", "PDF")</td> 566 <td>@documentPath.FileSize.ToSize(ByteExtension.SizeUnits.KB) KB</td> 567 </tr> 568 } 569 570 571 572 @foreach (var youtubeLink in video.Split('|')) 573 { 574 if (!String.IsNullOrEmpty(youtubeLink)) 575 { 576 int thumbCounter = 0; 577 string image = String.Format("https://img.youtube.com/vi/{0}/0.jpg", youtubeLink); 578 string thumb = String.Format("https://img.youtube.com/vi/{0}/0.jpg", youtubeLink); 579 <tr> 580 <td> 581 <div class="carousel__container__slide dw-mod"> 582 <a class="d-block dw-mod js-thumb-btn js-video-button" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" href="@youtubeLink" data-type="youtube" data-toggle="modal"> 583 <label for="GalleryModalTrigger"> 584 <img src="/Files/Images/Lauridsen/icons/icon-video.svg" class="product-page-table__icon d-inline-block align-middle mr-4" alt="@GetString("Ecom:Product:Field.video")" /> 585 <span class="d-inline-block align-middle u-underline">@GetString("Ecom:Product:Field.video")</span> 586 </label> 587 </a> 588 </div> 589 </td> 590 <td>@GetString("Ecom:Product:Field.video.Name")</td> 591 <td>-</td> 592 </tr> 593 thumbCounter++; 594 } 595 } 596 597 598 599 @foreach (var value in testList) 600 { 601 602 if (externalLink.IsNotNullOrEmpty() && !string.IsNullOrWhiteSpace(value)) 603 { 604 <tr> 605 <td scope="row"> 606 <i class="product-page-table__icon d-inline-block align-middle mr-3 fa fa-link fa-2x"></i> 607 <span class="d-inline-block align-middle u-underline product-external-link">@value</span> 608 </td> 609 <td>@Translate("Link")</td> 610 <td>-</td> 611 </tr> 612 } 613 } 614 </tbody> 615 </table> 616 </div> 617 </div> 618 </div> 619 <div class="grid product-page__content product-page__content--accessories js-toggle-retrigger"> 620 <h1 class="h3 section-title">@Translate("Accessories")</h1> 621 <div class="grid accessories-list dw-mod"> 622 <form name="multiForm" id="multiForm" class="accessories-list__form js-load-more-container" data-initial-load="5" method="post"> 623 <input type="hidden" name="CartCmd" id="CartCmd" value="addMulti" /> 624 @foreach (LoopItem relatedGroup in GetLoop("ProductRelatedGroups").Where(group => group.GetString("Ecom:Product:RelatedGroup.Name") == "Tilbehør" || group.GetString("Ecom:Product:RelatedGroup.Name") == "Reservedele")) 625 { 626 foreach (LoopItem relatedProduct in relatedGroup.GetLoop("RelatedProducts")) 627 { 628 Dynamicweb.Ecommerce.Products.Product currentRelatedProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(relatedProduct.GetString("Ecom:Product.ID"), relatedProduct.GetString("Ecom:Product.VariantID"), relatedProduct.GetString("Ecom:Product.LanguageID")); 629 var relatedProductImagePathValue = Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(currentRelatedProduct, "ImagePath"); 630 string imgUrl = "/Files/Images/missing_image.jpg"; 631 string relatedProductImagePath = !string.IsNullOrWhiteSpace(relatedProductImagePathValue.ToString()) ? "/Files/Images/Ecom/LHI_Products/Images/" + relatedProductImagePathValue + ".jpg" : ""; 632 string relatedProductImage = !string.IsNullOrWhiteSpace(relatedProductImagePath) ? relatedProductImagePath : relatedProduct.GetString("Ecom:Product.ImageLarge.Default.Clean"); 633 634 if (!string.IsNullOrWhiteSpace(relatedProductImage)) 635 { 636 imgUrl = relatedProductImage; 637 } 638 639 string name = relatedProduct.GetString("Ecom:Product.Name"); 640 string number = relatedProduct.GetString("Ecom:Product.Number"); 641 string price = relatedProduct.GetString("Ecom:Product.Price"); 642 string groupId = relatedProduct.GetString("Ecom:Product.PrimaryGroupID"); 643 string id = relatedProduct.GetString("Ecom:Product.ID"); 644 var stock = relatedProduct.GetInteger("Ecom:Product.Stock"); 645 string stockText = relatedProduct.GetString("Ecom:Product:Stock.Text"); 646 string shortDescription = relatedProduct.GetString("Ecom:Product.ShortDescription"); 647 648 649 string link = "Default.aspx?" + "ID=" + GetInteger("Ecom:Product.PrimaryOrCurrentPageID") + "&GroupID=" + relatedProduct.GetString("Ecom:Product.PrimaryOrFirstGroupID") + "&ProductID=" + id; 650 List<Dynamicweb.Security.UserManagement.Group> userGroups = new List<Dynamicweb.Security.UserManagement.Group>(); 651 bool userisLoggedIn = Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn(); 652 bool isEmpty = !userGroups.Any(); 653 654 if (isEmpty && Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn()) 655 { 656 userGroups = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser().Groups.ToList(); 657 } 658 659 <div class="accessories-list__item accessorie grid__col-12 grid__col--bleed-x js-load-more-item is-hidden"> 660 <div class="grid"> 661 <figure class="grid__col-sm-2 grid__col-12 accessorie__figure"> 662 <div class="stickers-container dw-mod"> 663 664 665 666 @if (Converter.ToBoolean(Pageview.Area.Item["EnableSaleTags"])) 667 { 668 string contentType = Pageview.Area.Item["EcommerceSaleTagContentType"].ToString(); 669 string text = ""; 670 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 671 672 673 switch (contentType) 674 { 675 case "Name": 676 foreach (LoopItem relatedDiscounts in GetLoop("ProductDiscounts")) 677 { 678 text = relatedDiscounts.GetString("Ecom:Product.Discount.Name"); 679 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 680 } 681 break; 682 case "Amount": 683 if (GetLoop("ProductDiscounts").Count > 0) 684 { 685 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, GetDouble("Ecom:Product.Discount.Price.Price") - GetDouble("Ecom:Product.Price.Price")); 686 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 687 } 688 break; 689 case "Percents": 690 double percents = 0; 691 if (relatedProduct.GetLoop("ProductDiscounts").Count > 0) 692 { 693 foreach (LoopItem discount in relatedProduct.GetLoop("ProductDiscounts")) 694 { 695 if (discount.GetDouble("Ecom:Product.Discount.ProductQuantity") == 1) 696 { 697 percents = discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 698 } 699 } 700 if (percents > 0) 701 { 702 text = Math.Round(percents, 0) + "%"; 703 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 704 } 705 706 707 } 708 break; 709 case "Amount and percents": 710 double amount = 0; 711 double percent = 0; 712 foreach (LoopItem relatedDiscounts in GetLoop("ProductDiscounts")) 713 { 714 if (relatedDiscounts.GetString("Ecom:Product.Discount.Type") == "PERCENT") 715 { 716 percent += relatedDiscounts.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 717 } 718 else if (relatedDiscounts.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 719 { 720 amount += relatedDiscounts.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 721 } 722 } 723 if (percent > 0) 724 { 725 text = percent + "%"; 726 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 727 } 728 if (amount > 0) 729 { 730 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 731 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 732 } 733 break; 734 default: 735 if (GetLoop("ProductDiscounts").Count > 0) 736 { 737 text = Translate("Sale!"); 738 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 739 } 740 break; 741 } 742 743 744 if (Converter.ToBoolean(Pageview.Area.Item["NewStickersEnable"]) && GetDate("Ecom:Product.Created").AddDays(Converter.ToDouble(Pageview.Area.Item["NewStickersExpiration"])) > DateTime.Now) 745 { 746 <div class="stickers-container__tag stickers-container__tag--new dw-mod">@Translate("New!")</div> 747 } 748 749 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.CustomSticker.Value"))) 750 { 751 <div class="stickers-container__tag stickers-container__tag--custom dw-mod">@GetString("Ecom:Product:Field.CustomSticker.Value")</div> 752 } 753 754 } 755 </div> 756 <div class="grid__cell"> 757 <a href="@link" onclick="Scroll.SavePosition(event)" title="@name"> 758 <img class="grid__cell-img accessorie__image" 759 src="/Admin/Public/GetImage.ashx?width=350&amp;height=350&amp;crop=5&amp;Compression=75&amp;DoNotUpscale=true&amp;image=@imgUrl" 760 alt="@name" /> 761 </a> 762 </div> 763 </figure> 764 <div class="grid__col-12 grid__col-sm-4 accessorie__description"> 765 <a class="" href="@link" onclick="Scroll.SavePosition(event)" title="@name"> 766 <div class="accessorie__number"><b>Vare nr.</b> @number</div> 767 <h3 class="accessorie__name">@name</h3> 768 <div class="accessorie__text">@shortDescription</div> 769 <div class="product-list-item__stock"> 770 <div class="stock-icon ml-0 @(stock > 0 ? "stock-icon--in" : "stock-icon--not")"></div> 771 <span>@stockText</span> 772 </div> 773 <span class="product-card__quantity-alert js-product-quantity-error-@id ">@Translate("Max stock level is reached")</span> 774 </a> 775 </div> 776 777 @if (!onlyPreview) 778 { 779 List<Price> priceCollectionList = new List<Price>(); 780 List<Price> getLowestPriceList = new List<Price>(); 781 List<Price> orderedPriceList = new List<Price>(); 782 List<Price> getPriceCollection = new List<Price>(); 783 784 if (userisLoggedIn) 785 { 786 if (currentProduct.Prices.ToList().Any()) 787 { 788 priceCollectionList = currentProduct.Prices.ToList(); 789 } 790 791 string userPriceGroups = string.Empty; 792 if (userGroups.Any()) 793 { 794 <div class=" grid__col-12 grid__col-sm-3 accessorie__details" style="text-align: center"> 795 @foreach (Price priceItem in priceCollectionList.Where(priceItem => priceItem.ProductId.Equals(uniqueId))) 796 { 797 foreach (Dynamicweb.Security.UserManagement.Group userGroupItem in userGroups.Where(userGroup => userGroup.ID.Equals(Int32.Parse(priceItem.UserGroupId)))) 798 { 799 userPriceGroups = userGroupItem.ID.ToString(); 800 if (userPriceGroups != null && priceCollectionList != null) 801 { 802 Price getLowest = priceCollectionList.Where(priceGroup => priceGroup.UserGroupId.Contains(userPriceGroups)).OrderBy(sortQuantity => sortQuantity.Quantity).ThenBy(sortOrder => sortOrder.Amount).ToList().FirstOrDefault(); 803 getLowestPriceList.Add(getLowest); 804 getPriceCollection = priceCollectionList.Where(priceGroup => priceGroup.UserGroupId.Contains(userPriceGroups)).ToList(); 805 if (getPriceCollection.Exists(check => check.Quantity > 2) && getPriceCollection != null) 806 { 807 orderedPriceList.Add(getPriceCollection.FirstOrDefault()); 808 } 809 } 810 } 811 } 812 @if (userPriceGroups != null && getLowestPriceList.Any()) 813 { 814 string priceWithDiscount = relatedProduct.GetString("Ecom:Product.Discount.Price.PriceFormatted"); 815 816 Price getLowestPrice = getLowestPriceList.OrderBy(lowerPrice => lowerPrice.Amount).ToList().FirstOrDefault(); 817 if (getLowestPrice.Quantity < 2) 818 { 819 <div class="accessorie__price price">@priceWithDiscount</div> 820 <div class=""> 821 @Translate("UnitPriceText") @getLowestPrice.Quantity @vismaUnitName 822 </div> 823 } 824 825 List<LoopItem> priceLoop = relatedProduct.GetLoop("Product.Prices"); 826 if (priceLoop.Any(x => x.GetDouble("Ecom:Product.Prices.Quantity") > 1)) 827 { 828 <div class="js-popup"> 829 830 <a class="js-popup-trigger">@Translate("DiscountText")</a> 831 <div class="js-popup-modal popup_productrelatedview"> 832 <div class="js-popout-close nz-icon icon-nz-close-circled"></div> 833 <ul class="grid__col-12 pt-5 p-0 d-flex flex-row flex-wrap"> 834 835 @foreach (LoopItem priceItem in priceLoop.Where(x => x.GetDouble("Ecom:Product.Prices.Quantity") > 1)) 836 { 837 string relatedVismaUnitName = !string.IsNullOrWhiteSpace(priceItem.GetString("Ecom:Product:Field.Enhed")) ? priceItem.GetString("Ecom:Product:Field.Enhed")?.ToLower() : Translate("UnitPriceTextStk"); 838 <li class="grid__col-lg-6 p-0 mb-0 grid__col-12 align-items-center align-items-xl-start">@Translate("UnitPriceText") @priceItem.GetDouble("Ecom:Product.Prices.Quantity") @relatedVismaUnitName</li> 839 <li class="grid__col-lg-6 p-0 pb-3 grid__col-12 align-items-center align-items-xl-end">@priceItem.GetString("Ecom:Product.Prices.AmountFormatted")</li> 840 } 841 </ul> 842 </div> 843 </div> 844 } 845 } 846 847 </div> 848 if (getLowestPriceList.Any()) 849 { 850 851 if (relatedProduct.GetLoop("VariantGroups").Count > 0) 852 { 853 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 854 <div class="accessorie__controls-inner"> 855 856 <a href="@link" class="btn btn-secondary dw-mod js-scroll-btn d-inline-block px-5">@Translate("Select variant")</a> 857 </div> 858 </div> 859 860 } 861 else 862 { 863 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 864 <div class="accessorie__controls-inner"> 865 <div class="accessorie__button-container d-inline-block"> 866 <button type="button" id="CartButton_@id" class="btn btn--primary accessorie__cart" name="submit" onclick="Cart.AddToCart(event, '@id', document.getElementById('Quantity_@id').value, 'Unit_@id', 'Variant_@id');"> 867 <i class="fa fa-shopping-cart"></i> 868 <span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span> 869 </button> 870 </div> 871 872 <div class="product-card__quantity--condenced product-card__quantity accessorie__quantity"> 873 <input id="Quantity_@id" class="product-card__quantity-input pointer-events js-quantity-input" name="Quantity@accessoriesProduct.Id" data-id="@id" type="number" min="1" max="@stock" value="1"> 874 <span class="product-card__quantity-add js-product-quantity-add" data-icon-nz="chevron-up"></span> 875 <span class="product-card__quantity-subtract js-product-quantity-subtract" data-icon-nz="chevron-down"></span> 876 </div> 877 878 </div> 879 </div> 880 } 881 } 882 else 883 { 884 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 885 <div class="accessorie__controls-inner"> 886 <div class="accessorie__button-container d-inline-block"> 887 <button type="button" id="CartButton_@id" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" name="submit" data-target=".js-target"> 888 <span class="u-hidden-xs u-hidden-xxs"> @Translate("CallForPrice")</span> 889 </button> 890 </div> 891 </div> 892 </div> 893 } 894 } 895 else 896 { 897 <div class=" grid__col-12 grid__col-sm-3 accessorie__details" style="text-align: center"> 898 <div class="accessorie__price price"></div> 899 <div class="accessorie__before-price before-price "></div> 900 <div class=""> 901 </div> 902 <div class="js-popup"> 903 <div class="js-popup-modal popup_productrelatedview"> 904 <div class="js-popout-close nz-icon icon-nz-close-circled"></div> 905 </div> 906 </div> 907 </div> 908 if (getLowestPriceList.Any()) 909 { 910 911 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 912 <div class="accessorie__controls-inner"> 913 914 <div class="accessorie__button-container d-inline-block"> 915 <button type="button" id="CartButton_@id" class="btn btn--primary accessorie__cart" name="submit" onclick="Cart.AddToCart(event, '@id', document.getElementById('Quantity_@id').value, 'Unit_@id', 'Variant_@id');"> 916 <i class="fa fa-shopping-cart"></i> 917 <span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span> 918 </button> 919 </div> 920 921 <div class="product-card__quantity--condenced product-card__quantity accessorie__quantity"> 922 <input id="Quantity_@id" class="product-card__quantity-input pointer-events js-quantity-input" name="Quantity@accessoriesProduct.Id" data-id="@id" type="number" min="1" max="@stock" value="1"> 923 <span class="product-card__quantity-add js-product-quantity-add" data-icon-nz="chevron-up"></span> 924 <span class="product-card__quantity-subtract js-product-quantity-subtract" data-icon-nz="chevron-down"></span> 925 </div> 926 927 </div> 928 </div> 929 } 930 else 931 { 932 933 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 934 <div class="accessorie__controls-inner"> 935 <div class="accessorie__button-container d-inline-block"> 936 <button type="button" id="CartButton_@id" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" name="submit" data-target=".js-target"> 937 <span class="u-hidden-xs u-hidden-xxs"> @Translate("CallForPrice")</span> 938 </button> 939 </div> 940 </div> 941 </div> 942 } 943 } 944 } 945 } 946 else 947 { 948 <div class="grid__col-12 grid__col-sm-6 align-items-center align-items-lg-end"> 949 <div class="grid__cell"> 950 <div class="grid__col-12 pb-0"> 951 <h5>@Translate("LoginText")</h5> 952 </div> 953 <div class="grid__col-12 pb-0"> 954 <label for="SignInModalTrigger" class="btn btn--primary u-no-margin sign-in-modal-trigger-button dw-mod" onclick="setTimeout(function() { document.getElementById('LoginUsername').focus() }, 10)">@Translate("Sign in")</label> 955 </div> 956 </div> 957 </div> 958 } 959 </div> 960 </div> 961 } 962 } 963 <div class="grid__col--bleed-y mb-6"> 964 <a class="btn btn-teritary btn--load-more js-load-more-trigger dw-mod">@Translate("Load more")</a> 965 </div> 966 </form> 967 </div> 968 </div> 969 </div> 970 </section> 971 @if (GetLoop("ProductRelatedGroups").Any()) 972 { 973 <section class="related-products"> 974 <div class="grid related-products__inner-container"> 975 976 <div class="grid__col-xs-12 related-products__headline-container"> 977 <h2 class="related-products__headline h2 section-title section-title--condensed">@Translate("Related products")</h2> 978 </div> 979 980 <div class="grid__col-12 grid__col-md-10 grid__col--bleed m-auto"> 981 <div class="grid"> 982 983 @foreach (LoopItem relatedGroup in GetLoop("ProductRelatedGroups").Where(group => group.GetString("Ecom:Product:RelatedGroup.Name") == "Relaterede produkter")) 984 { 985 foreach (LoopItem related in relatedGroup.GetLoop("RelatedProducts")) 986 { 987 Dynamicweb.Ecommerce.Products.Product currentRelatedProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(related.GetString("Ecom:Product.ID"), related.GetString("Ecom:Product.VariantID"), related.GetString("Ecom:Product.LanguageID")); 988 var relatedProductImagePathValue = Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(currentRelatedProduct, "ImagePath"); 989 string imgUrl = "/Files/Images/missing_image.jpg"; 990 string relatedProductImagePath = !string.IsNullOrWhiteSpace(relatedProductImagePathValue.ToString()) ? "/Files/Images/Ecom/LHI_Products/Images/" + relatedProductImagePathValue + ".jpg" : ""; 991 string relatedProductImage = !string.IsNullOrWhiteSpace(relatedProductImagePath) ? relatedProductImagePath : related.GetString("Ecom:Product.ImageLarge.Default.Clean"); 992 993 if (!string.IsNullOrWhiteSpace(relatedProductImage)) 994 { 995 imgUrl = relatedProductImage; 996 } 997 998 string name = related.GetString("Ecom:Product.Name"); 999 string number = related.GetString("Ecom:Product.Number"); 1000 string price = related.GetString("Ecom:Product.Price"); 1001 string groupId = related.GetString("Ecom:Product.PrimaryGroupID"); 1002 string id = related.GetString("Ecom:Product.ID"); 1003 var stock = related.GetInteger("Ecom:Product.Stock"); 1004 string stockText = related.GetString("Ecom:Product:Stock.Text"); 1005 1006 <div class="grid__col-12 grid__col-sm-6 grid__col-lg-3"> 1007 <div class="related-products__product related-product"> 1008 <a href="@related.GetString("Ecom:Product.Link.Clean")"> 1009 <div class="stickers-container dw-mod"> 1010 1011 @if (Converter.ToBoolean(Pageview.Area.Item["EnableSaleTags"])) 1012 { 1013 string contentType = Pageview.Area.Item["EcommerceSaleTagContentType"].ToString(); 1014 string text = ""; 1015 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 1016 1017 1018 switch (contentType) 1019 { 1020 case "Name": 1021 foreach (LoopItem relatedDiscounts in GetLoop("ProductDiscounts")) 1022 { 1023 text = relatedDiscounts.GetString("Ecom:Product.Discount.Name"); 1024 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 1025 } 1026 break; 1027 case "Amount": 1028 if (GetLoop("ProductDiscounts").Count > 0) 1029 { 1030 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, GetDouble("Ecom:Product.Discount.Price.Price") - GetDouble("Ecom:Product.Price.Price")); 1031 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 1032 } 1033 break; 1034 case "Percents": 1035 double percents = 0; 1036 if (related.GetLoop("ProductDiscounts").Count > 0) 1037 { 1038 foreach (LoopItem discount in related.GetLoop("ProductDiscounts")) 1039 { 1040 if (discount.GetDouble("Ecom:Product.Discount.ProductQuantity") == 1) 1041 { 1042 percents = discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 1043 } 1044 } 1045 if (percents > 0) 1046 { 1047 text = Math.Round(percents, 0) + "%"; 1048 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 1049 } 1050 1051 1052 } 1053 break; 1054 case "Amount and percents": 1055 double amount = 0; 1056 double percent = 0; 1057 foreach (LoopItem relatedDiscounts in GetLoop("ProductDiscounts")) 1058 { 1059 if (relatedDiscounts.GetString("Ecom:Product.Discount.Type") == "PERCENT") 1060 { 1061 percent += relatedDiscounts.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 1062 } 1063 else if (relatedDiscounts.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 1064 { 1065 amount += relatedDiscounts.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 1066 } 1067 } 1068 if (percent > 0) 1069 { 1070 text = percent + "%"; 1071 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 1072 } 1073 if (amount > 0) 1074 { 1075 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 1076 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 1077 } 1078 break; 1079 default: 1080 if (GetLoop("ProductDiscounts").Count > 0) 1081 { 1082 text = Translate("Sale!"); 1083 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 1084 } 1085 break; 1086 } 1087 1088 1089 if (Converter.ToBoolean(Pageview.Area.Item["NewStickersEnable"]) && GetDate("Ecom:Product.Created").AddDays(Converter.ToDouble(Pageview.Area.Item["NewStickersExpiration"])) > DateTime.Now) 1090 { 1091 <div class="stickers-container__tag stickers-container__tag--new dw-mod">@Translate("New!")</div> 1092 } 1093 1094 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.CustomSticker.Value"))) 1095 { 1096 <div class="stickers-container__tag stickers-container__tag--custom dw-mod">@GetString("Ecom:Product:Field.CustomSticker.Value")</div> 1097 } 1098 1099 } 1100 1101 1102 </div> 1103 <img class="related-product__image b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=350&amp;height=350&amp;crop=5&amp;Compression=75&amp;DoNotUpscale=true&amp;image=@imgUrl" alt="@name" /> 1104 <h4 class="related-product__name">@name</h4> 1105 <div class="related-product__number">@Translate("product number") @number</div> 1106 1107 <div class="product-list-item__stock"> 1108 <div class="stock-icon ml-0 @(stock > 0 ? "stock-icon--in" : "stock-icon--not")"></div> 1109 <span>@stockText</span> 1110 </div> 1111 1112 <span class="product-card__quantity-alert js-product-quantity-error-@id ">@Translate("Max stock level is reached")</span> 1113 </a> 1114 1115 @if (!onlyPreview) 1116 { 1117 string priceWithDiscount = related.GetString("Ecom:Product.Discount.Price.Price"); 1118 string currencySymbol = related.GetString("Ecom:Product.Currency.Symbol"); 1119 string priceWithOutDiscount = related.GetString("Ecom:Product.Price.Price"); 1120 bool productHasDiscount = GetBoolean("Ecom:Product.HaveDiscount"); 1121 1122 <div class="related-product__button-container d-inline-block"> 1123 @if (priceWithDiscount != "0,00" || priceWithOutDiscount != "0,00") 1124 { 1125 if (GetString("Ecom:Product.Discount.TotalAmount") != "DKK 0,00") 1126 { 1127 <div class="related-product__price withdiscount">@currencySymbol @priceWithDiscount</div> 1128 } 1129 1130 else 1131 { 1132 <div class="related-product__price withoutdiscount">@currencySymbol @priceWithOutDiscount</div> 1133 } 1134 1135 List<LoopItem> priceLoop = related.GetLoop("Product.Prices"); 1136 if (priceLoop.Any(x => x.GetDouble("Ecom:Product.Prices.Quantity") > 1)) 1137 { 1138 <div class="js-popup"> 1139 <a class="js-popup-trigger">@Translate("DiscountText")</a> 1140 <div class="js-popup-modal popup_productrelatedview"> 1141 <div class="js-popout-close nz-icon icon-nz-close-circled"></div> 1142 <ul class="grid__col-12 pt-5 p-0 d-flex flex-row flex-wrap"> 1143 1144 @foreach (LoopItem priceItem in priceLoop.Where(x => x.GetDouble("Ecom:Product.Prices.Quantity") > 1)) 1145 { 1146 <li class="grid__col-lg-6 p-0 mb-0 grid__col-12 align-items-center align-items-xl-start">@Translate("UnitPriceText") @priceItem.GetDouble("Ecom:Product.Prices.Quantity") @Translate("UnitPriceTextStk")</li> 1147 <li class="grid__col-lg-6 p-0 pb-3 grid__col-12 align-items-center align-items-xl-end">@priceItem.GetString("Ecom:Product.Prices.AmountFormatted")</li> 1148 } 1149 </ul> 1150 </div> 1151 </div> 1152 } 1153 1154 if (related.GetLoop("VariantGroups").Count > 0) 1155 { 1156 <div class="related-product__controls"> 1157 1158 1159 <a href="@related.GetString("Ecom:Product.Link.Clean")" class="btn btn-secondary dw-mod js-scroll-btn d-inline-block px-5">@Translate("Select variant")</a> 1160 1161 </div> 1162 1163 } 1164 else 1165 { 1166 <div class="related-product__controls"> 1167 <div class="product-card__quantity--condenced product-card__quantity related-product__quantity"> 1168 <input id="Quantity_@id" class="product-card__quantity-input pointer-events js-quantity-input" name="Quantity@id" data-id="@id" type="number" min="1" max="@stock" value="1"> 1169 <span class="product-card__quantity-add js-product-quantity-add" data-icon-nz="chevron-up"></span> 1170 <span class="product-card__quantity-subtract js-product-quantity-subtract" data-icon-nz="chevron-down"></span> 1171 </div> 1172 <button type="button" id="CartButton_@id" class="btn btn--primary related-product__cart" name="submit" onclick="Cart.AddToCart(event, '@id', document.getElementById('Quantity_@id').value, 'Unit_@id', 'Variant_@id');"> 1173 <i class="fa fa-shopping-cart"></i> 1174 <span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span> 1175 </button> 1176 </div> 1177 } 1178 1179 1180 } 1181 else 1182 { 1183 <button type="button" id="CartButton_@id" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" name="submit" data-target=".js-target"> 1184 <span class="u-hidden-xs u-hidden-xxs"> @Translate("CallForPrice")</span> 1185 </button> 1186 } 1187 </div> 1188 1189 1190 } 1191 else 1192 { 1193 <div class="related-product__login-label">@Translate("LoginText")</div> 1194 <label for="SignInModalTrigger" class="btn btn--primary u-no-margin sign-in-modal-trigger-button dw-mod related-product__login" onclick="setTimeout(function () { document.getElementById('LoginUsername').focus() }, 10)">@Translate("Sign in")</label> 1195 } 1196 1197 1198 </div> 1199 </div> 1200 1201 1202 1203 1204 } 1205 1206 } 1207 1208 </div> 1209 </div> 1210 </div> 1211 </section> 1212 1213 1214 1215 } 1216 </div> 1217 1218 @* 1219 @if(GetLoop("eCom:Related.CustomersWhoSawThisAlsoSaw").Any()) 1220 { 1221 foreach (LoopItem item in GetLoop("eCom:Related.CustomersWhoSawThisAlsoSaw")) 1222 { 1223 relatedProductsFeed += item.GetString("Ecom:Product.ID"); 1224 relatedProductsFeed += ""; 1225 } 1226 1227 <div class="grid"> 1228 <div class="grid__col-12"> 1229 <div class="bg-gray bg-gray-full-width"> 1230 <h2 class="h1 section-title section-title--condensed">@Translate("ecom-related-products-3", "Related products")</h2> 1231 <div class="js-handlebars-root" id="ProductList_@productId" data-template="ProductContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedProductsFeed" data-preloader="overlay"></div> 1232 </div> 1233 </div> 1234 </div> 1235 } 1236 *@ 1237 1238 @helper ProductPropertiesMainArea() 1239 { 1240 if (GetLoop("CustomFieldValues").Count > 0) 1241 { 1242 var visibleCount = 0; 1243 1244 <div class="specs-list specs-list--5"> 1245 <dl class="table table--clean table--compact product-page__specs-list"> 1246 @foreach (LoopItem customField in GetLoop("CustomFieldValues").Where(customField => customField.GetString("Product.CustomField.System") != "description").Where(customField => customField.GetString("Product.CustomField.System") != "LongDescription").Where(customField => customField.GetString("Product.CustomField.System") != "ShortDescription")) 1247 { 1248 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 1249 1250 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 1251 { 1252 fieldValue = ""; 1253 int count = 0; 1254 1255 foreach (LoopItem customFieldOptions in customField.GetLoop("Product.CustomField.Options").Where(customFieldOptions => !string.IsNullOrWhiteSpace(customFieldOptions.GetString("Product.CustomField.Option.Name")))) 1256 { 1257 if (customFieldOptions.GetBoolean("Product.CustomField.Option.IsSelected")) 1258 { 1259 if (count != 0) 1260 { 1261 fieldValue += ", "; 1262 } 1263 1264 fieldValue += customFieldOptions.GetString("Product.CustomField.Option.Name"); 1265 count++; 1266 } 1267 } 1268 } 1269 1270 if (fieldValue == "False") 1271 { 1272 fieldValue = Translate("No"); 1273 } 1274 1275 if (fieldValue == "True") 1276 { 1277 fieldValue = Translate("Yes"); 1278 } 1279 1280 1281 if (!String.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) 1282 && !String.IsNullOrWhiteSpace(fieldValue) 1283 && customField.GetString("Product.CustomField.Name") != "Custom sticker" 1284 && customField.GetString("Product.CustomField.Name").Contains("Produkt tekst") == true) 1285 { 1286 if (!String.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1287 { 1288 visibleCount++; 1289 <dd class="product-page__specs-value"><a href="@customField.GetString("Document.FullPath")" download title="@Translate("Download")" class="product__document"><span property="identifier">@getIconForFile(fieldValue) @Path.GetFileName(fieldValue)</span></a></dd> 1290 } 1291 else 1292 { 1293 visibleCount++; 1294 <dd class="product-page__specs-value"><span property="identifier">@fieldValue</span></dd> 1295 } 1296 } 1297 } 1298 </dl> 1299 1300 @if (visibleCount > 5) 1301 { 1302 <div class="js-load-more-specs specs-list__trigger"> 1303 <span class="specs-list__load-more">@Translate("Show more")</span> 1304 <span class="specs-list__load-less">@Translate("Show less")</span> 1305 </div> 1306 } 1307 1308 </div> 1309 } 1310 } 1311 @helper ProductProperties() 1312 { 1313 if (GetLoop("CustomFieldValues").Count > 0) 1314 { 1315 var visibleCount = 0; 1316 1317 <div class="specs-list specs-list--10"> 1318 <dl class="table table--clean table--compact product-page__specs-list"> 1319 @foreach (LoopItem customField in GetLoop("CustomFieldValues").Where(customField => customField.GetString("Product.CustomField.System") != "description").Where(customField => customField.GetString("Product.CustomField.System") != "LongDescription").Where(customField => customField.GetString("Product.CustomField.System") != "ShortDescription")) 1320 { 1321 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 1322 1323 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 1324 { 1325 fieldValue = ""; 1326 int count = 0; 1327 1328 foreach (LoopItem customFieldOptions in customField.GetLoop("Product.CustomField.Options").Where(customFieldOptions => !string.IsNullOrWhiteSpace(customFieldOptions.GetString("Product.CustomField.Option.Name")))) 1329 { 1330 if (customFieldOptions.GetBoolean("Product.CustomField.Option.IsSelected")) 1331 { 1332 if (count != 0) 1333 { 1334 fieldValue += ", "; 1335 } 1336 1337 fieldValue += customFieldOptions.GetString("Product.CustomField.Option.Name"); 1338 count++; 1339 } 1340 } 1341 } 1342 if (fieldValue == "False") 1343 { 1344 fieldValue = Translate("No"); 1345 } 1346 1347 if (fieldValue == "True") 1348 { 1349 fieldValue = Translate("Yes"); 1350 } 1351 1352 if (!String.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) 1353 && !String.IsNullOrWhiteSpace(fieldValue) 1354 && customField.GetString("Product.CustomField.Name") != "Custom sticker" 1355 && !customField.GetString("Product.CustomField.Name").Contains("Produktions ansvarlig") 1356 && !customField.GetString("Product.CustomField.Name").Contains("Video") 1357 && !customField.GetString("Product.CustomField.Name").Contains("PDF") 1358 && !customField.GetString("Product.CustomField.Name").Contains("Lokation") 1359 && !customField.GetString("Product.CustomField.Name").Contains("Status") 1360 && !customField.GetString("Product.CustomField.Name").Contains("Produktgr. (CO)") 1361 && !customField.GetString("Product.CustomField.Name").Contains("Produktprisgr. 1 (rabatgruppe)") 1362 && !customField.GetString("Product.CustomField.Name").Contains("Prisliste") 1363 && !customField.GetString("Product.CustomField.Name").Contains("Godkendelse") 1364 && !customField.GetString("Product.CustomField.Name").Contains("Salgsstatistik") 1365 && !customField.GetString("Product.CustomField.Name").Contains("ABC") 1366 && !customField.GetString("Product.CustomField.Name").Contains("Billedefilnr (LFR)") 1367 && !customField.GetString("Product.CustomField.Name").Contains("Rabat gruppe 2") 1368 && !customField.GetString("Product.CustomField.Name").Contains("Visma changed by user") 1369 && !customField.GetString("Product.CustomField.Name").Contains("Visma changed date") 1370 && customField.GetString("Product.CustomField.Value") != "0" 1371 && customField.GetString("Product.CustomField.Value") != "" 1372 && customField.GetString("Product.CustomField.Name").Contains("Produkt tekst") != true) 1373 { 1374 <dt class="product-page__specs-display" width="160">@Translate(customField.GetString("Product.CustomField.Name")): </dt> 1375 if (!String.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1376 { 1377 visibleCount++; 1378 <dd class="text-right product-page__specs-value"><a href="@customField.GetString("Document.FullPath")" download title="@Translate("Download")" class="product__document"><span property="identifier">@getIconForFile(fieldValue) @Path.GetFileName(fieldValue)</span></a></dd> 1379 } 1380 else 1381 { 1382 visibleCount++; 1383 <dd class="text-right product-page__specs-value"><span property="identifier">@fieldValue</span></dd> 1384 } 1385 } 1386 } 1387 </dl> 1388 1389 @if (visibleCount > 10) 1390 { 1391 <div class="js-load-more-specs specs-list__trigger"> 1392 <span class="specs-list__load-more">@Translate("Show more")</span> 1393 <span class="specs-list__load-less">@Translate("Show less")</span> 1394 </div> 1395 } 1396 </div> 1397 } 1398 1399 if (GetLoop("ProductCategories").Count > 0) 1400 { 1401 <dl class="product-page__specs-list"> 1402 @foreach (LoopItem categoryGroup in GetLoop("ProductCategories")) 1403 { 1404 int fieldsCount = 0; 1405 foreach (LoopItem categoryField in categoryGroup.GetLoop("ProductCategoryFields")) 1406 { 1407 if (!String.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Value"))) 1408 { 1409 fieldsCount++; 1410 } 1411 } 1412 if (fieldsCount > 0) 1413 { 1414 <dd class="product-page__specs-display">@categoryGroup.GetString("Ecom:Product.Category.Name")</dd> 1415 1416 foreach (LoopItem categoryField in categoryGroup.GetLoop("ProductCategoryFields")) 1417 { 1418 string fieldValue = categoryField.GetString("Ecom:Product.CategoryField.Value"); 1419 1420 if (fieldValue == "False") 1421 { 1422 fieldValue = Translate("No"); 1423 } 1424 1425 if (fieldValue == "True") 1426 { 1427 fieldValue = Translate("Yes"); 1428 } 1429 1430 if (!String.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Label")) && !String.IsNullOrEmpty(fieldValue)) 1431 { 1432 <dt class="product-page__specs-display">@categoryField.GetString("Ecom:Product.CategoryField.Label"):</dt> 1433 <dd class="text-right product-page__specs-value"><span property="identifier">@fieldValue</span></dd> 1434 } 1435 } 1436 } 1437 } 1438 </dl> 1439 } 1440 } 1441 1442 <script id="PricesAndActionsTemplate" type="text/x-template"> 1443 {{#.}} 1444 1445 @if (!onlyPreview) 1446 { 1447 if (cfp == false) 1448 { 1449 <text> 1450 {{#ifCond hasVariants "!==" "disabled"}} 1451 1452 @if (GetString("Ecom:Product.Discount.TotalAmount") != "DKK 0,00") 1453 { 1454 1455 <small class="text-gray font-weight-light">@Translate("NettoPrice")</small> 1456 <div class="text-gray font-weight-light product__price--discount {{onSale}}">{{#Discount}}{{#if @@first}}{{this.discountCurrency}} {{this.discount}}{{/if}}{{/Discount}}</div> 1457 <br /> 1458 <small class="text-gray font-weight-light">@Translate("ProductDiscount")</small> 1459 <div class="text-gray font-weight-light product__price--discount {{onSale}}">{{#Discount}}{{#if @@first}}{{this.discountCurrency}} {{this.subtractPriceWithoutDecimals}}{{/if}}{{/Discount}}</div> 1460 <br /> 1461 <small class="text-gray font-weight-light">@Translate("PriceWithDiscount")</small> 1462 1463 } 1464 1465 else 1466 { 1467 <small class="text-gray font-weight-light">@Translate("PriceWithoutDiscount")</small> 1468 } 1469 1470 @if (GetLoop("ProductDiscounts").Any()) 1471 { 1472 <div class="h1 my-3 text-gray font-weight-light">{{price}}</div> 1473 } 1474 else 1475 { 1476 <div class="h1 my-3 text-gray font-weight-light">{{price}}</div> 1477 } 1478 1479 {{/ifCond}} 1480 </text> 1481 1482 1483 } 1484 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.Text")) || !String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText"))) 1485 { 1486 if (GetLoop("Product.Prices").Count >= 1) 1487 { 1488 1489 var priceLoop = GetLoop("Product.Prices"); 1490 var excludedIds = "1"; 1491 var priceQuantity = priceLoop.Where(i => !excludedIds.Contains(i.GetString("Ecom:Product.Prices.Quantity"))); 1492 1493 if (GetLoop("Product.Prices").Count > 1 && priceQuantity.Any()) 1494 { 1495 1496 1497 <div class="js-popup"> 1498 <a class="js-popup-trigger">@Translate("DiscountText")</a> 1499 <div class="js-popup-modal popup_productview"> 1500 <div class="js-popout-close nz-icon icon-nz-close-circled"></div> 1501 <ul class="grid__col-12 pt-5 p-0 d-flex flex-row flex-wrap"> 1502 @* FOREACH DISCOUNT LOOP FROM JSON FEED *@ 1503 {{#each Discount}} 1504 {{#unless @@first}} 1505 <li class="grid__col-lg-6 p-0 mb-0 grid__col-12 align-items-center align-items-xl-start">@Translate("UnitPriceText") {{this.discountQuantity}} {{this.vismaUnitName}}</li> 1506 <li class="grid__col-lg-6 p-0 pb-3 grid__col-12 align-items-center align-items-xl-end">{{this.discountCurrency}} {{this.discount}}</li> 1507 {{/unless}} 1508 {{/each}} 1509 1510 </ul> 1511 </div> 1512 </div> 1513 } 1514 } 1515 <br> 1516 1517 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.Text")) || !String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText"))) 1518 { 1519 string stockIcon = GetInteger("Ecom:Product.Stock") > 0 ? "product__stock-icon--in" : "product__stock-icon--not"; 1520 1521 if (cfp == false) 1522 { 1523 <table class="table table--clean delivery-and-stock-info dw-mod"> 1524 <tr> 1525 <td class="u-no-padding"> 1526 <div class="stock-icon ml-0 @stockIcon"></div> 1527 <span class="font-weight-bold">@GetString("Ecom:Product:Stock.Text")</span> 1528 </td> 1529 </tr> 1530 <tr> 1531 @* 1532 @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText"))) 1533 { 1534 <td class="u-no-padding">@Translate("Shipping") @GetString("Ecom:Product:Stock.DeliveryText") @GetString("Ecom:Product:Stock.DeliveryUnit")</td> 1535 } 1536 *@ 1537 </tr> 1538 </table> 1539 } 1540 } 1541 1542 <div class="buttons-collection product__price-actions__actions dw-mod d-inline-block d-lg-flex mt-5 w-100"> 1543 1544 @if (GetBoolean("Ecom:Product:Field.CFP")) 1545 { 1546 <div class="cfp-btn-container pt-4 pt-lg-0"> 1547 <button type="button" id="CartButton_{{id}}" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" name="submit" data-target=".js-target">@Translate("CallForPrice")</button> 1548 </div> 1549 } 1550 1551 else 1552 { 1553 var disabledClass = String.IsNullOrWhiteSpace(variantId) && GetLoop("VariantGroups").Count > 0 ? "disabled" : ""; 1554 @* Product quantity *@ 1555 <div class="product-card__quantity product-card__quantity--condenced"> 1556 <input id="Quantity_{{id}}" class="product-card__quantity-input pointer-events js-quantity-input" data-id="{{id}}" name="Quantity" type="number" min="1" max="@stockAmount" value="1"> 1557 <span class="product-card__quantity-add js-product-quantity-add" data-icon-nz="chevron-up"></span> 1558 <span class="product-card__quantity-subtract js-product-quantity-subtract" data-icon-nz="chevron-down"></span> 1559 </div> 1560 <div class="product-btn-buy-container pt-4 pt-lg-0 pl-lg-3"> 1561 {{#ifCond hasVariants "==" "disabled"}} 1562 <a href="{{link}}" class="btn btn-secondary dw-mod js-scroll-btn d-inline-block px-5 @disabledClass">@Translate("Select variant")</a> 1563 {{else}} 1564 <button type="button" id="CartButton_{{id}}" class="btn btn-primary dw-mod d-inline-block px-5 @disabledClass" name="submit" onclick="Cart.AddToCart(event, '{{productId}}', document.getElementById('Quantity_{{id}}').value, 'Unit_{{id}}', 'Variant_{{productId}}');">@Translate("Add to cart")</button> 1565 {{/ifCond}} 1566 </div> 1567 } 1568 1569 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName"))) 1570 { 1571 string favoriteId = "Favorite" + GetString("Ecom:Product.ID"); 1572 1573 <div id="@favoriteId" class="favorites fav-product-container favorites--md d-inline-block dw-mod p-0 pl-lg-3"> 1574 <label for="FavoriteTrigger" class="btn mb-0 btn-secondary"><span class="pr-2 product__add-to-favorites"></span><small class="x-small">@Translate("Add to list")</small></label> 1575 <input type="checkbox" id="FavoriteTrigger" class="dropdown-trigger"> 1576 <div class="dropdown"> 1577 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 1578 @if (GetLoop("CustomerCenter.ListTypes").Any()) 1579 { 1580 <ul class="list list--clean dw-mod"> 1581 @foreach (LoopItem listType in GetLoop("CustomerCenter.ListTypes")) 1582 { 1583 foreach (LoopItem list in listType.GetLoop("CustomerCenter.ProductLists")) 1584 { 1585 <li> 1586 @{string favLinkType = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? list.GetString("Ecom:Product.RemoveFromThisList") : list.GetString("Ecom:Product.AddToThisListAction");} 1587 @{string isInListIcon = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? "fa fa-star" : "fa fa-star-o";} 1588 <a href="@favLinkType" class="list__link dw-mod"><i class="@isInListIcon"></i> @list.GetValue("Ecom:CustomerCenter.List.Name")</a> 1589 </li> 1590 } 1591 } 1592 </ul> 1593 } 1594 1595 else 1596 { 1597 <p>@Translate("CreateFavoritList")</p><a class="btn-sm btn-primary d-block text-center" href="@favoritPage">@Translate("CreateFavoritListButton")</a> 1598 } 1599 1600 </div> 1601 <label class="dropdown-trigger-off" for="FavoriteTrigger"></label> 1602 </div> 1603 </div> 1604 } 1605 1606 1607 </div> 1608 1609 <span class="product-card__quantity-alert js-product-quantity-error-{{id}}">@Translate("Max stock level is reached")</span> 1610 } 1611 } 1612 1613 else 1614 { 1615 <button type="button" id="CartButton_{{id}}" class="u-hidden"></button> 1616 } 1617 {{/.}} 1618 </script> 1619 1620 <script id="Units" type="text/x-template"> 1621 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '/Default.aspx?ID=@feedId&UnitID={{value}}')">{{name}}</div> 1622 </script> 1623 1624 1625 @* Script templates for related products *@ 1626 <script id="ProductPreRenderContainer" type="text/x-template"> 1627 <div class="u-h600px u-full-width"> 1628 <div class="grid"> 1629 <div class="grid__col-12"> 1630 <div class="pre-render-element pre-render-element--md"></div> 1631 </div> 1632 </div> 1633 </div> 1634 </script> 1635 1636 <script id="ProductContainer" type="text/x-template"> 1637 {{#.}} 1638 <div class="u-min-h400px u-full-width"> 1639 <div class="grid"> 1640 <div class="grid__col-45px grid__col--bleed-x"> 1641 <div class="grid__cell grid__cell--align-middle-left"> 1642 <button class="btn btn--condensed btn--clean {{prevdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{prevPage}}')" {{prevdisabled}}><i class="fa fa-chevron-left fa-2x"></i></button> 1643 </div> 1644 </div> 1645 <div class="grid__col-auto grid__col--bleed-x"> 1646 <div id="ProductsContainer" class="grid product-list dw-mod"> 1647 {{#ProductsContainer}} 1648 <div id="Product{{productId}}" class="grid__col-@relatedProductsColumnWidth product-list__list-item dw-mod"> 1649 <div class="product-list__inner"> 1650 {{#Product}} 1651 <div class="grid__cell product-list__grid-item__image dw-mod {{noImage}}"> 1652 <div class="stickers-container dw-mod"> 1653 {{#Stickers}} 1654 {{>Sticker}} 1655 {{/Stickers}} 1656 </div> 1657 <a href="{{link}}" onclick="Scroll.SavePosition(event)"><img class="grid__cell-img grid__cell-img--centered b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=300&amp;height=300&amp;crop=5&amp;Compression=75&amp;image={{image}}" alt="{{name}}" /></a> 1658 </div> 1659 1660 <div class="grid__cell product-list__grid-item__price-info {{shortGridInfo}} dw-mod"> 1661 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-condensed-text">{{name}}</h6></a> 1662 <div class="item-number dw-mod">{{number}}</div> 1663 1664 @if (!onlyPreview && cfp == true) 1665 { 1666 <div class="price dw-mod">{{price}}</div> 1667 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 1668 } 1669 </div> 1670 1671 <div class="product-list__grid-item__footer dw-mod"> 1672 <div class="u-ta-center"> 1673 1674 @if (!onlyPreview && cfp == true) 1675 { 1676 <a href="{{link}}" id="CartButton_{{id}}" class="btn btn--secondary text-uppercase u-no-margin dw-mod">@Translate("View")</a> 1677 } 1678 else 1679 { 1680 <h5 class="mb-2">@Translate("LoginText", "Login")</h5> 1681 <label for="SignInModalTrigger" class="btn btn--primary u-no-margin sign-in-modal-trigger-button dw-mod" onclick="setTimeout(function () { document.getElementById('LoginUsername').focus() }, 10)">@Translate("Sign in")</label> 1682 } 1683 </div> 1684 </div> 1685 {{/Product}} 1686 </div> 1687 </div> 1688 {{/ProductsContainer}} 1689 </div> 1690 </div> 1691 1692 <div class="grid__col-45px grid__col--bleed-x"> 1693 <div class="grid__cell grid__cell--align-middle-right"> 1694 <button class="btn btn--condensed btn--clean {{nextdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{nextPage}}')" {{nextdisabled}}><i class="fa fa-chevron-right fa-2x"></i></button> 1695 </div> 1696 </div> 1697 1698 </div> 1699 </div> 1700 {{/.}} 1701 </script> 1702 1703 <script id="Sticker" type="text/x-template"> 1704 <div class="stickers-container__tag {{className}} dw-mod">{{text}}</div> 1705 </script> 1706 1707 @* Units templates *@ 1708 1709 <script id="UnitOption" type="text/x-template"> 1710 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}&rid={{id}}')">{{name}}</div> 1711 </script> 1712 1713 1714 @*Variants data generation*@ 1715 1716 <script> 1717 document.addEventListener("DOMContentLoaded", function (event) { 1718 var variants = []; 1719 1720 document.getElementById("productGrid").addEventListener('contentLoaded', function (e) { 1721 if (e.srcElement.classList.contains("js-variants-wrap")) { 1722 Variants.SetVariantOptionStatesForProductList(e.srcElement); 1723 } 1724 }, false); 1725 1726 @foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 1727 { 1728 <text>var optionsArray = [];</text> 1729 1730 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 1731 { 1732 string variantSelection = variantoption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 1733 1734 <text> 1735 var option = new Variants.VariantOption("@uniqueId", "@GetString("Ecom:Product.ID")", "@variantoption.GetValue("Ecom:VariantOption.ID")", "@variantoption.GetString("Ecom:VariantOption.Name")", "@variantSelection", "", "@variantoption.GetString("Ecom:VariantOption.Color")", "@variantoption.GetString("Ecom:VariantOption.ImgSmall.Clean")"); 1736 optionsArray.push(option); 1737 </text> 1738 } 1739 1740 <text> 1741 var group = new Variants.VariantGroup("@GetString("Ecom:Product.ID")_@variantgroup.GetValue("Ecom:VariantGroup.ID")", "@variantgroup.GetValue("Ecom:VariantGroup.Name")", optionsArray); 1742 variants.push(group); 1743 </text> 1744 } 1745 1746 var combinations = []; 1747 @foreach (LoopItem variantcomb in GetLoop("VariantStockCombinations")) 1748 { 1749 <text> 1750 combinations.push(new Variants.CombinationItem("@variantcomb.GetValue("Ecom:VariantStockCombination.VariantID")")); 1751 </text> 1752 } 1753 1754 variants = variants.sort(function (a, b) { 1755 var firstVariantId = a.VariantOptions[0].variantId; 1756 for (var i = 0; i < combinations.length; i++) { 1757 var combinationIndex = combinations[i].id.indexOf(firstVariantId); 1758 if (combinationIndex != -1) { 1759 return combinationIndex; 1760 } 1761 } 1762 //should never happen 1763 return 0; 1764 }); 1765 1766 Variants.SetProductFeedId('@feedId'); 1767 Variants.SetProductUrl('/@GetString("Ecom:Product.VariantLinkGroup.Clean")'); 1768 1769 HandlebarsBolt.SetDataInCache(("Variants" + "@productId"), variants); 1770 HandlebarsBolt.SetDataInCache(("Combinations" + "@productId"), combinations); 1771 1772 document.getElementById("PriceAndActions").addEventListener('contentLoaded', function (e) { 1773 Variants.InitVariants(variants, combinations, "@productId", "@uniqueId"); 1774 }, false); 1775 1776 1777 Handlebars.registerHelper('compare', function (lvalue, operator, rvalue, options) { 1778 1779 var operators, result; 1780 1781 if (arguments.length < 3) { 1782 throw new Error("Handlerbars Helper 'compare' needs 2 parameters"); 1783 } 1784 1785 if (options === undefined) { 1786 options = rvalue; 1787 rvalue = operator; 1788 operator = "==="; 1789 } 1790 1791 operators = { 1792 '==': function (l, r) { return l == r; }, 1793 '===': function (l, r) { return l === r; }, 1794 '!=': function (l, r) { return l != r; }, 1795 '!==': function (l, r) { return l !== r; }, 1796 '<': function (l, r) { return l < r; }, 1797 '>': function (l, r) { return l > r; }, 1798 '<=': function (l, r) { return l <= r; }, 1799 '>=': function (l, r) { return l >= r; }, 1800 'typeof': function (l, r) { return typeof l == r; } 1801 }; 1802 1803 if (!operators[operator]) { 1804 throw new Error("Handlerbars Helper 'compare' doesn't know the operator " + operator); 1805 } 1806 1807 result = operators[operator](lvalue, rvalue); 1808 1809 if (result) { 1810 return options.fn(this); 1811 } else { 1812 return options.inverse(this); 1813 } 1814 1815 }); 1816 1817 1818 }); 1819 </script> 1820 1821 @functions { 1822 string getIconForFile(string fileName) 1823 { 1824 string ext = Path.GetExtension(fileName); 1825 string icon = ""; 1826 switch (ext.ToLower()) 1827 { 1828 case ".xls": 1829 case ".xlsx": 1830 icon = "fa-file-excel-o"; 1831 break; 1832 case ".ppt": 1833 case ".pptx": 1834 icon = "fa-file-powerpoint-o"; 1835 break; 1836 case ".doc": 1837 case ".docx": 1838 icon = "fa-file-word-o"; 1839 break; 1840 case ".jpg": 1841 case ".jpeg": 1842 case ".png": 1843 case ".gif": 1844 case ".pdf": 1845 return "<img class='product__document-icon b-lazy' src='/Files/Images/placeholder.gif' data-src='/Admin/Public/GetImage.ashx?crop=5&height=70&width=120&Compression=75&DoNotUpscale=true&image=" + fileName + "' />"; 1846 default: 1847 icon = "fa-file-o"; 1848 break; 1849 } 1850 return "<i class='fa " + icon + "'></i> "; 1851 } 1852 1853 public static string ToPascalCase(string str) 1854 { 1855 return CultureInfo.InvariantCulture.TextInfo 1856 .ToTitleCase(str.ToLowerInvariant()) 1857 .Replace("-", "") 1858 .Replace("_", "") 1859 .Replace(" ", ""); 1860 } 1861 } 1862 1863 <script type="application/ld+json"> 1864 { 1865 "@@context": "http://schema.org/", 1866 "@@type": "Product", 1867 "name": "@GetString("Ecom:Product.Name")", 1868 @if (!string.IsNullOrEmpty(GetString("Ecom:Product.ImageLarge.Default.Clean"))) 1869 { 1870 <text>"image": [ 1871 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=400&crop=0&Compression=75&DoNotUpscale=true&image=@productImage", 1872 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=300&crop=0&Compression=75&DoNotUpscale=true&image=@productImage", 1873 "@siteURL/Admin/Public/GetImage.ashx?width=448&height=225&crop=0&Compression=75&DoNotUpscale=true&image=@productImage" 1874 ],</text> 1875 } 1876 "description": "@GetString("Ecom: Product.ShortDescription")", 1877 "mpn": "925872", 1878 @if (!string.IsNullOrEmpty(brand)) 1879 { 1880 <text>"brand": { 1881 "@@type": "Thing", 1882 "name": "@brand" 1883 },</text> 1884 } 1885 "offers": { 1886 "@@type": "Offer", 1887 "priceCurrency": "@GetString("Ecom:Product.Price.Currency.Code")", 1888 "price": "@GetString("Ecom:Product.Price.Price")", 1889 "availability": "@(GetInteger("Ecom:Product.Stock") > 0 ? "InStock" : "OutOfStock")" 1890 } 1891 } 1892 </script> 1893 <script> 1894 document.addEventListener("DOMContentLoaded", function () { 1895 if (document.getElementById("PriceAndActions")) { 1896 document.getElementById("PriceAndActions").addEventListener("contentLoaded", function (event) { 1897 if (document.querySelector(".js-variants") != null) { 1898 MatchVariants.Update(document.querySelector(".js-variants"), "DoNothing"); 1899 } 1900 }); 1901 } 1902 }); 1903 1904 //Custom dropdown 1905 var isOpen = false; 1906 1907 function toggleOptions(id) { 1908 1909 isOpen = !isOpen; 1910 if (isOpen) { 1911 document.getElementById(id).style.visibility = 'visible'; 1912 document.getElementById(id).classList.add("active"); 1913 document.getElementById(id).focus(); 1914 } else { 1915 document.getElementById(id).blur(); 1916 document.getElementById(id).classList.remove("active"); 1917 document.getElementById(id).style.visibility = 'hidden'; 1918 } 1919 1920 } 1921 1922 function selected(val, id, blurId) { 1923 document.getElementById(id).innerHTML = val; 1924 toggleOptions(blurId); 1925 var variantContainer = $(".js-variants"); 1926 variantContainer.find('.dropdown-container').each(function () { 1927 1928 var $this = $(this); 1929 var disabledItem = $this.find('.disabled'); 1930 if (disabledItem) { 1931 var displayValueItem = $this.find('.value-text'); 1932 1933 if (displayValueItem.html() == disabledItem.html()) { 1934 displayValueItem.html("@Translate("Select variant")"); 1935 } 1936 } 1937 1938 }); 1939 } 1940 </script>

Kontakt os

Har du spørgsmål til vores produkter, løsninger eller services? Eller søger du hjælp til beregninger og dimensioneringer? Vi står klar til at hjælpe. Udfyld formularen herunder, og vi kontakter dig hurtigst muligt.