0
Din indkøbskurv

Opdaterer kurv

stk. a

-
+

Din kurv i alt (ex. fragt)

Handel videre

Gå til kassen
VISA/DK VISA/DK VISA/DK VISA/DK VISA/DK
Find forhandler

,

Tlf.

Se alle

Error executing template "Designs/Mobler2018/eCom/Product/Product.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_63f3ec38eeae4314b7f0b5b72912384b.Execute() in D:\dynamicweb.net\Solutions\mobler.LIVE\Files\Templates\Designs\Mobler2018\eCom\Product\Product.cshtml:line 335
   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 @using System.Web 2 @using Mobler.Website.CustomModules.MoblerHelpers 3 @using System.Text.RegularExpressions 4 @using CampaignModule.Models 5 @using Dynamicweb.Core 6 @using Dynamicweb.Ecommerce.Products 7 @using Group = Dynamicweb.Ecommerce.Products.Group 8 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 9 10 @{ 11 var request = HttpContext.Current.Request; 12 string shopname = MoblerHelpers.GetShopName(); 13 string SelectPlaceholder = Translate("ShopSelectPlaceholder", "Indtast by, postnummer eller adresse"); 14 var shopInfo = MoblerHelpers.ShopInfo(); 15 int ShopPageId = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetInt("ShopPageId"); 16 var AllShops = Firstweb.Custom.CustomCode.Frontend.Helpers.Shops.GetAllShops(ShopPageId); 17 int AjaxCartPageId = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetInt("AjaxCartPageId"); 18 int CustomersAlsoSawPageId = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetInt("CustomersAlsoSawPageId"); 19 string relewiseRecommandationsEndpoint = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("RelewiseRecommandationsPageId"); 20 bool userIsAnonymous= Mobler.Website.CustomCode.RelewiseCustom.RelewiseConnectorSetting.IsAnonymous; 21 bool showRecommendations = Mobler.Website.CustomCode.RelewiseCustom.RelewiseConnectorSetting.ShowRecommendations; 22 string CartPage = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("CartPage"); 23 string VariantsEndpoint = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("VariantsUrl"); 24 string VariantDetailsEndpoint = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("VariantDetailsUrl"); 25 string BlackFridayTheme = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("BlackFridayTheme"); 26 string ProductID = GetString("Ecom:Product.ID"); 27 string GroupID = Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.GetProductDefaultShopGroupID(ProductID); //GetString("Ecom:Product.PrimaryOrFirstGroupID"); 28 string DefaultVariantID = GetString("Ecom:Product.DefaultVariantComboID"); 29 string ProductImage = MoblerHelpers.GetProductListImage(ProductID, DefaultVariantID); 30 string ProductName = GetString("Ecom:Product.Name"); 31 string ProductNumber = GetString("Ecom:Product.Number"); 32 string ProductCatalogLink = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.ProductCatelog.Value.Clean")) ? GetString("Ecom:Product:Field.ProductCatelog.Value.Clean") : ""; 33 string VariantId = GetString("Ecom:Product.VariantID"); 34 string ShortDescription = GetString("Ecom:Product.ShortDescription"); 35 string LongDescription = GetString("Ecom:Product.LongDescription").Replace("||", "<br/>"); 36 string CurrentVariantName = GetString("Ecom:Product.SelectedVariantComboName"); 37 var FaqQuestions = MoblerHelpers.GetProductFAQs(ProductID, GroupID); 38 39 // Group Specific - Exclude Bed Accessories 40 bool excludeBedAccessories = GetBoolean("Ecom:Product.CategoryField.Senge.ExcludeBedAccessories.Value"); 41 42 43 Mobler.Website.CustomCode.Frontend.PayeverHelper payeverHelper = new Mobler.Website.CustomCode.Frontend.PayeverHelper(); 44 Mobler.Website.CustomCode.Models.PayeverWidget PayeverWidget = payeverHelper.GetPayeverWidgetInformation(); 45 46 string MetaDescription = GetString("Ecom:Product.MetaDescription"); 47 48 if (string.IsNullOrEmpty(MetaDescription)) 49 { 50 MetaDescription = Mobler.Website.CustomCode.Frontend.Helpers.Text.GetFirstLine(LongDescription.Replace("<br/>", " ")); 51 } 52 else 53 { 54 MetaDescription = ""; //Meta data description bliver sat af DW, hvis dette felt er udfyldt, så vi skal ikke opsætte noget. 55 } 56 57 var RelatedBlogs = Firstweb.Custom.CustomCode.Frontend.Helpers.Blogs.GetBlogsRelatedToProduct(ProductID); 58 bool NewItem = GetBoolean("Ecom:Product:Field.NewItem"); 59 DateTime NewItemExpiryDate = GetDate( "Ecom:Product:Field.NewItemExpiryDate" ); 60 bool LowPrice = GetBoolean("Ecom:Product:Field.Splash3"); 61 62 Mobler.Website.CustomCode.Frontend.ProductsDisplayVariant productsDisplayVariant = Mobler.Website.CustomCode.Frontend.ProductsDisplayVariant.Instance(); 63 64 bool ForSale = !GetBoolean("Ecom:Product:Field.NotForSaleOnline"); 65 string FirstImage = ""; 66 var Images = MoblerHelpers.GetProductImages(GetString("Ecom:Product.ID"), VariantId); 67 bool First = true; 68 bool FirstIndicator = true; 69 int IndicatorIncrementer = 0; 70 string ProductLink = GetString("Ecom:Product.Link.Clean"); 71 72 double ActualPrice = GetDouble("Ecom:Product.Price.Price"); 73 double spar = 0; 74 double price = 0; 75 double normalPrice = 0; 76 77 string priceFormatted = ""; 78 string sparFormatted = ""; 79 string normalPriceFormatted = ""; 80 81 string campaignColor = ""; 82 string campaignText = ""; 83 string campaignTextClean = ""; 84 string campaignDate = ""; 85 86 string campaignDateStart = ""; 87 string campaignDateEnd = ""; 88 89 bool CampaignActiveOnProduct = GetBoolean("CampaignModule:Product.CampaignActiveOnProduct"); 90 if (!CampaignActiveOnProduct) 91 { 92 price = ActualPrice; 93 priceFormatted = MoblerHelpers.formatPrice(price); 94 } 95 else 96 { 97 normalPrice = GetDouble("CampaignModule:Product.CampaignProduct.NormalPrice"); 98 normalPriceFormatted = GetString("CampaignModule:Product.CampaignProduct.NormalPrice.FormattedRetail"); 99 100 price = GetDouble("CampaignModule:Product.CampaignProduct.CampaignPrice"); 101 priceFormatted = GetString("CampaignModule:Product.CampaignProduct.CampaignPrice.FormattedRetail"); 102 103 spar = GetDouble("CampaignModule:Product.CampaignProduct.DiscountAmount"); 104 sparFormatted = GetString("CampaignModule:Product.CampaignProduct.DiscountAmount.FormattedRetail"); 105 106 campaignColor = GetString("CampaignModule:Product.Campaign.Color"); 107 campaignTextClean = GetString("CampaignModule:Product.Campaign.Text"); 108 109 campaignDateStart = GetString("CampaignModule:Product.CampaignProduct.Campaign.Start"); 110 campaignDateEnd = GetString("CampaignModule:Product.CampaignProduct.Campaign.End"); 111 campaignText = $"{Translate("Campaign.BeforeDate.Text", "Gældende fra:")} {campaignDateStart} {Translate("Campaign.BeforeDate.Text2", "t.o.m.")} {campaignDateEnd}"; 112 } 113 114 string DataLayerPrice = ActualPrice.ToString().Replace(".", "").Replace(",", "."); 115 System.Web.HttpContext.Current.Items["OverrideOgTags"] = true; 116 string OgImage = "https://mobler.dk" + Images.FirstOrDefault(); 117 118 string TrimmedTeaser = Firstweb.Custom.CustomCode.Frontend.Helpers.JSFormatting.TrimLinebreaks(ShortDescription); 119 string TrimmedName = Firstweb.Custom.CustomCode.Frontend.Helpers.JSFormatting.TrimLinebreaks(ProductName); 120 121 var ParentGroups = Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.getBreadCrumbGroupList(GroupID, true); 122 var DataLayerParentGroup = ParentGroups.Last().Name; 123 List<string> DataLayerParentGroupStrings = ParentGroups.Select(group => group.Name).ToList(); 124 string DataLayerParentGroups = string.Join(" > ", DataLayerParentGroupStrings); 125 126 // Handle USPs on the product page 127 int uspPageId = 0; 128 string uspProductdetailLinkProductLevel = GetString("Ecom:Product:Field.uspproductdetaillink.Value.Clean"); 129 string uspProductdetailLinkGroupLevel = ParentGroups.Last().ProductGroupFieldValues.GetProductGroupFieldValue("uspproductdetaillink").Value.ToString(); 130 bool hasUspProductdetailLinkProductLevel = !string.IsNullOrEmpty(uspProductdetailLinkProductLevel); 131 bool hasUspProductdetailLinkGroupLevel = !string.IsNullOrEmpty(uspProductdetailLinkGroupLevel); 132 133 // Check if there's a product detail link on the product level 134 if (hasUspProductdetailLinkProductLevel) 135 { 136 Int32.TryParse(uspProductdetailLinkProductLevel.Substring(uspProductdetailLinkProductLevel.LastIndexOf('=') + 1), out uspPageId); 137 } 138 // Check if there's a product detail link on the group level 139 else if (hasUspProductdetailLinkGroupLevel) 140 { 141 Int32.TryParse(uspProductdetailLinkGroupLevel.Substring(uspProductdetailLinkGroupLevel.LastIndexOf('=') + 1), out uspPageId); 142 } 143 144 // Handle display of product catalogue image, if it exists on the group level 145 string productCatalogueImage = ParentGroups.Last().ProductGroupFieldValues.GetProductGroupFieldValue("ProductCatalogueImage").Value.ToString(); 146 147 // Handle USP Icons and Text 148 string usp1Icon = ParentGroups.Last().ProductGroupFieldValues.GetProductGroupFieldValue("usp_1_icon").Value.ToString(); 149 if (usp1Icon == "") 150 { 151 usp1Icon = "piggy-bank"; 152 } 153 string usp2Icon = ParentGroups.Last().ProductGroupFieldValues.GetProductGroupFieldValue("usp_2_icon").Value.ToString(); 154 if (usp2Icon == "") 155 { 156 usp2Icon = "truck"; 157 } 158 string usp3Icon = ParentGroups.Last().ProductGroupFieldValues.GetProductGroupFieldValue("usp_3_icon").Value.ToString(); 159 if (usp3Icon == "") 160 { 161 usp3Icon = "calendar"; 162 } 163 164 string usp1IconText = Translate("Product.USPIcon.One.Title", "Prismatch"); 165 string usp2IconText = Translate("Product.USPIcon.Two.Title", "Fri kantstenslevering*"); 166 string usp3IconText = Translate("Product.USPIcon.Three.Title", "Rentefri finansiering"); 167 string usp1IconTextFromField = ParentGroups.Last().ProductGroupFieldValues.GetProductGroupFieldValue("uspicontext1").Value.ToString(); 168 string usp2IconTextFromField = ParentGroups.Last().ProductGroupFieldValues.GetProductGroupFieldValue("uspicontext2").Value.ToString(); 169 string usp3IconTextFromField = ParentGroups.Last().ProductGroupFieldValues.GetProductGroupFieldValue("uspicontext3").Value.ToString(); 170 171 if (!string.IsNullOrEmpty(usp1IconTextFromField)) 172 { 173 usp1IconText = usp1IconTextFromField; 174 } 175 if (!string.IsNullOrEmpty(usp2IconTextFromField)) 176 { 177 usp2IconText = usp2IconTextFromField; 178 } 179 if (!string.IsNullOrEmpty(usp3IconTextFromField)) 180 { 181 usp3IconText = usp3IconTextFromField; 182 } 183 184 string usp1IconClass = "fa-solid fa-" + usp1Icon + " fs3"; 185 string usp2IconClass = "fa-solid fa-" + usp2Icon + " fs3"; 186 string usp3IconClass = "fa-solid fa-" + usp3Icon + " fs3"; 187 188 string seeProductInStore = ""; 189 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.seeproductinstore.Value.Clean"))) 190 { 191 seeProductInStore = GetString("Ecom:Product:Field.seeproductinstore.Value.Clean"); 192 } 193 194 string ShowOnPageUrl = ""; 195 string GetCartEndpoint = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("GetCartJson"); 196 197 string QuickDeliveryColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("QuickDeliveryColor"); 198 string QuickDeliveryDescription = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("QuickDeliveryDescription"); 199 string NormalDeliveryDescription = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("NormalDeliveryDescription"); 200 string BrandName = GetString("Ecom:Product:Field.Maerkevarer.Value.Clean"); 201 string DeliveryTime = Translate("DeliveryTime." + BrandName, "Gns. leveringstid 3-12 dage"); 202 bool HideDelivery = DeliveryTime == "Skjul"; 203 string DeliveryColor = "#00AB5D"; 204 bool QuickDelivery = GetBoolean("Ecom:Product:Field.QuickDelivery.Value.Clean"); 205 string CustomDelivery = GetString("Ecom:Product:Field.CustomDeliveryTime.Value.Clean"); 206 if (QuickDelivery) 207 { 208 DeliveryColor = QuickDeliveryColor; 209 DeliveryTime = Translate("DeliveryTime.QuickDelivery", "Ekstra hurtig levering"); 210 } 211 else if (!String.IsNullOrEmpty(CustomDelivery)) 212 { 213 DeliveryTime = CustomDelivery; 214 } 215 string DeliveryFontWeightModifier = QuickDelivery ? "font-weight-bold" : ""; 216 bool DisplayAverageDeliveryTime = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetBoolean("DisplayAverageDeliveryTime"); 217 218 double CostPrice = GetDouble("Ecom:Product:Field.FirstwebCostPrice.Value.Raw"); 219 string DailyPriceBackgroundColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("AktuelDagsprisBackgroundColor"); 220 string DailyPriceTextColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("AktuelDagsprisTextColor"); 221 string EAN = GetString("Ecom:Product:Field.FirstEan.Value"); 222 string productionDescription = GetString("Ecom:Product:Field.FirstwebProductionDescription"); 223 224 Mobler.Website.CustomCode.RelewiseCustom.RelewiseCaller relewiseCaller = new Mobler.Website.CustomCode.RelewiseCustom.RelewiseCaller(); 225 relewiseCaller.TrackProductView(ProductID, VariantId); 226 bool hasVariants = false; 227 } 228 229 @SnippetStart("PricesContainer") 230 <div class="row"> 231 <div class="col-12 col-sm-12 offset-sm-0 d-flex justify-content-center justify-content-lg-start flex-column"> 232 @if (GetLoop("Co3VariantCombinations").Count > 0) { 233 hasVariants = true; 234 // Only show the extra price at top, if we have variants 235 <div class="d-flex flex-wrap flex-column justify-content-end border-grey border-bottom-0 p-4"> 236 <p class="price font-weight-bold m-0"> 237 <span class="unimportant-hidden" data-bind="css: { 'd-inline': SplashType() == 1 }">@Translate("ProductNow", "NU") </span> 238 <span class="total-price" data-bind="text: Price"></span> 239 </p> 240 @if (campaignTextClean == "KOMBI") 241 { 242 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 5 }"></div> 243 <div class="d-none" data-bind="setInitValue: { observable: BeforePriceDouble, value: @normalPrice }"></div> 244 <div class="d-none" data-bind="setInitValue: { observable: BeforePrice, value: '@normalPriceFormatted' }"></div> 245 <div class="d-none" data-bind="setInitValue: { observable: SavingDouble, value: @spar }"></div> 246 <div class="d-none" data-bind="setInitValue: { observable: Saving, value: '@sparFormatted' }"></div> 247 } 248 else if (spar > 0) 249 { 250 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 1 }"></div> 251 <div class="d-none" data-bind="setInitValue: { observable: BeforePriceDouble, value: @normalPrice }"></div> 252 <div class="d-none" data-bind="setInitValue: { observable: BeforePrice, value: '@normalPriceFormatted' }"></div> 253 <div class="d-none" data-bind="setInitValue: { observable: SavingDouble, value: @spar }"></div> 254 <div class="d-none" data-bind="setInitValue: { observable: Saving, value: '@sparFormatted' }"></div> 255 } 256 else if (NewItem) 257 { 258 if (NewItemExpiryDate > DateTime.Now) 259 { 260 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 2 }"></div> 261 } 262 } 263 else if (LowPrice) 264 { 265 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 3 }"></div> 266 } 267 else if (CostPrice > 0) 268 { 269 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 4 }"></div> 270 } 271 272 <div class="w-100 unimportant-hidden" data-bind="css: { 'd-flex': SplashType() == 1 || SplashType() == 5}"> 273 <p class="color-subtle fs0 m-0 text-uppercase mr-3">@Translate("PriceBefore", "Før") <span class="before-price" data-bind="text: BeforePrice"></span></p> 274 <p class="splash fs0 text-uppercase m-0 px-2">@Translate("PriceSaving", "Spar") <span class="total-saving" data-bind="text: Saving"></span></p> 275 </div> 276 277 <div class="price-info fs-s mt-4"> 278 @if (excludeBedAccessories) 279 { 280 <p class="price-info-text color-subtle mb-1 js-update-price-info-text">@Translate("Ecom:Product.Pricing.Excludes.Beds", "Prisen er ekskl. ben og gavl.")</p> 281 } 282 @if (hasVariants) 283 { 284 <div class="variant-price-disclaimer color-subtle mb-1">@Translate("VariantPriceDisclaimer", "Prisen kan variere efter materialevalg")</div> 285 } 286 </div> 287 288 @if (!string.IsNullOrEmpty(campaignDateStart) && !string.IsNullOrEmpty(campaignDateEnd) && !string.IsNullOrEmpty(campaignText)) 289 { 290 <div class="d-none" data-bind="setInitValue: { observable: CampaignText, value: '@campaignText' }"></div> 291 <div class="price-info fs-xs"> 292 <p class="mb-1"><span class="dot dot-yellow"></span> <span data-bind="text: CampaignText"></span></p> 293 </div> 294 } 295 else 296 { 297 <div class="d-none" data-bind="setInitValue: { observable: CampaignText, value: '' }"></div> 298 } 299 @* <p data-bind="text: CampaignText"></p> *@ 300 </div> 301 } 302 303 @if (GetLoop("Co3VariantCombinations").Count > 0) 304 { 305 <div class="variant-selectors"> 306 @{ 307 hasVariants = true; 308 var VariantGroupsWithMultipleOptions = GetLoop("VariantGroups").Where(x => x.GetLoop("VariantAvailableOptions").Count > 1); 309 int VariantGroupCount = VariantGroupsWithMultipleOptions.Count(); 310 int VariantCombinationsCount = GetLoop("Co3VariantCombinations").Count; 311 int PossibleVariantCombinations = 1; 312 } 313 @foreach (var VG in GetLoop("VariantGroups")) 314 { 315 PossibleVariantCombinations *= VG.GetLoop("VariantAvailableOptions").Count; 316 } 317 @if (VariantGroupCount == 1) 318 { 319 var RelevantVariantGroup = VariantGroupsWithMultipleOptions.FirstOrDefault(); 320 var SelectedVariant = RelevantVariantGroup.GetLoop("VariantAvailableOptions").Where(x => x.GetBoolean("Ecom:VariantOption.Selected")).FirstOrDefault(); 321 int variantCount = RelevantVariantGroup.GetLoop("VariantAvailableOptions").Count; 322 var variantSelectorClass = "variant-options bg-white"; 323 if (RelevantVariantGroup.GetString("Ecom:VariantGroup.Label").ToLower().Contains("farve") && variantCount <= 5) 324 { 325 variantSelectorClass = "variant-selector__color-picker d-flex flex-wrap"; 326 } 327 string variantInfoText = Translate("VariantInfo-" + RelevantVariantGroup.GetString("Ecom:VariantGroup.Label"), "Variant Info Text"); 328 string variantInfoTextEscapedLineBreaks = variantInfoText.Replace(System.Environment.NewLine, "<br />"); 329 330 <div class="position-relative border-grey p-4"> 331 <div class="variant-selector__header"> 332 <div class="variant-selector__header-inner"> 333 <span class="font-weight-bold fs0">@RelevantVariantGroup.GetString("Ecom:VariantGroup.Label")</span> 334 <div class="variant-selector__header-choices"> 335 <span class="variantoptionname fs0" data-bind="text: SelectedVariantOption0">@SelectedVariant.GetString("Ecom:VariantOption.Name")</span> 336 </div> 337 </div> 338 <span class="variant-selector__toggle" data-bind="click: ToggleVariantInfo.bind($data, '@variantInfoTextEscapedLineBreaks')"> 339 <span class="fas fa-info-circle"></span> 340 </span> 341 </div> 342 343 @if (!RelevantVariantGroup.GetString("Ecom:VariantGroup.Label").ToLower().Contains("farve") || variantCount > 5) 344 { 345 <div class="variant-dropdown border-grey p-2 mt-3 d-flex justify-content-between align-items-center pointer js-variant-dropdown"> 346 <p class="m-0"><span data-bind="text: SelectedVariantOption0">@SelectedVariant.GetString("Ecom:VariantOption.Name")</span></p> 347 <i class="fas fa-chevron-down"></i> 348 </div> 349 } 350 351 <div class="@variantSelectorClass"> 352 @foreach (LoopItem Variant in RelevantVariantGroup.GetLoop("VariantAvailableOptions")) 353 { 354 LoopItem VariantCombination = GetLoop("Co3VariantCombinations").FirstOrDefault(x => x.GetString("Ecom:VariantCombination.VariantID").ToString().Contains(Variant.GetString("Ecom:VariantOption.ID"))); 355 string VariantName = Variant.GetString("Ecom:VariantOption.Name"); 356 string VariantIdentifier = Variant.GetString("Ecom:VariantOption.ID"); 357 string VariantLink = VariantCombination.GetString("Ecom:VariantCombination.Link.Clean"); 358 string VariantPreview = String.Empty; 359 var ObservableToSet = "SelectedVariantOption0"; 360 var ObservableToSetId = "SelectedVariantOptionId0"; 361 bool ShowPreview = RelevantVariantGroup.GetString("Ecom:VariantGroup.Name").ToLower().Contains("farve") || RelevantVariantGroup.GetString("Ecom:VariantGroup.Name").ToLower().Contains("materiale"); 362 363 List<string> variantCombinationVariantIds = GetLoop("Co3VariantCombinations").Select(p => p.GetString("Ecom:VariantCombination.VariantID")).ToList(); 364 string variantOptionColor = Variant.GetString("Ecom:VariantOption.ColorHex"); 365 string variantIdWithColorOptionId = variantCombinationVariantIds.FirstOrDefault(vid => vid.Contains(VariantIdentifier)); 366 367 if (!String.IsNullOrEmpty(Variant.GetString("Ecom:VariantOption.ImgSmall.Clean")) && ShowPreview) 368 { 369 if (Variant.GetString("Ecom:VariantOption.ImgSmall.Clean").StartsWith("#")) 370 { 371 VariantPreview = "style= \"background-color: " + Variant.GetString("Ecom:VariantOption.ImgSmall.Clean") + ";\""; 372 } 373 else 374 { 375 VariantPreview = "style=\"background-image: url('" + Variant.GetString("Ecom:VariantOption.ImgSmall.Clean") + "');\""; 376 } 377 } 378 379 if (!RelevantVariantGroup.GetString("Ecom:VariantGroup.Label").ToLower().Contains("farve") || variantCount > 5) 380 { 381 <div class="option pointer color-primary d-flex w-100 p-2 bg-grey" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VariantIdentifier', @ObservableToSet, '@VariantName', @ObservableToSetId)"> 382 @if (!String.IsNullOrEmpty(VariantPreview)) 383 { 384 <span class="option-preview mr-2" @VariantPreview></span> 385 } 386 <span>@VariantName</span> 387 </div> 388 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSet, value: '@SelectedVariant.GetString("Ecom:VariantOption.Name")' }"></div> 389 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSetId, value: '@SelectedVariant.GetString("Ecom:VariantOption.ID")' }"></div> 390 } 391 else 392 { 393 if (variantIdWithColorOptionId.IsNullOrEmpty() == false) 394 { 395 bool selectedVariant = Variant.GetBoolean("Ecom:VariantOption.Selected"); 396 string selectedVariantClass = ""; 397 if (selectedVariant) 398 { 399 selectedVariantClass = "selected"; 400 } 401 402 <div id="@VariantIdentifier" class="product-item__variant large @selectedVariantClass" style="background-color: @variantOptionColor;" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VariantIdentifier', @ObservableToSet, '@VariantName', @ObservableToSetId)"></div> 403 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSet, value: '@SelectedVariant.GetString("Ecom:VariantOption.Name")' }"></div> 404 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSetId, value: '@SelectedVariant.GetString("Ecom:VariantOption.ID")' }"></div> 405 } 406 } 407 } 408 </div> 409 </div> 410 } 411 else if (PossibleVariantCombinations == VariantCombinationsCount) 412 { 413 Dictionary<string, string> CurrentlySelectedVariantOptions = new Dictionary<string, string>(); 414 foreach (var VG in GetLoop("VariantGroups")) 415 { 416 foreach (var VO in VG.GetLoop("VariantAvailableOptions").Where(x => x.GetBoolean("Ecom:VariantOption.Selected"))) 417 { 418 CurrentlySelectedVariantOptions.Add(VG.GetString("Ecom:VariantGroup.Name"), VO.GetString("Ecom:VariantOption.ID")); 419 } 420 } 421 int VGLoopCounter = 0; 422 foreach (var VG in GetLoop("VariantGroups")) 423 { 424 List<LoopItem> RelevantVariantCombinations = new List<LoopItem>(); 425 var VariantCombinationLink = GetLoop("Co3VariantCombinations"); 426 var SelectedVariant = VG.GetLoop("VariantAvailableOptions").FirstOrDefault(x => x.GetBoolean("Ecom:VariantOption.Selected")); 427 var ObservableToSet = "SelectedVariantOption" + VGLoopCounter.ToString(); 428 var ObservableToSetId = "SelectedVariantOptionId" + VGLoopCounter.ToString(); 429 int variantCount = VG.GetLoop("VariantAvailableOptions").Count; 430 431 VGLoopCounter++; 432 433 var variantSelectorClass = "variant-options bg-white"; 434 if (!VG.GetString("Ecom:VariantGroup.ID").ToLower().Contains("fasthed")) 435 { 436 if (VG.GetString("Ecom:VariantGroup.Label").ToLower().Contains("farve") && variantCount <= 5) 437 { 438 variantSelectorClass = "variant-selector__color-picker d-flex flex-wrap"; 439 } 440 else if (VG.GetString("Ecom:VariantGroup.Label").ToLower().Contains("farve") && variantCount > 5) 441 { 442 variantSelectorClass = "variant-options bg-white"; 443 } 444 else 445 { 446 variantSelectorClass = "radio-button d-flex flex-column"; 447 } 448 } 449 450 foreach (var VC in VariantCombinationLink) 451 { 452 var Add = true; 453 foreach (var KVP in CurrentlySelectedVariantOptions.Where(s => s.Key != VG.GetString("Ecom:VariantGroup.Name"))) 454 { 455 if (!VC.GetString("Ecom:VariantCombination.VariantID").ToString().Contains(KVP.Value)) 456 { 457 Add = false; 458 } 459 } 460 if (Add) 461 { 462 RelevantVariantCombinations.Add(VC); 463 } 464 } 465 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSet, value: '@SelectedVariant.GetString("Ecom:VariantOption.Name")' }"></div> 466 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSetId, value: '@SelectedVariant.GetString("Ecom:VariantOption.ID")' }"></div> 467 468 string variantInfoText = Translate("VariantInfo-" + VG.GetString("Ecom:VariantGroup.Label"), "Variant Info Text"); 469 string variantInfoTextEscapedLineBreaks = variantInfoText.Replace(System.Environment.NewLine, "<br />"); 470 471 <div class="variant-selector position-relative border-grey border-bottom-0 p-4" data-variantgroupid="@VG.GetString("Ecom:VariantGroup.ID")"> 472 <div class="variant-selector__header"> 473 <div class="variant-selector__header-inner"> 474 <span class="font-weight-bold fs0">@VG.GetString("Ecom:VariantGroup.Label")</span> 475 <div class="variant-selector__header-choices"> 476 <span class="variantoptionname fs0" data-bind="text: @ObservableToSet">@SelectedVariant.GetString("Ecom:VariantOption.Name")</span> 477 </div> 478 </div> 479 <span class="variant-selector__toggle" data-bind="click: ToggleVariantInfo.bind($data, '@variantInfoTextEscapedLineBreaks')"> 480 <span class="fas fa-info-circle"></span> 481 </span> 482 </div> 483 @if (VG.GetString("Ecom:VariantGroup.Label").ToLower().Contains("fasthed") || VG.GetString("Ecom:VariantGroup.Label").ToLower().Contains("farve") && variantCount > 5) 484 { 485 <div class="variant-dropdown border-grey p-2 mt-3 d-flex justify-content-between align-items-center pointer js-variant-dropdown"> 486 <p class="m-0"><span data-bind="text: @ObservableToSet">@SelectedVariant.GetString("Ecom:VariantOption.Name")</span></p> 487 <i class="fas fa-chevron-down"></i> 488 </div> 489 } 490 491 <div class="@variantSelectorClass"> 492 @foreach (var VO in VG.GetLoop("VariantAvailableOptions")) 493 { 494 var VariantCombination = RelevantVariantCombinations.Where(vc => vc.GetString("Ecom:VariantCombination.VariantID").ToString().Contains(VO.GetString("Ecom:VariantOption.ID"))).FirstOrDefault(); 495 string VariantLink = VariantCombination.GetString("Ecom:VariantCombination.Link.Clean"); 496 string VariandOptionId = VariantCombination.GetString("Ecom:VariantCombination.VariantID"); 497 string VariantPreview = String.Empty; 498 string VOName = VO.GetString("Ecom:VariantOption.Name"); 499 string VOId = VO.GetString("Ecom:VariantOption.ID"); 500 bool ShowPreview = VG.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("farve") || VG.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("materiale") ? true : false; 501 502 List<string> variantCombinationVariantIds = GetLoop("Co3VariantCombinations").Select(p => p.GetString("Ecom:VariantCombination.VariantID")).ToList(); 503 string variantOptionColor = VO.GetString("Ecom:VariantOption.ColorHex"); 504 string variantIdWithColorOptionId = variantCombinationVariantIds.FirstOrDefault(vid => vid.Contains(VariandOptionId)); 505 506 if (!String.IsNullOrEmpty(VO.GetString("Ecom:VariantOption.ImgSmall.Clean")) && ShowPreview) 507 { 508 if (VO.GetString("Ecom:VariantOption.ImgSmall.Clean").StartsWith("#")) 509 { 510 VariantPreview = "style= \"background-color: " + VO.GetString("Ecom:VariantOption.ImgSmall.Clean") + ";\""; 511 } 512 else 513 { 514 VariantPreview = "style=\"background-image: url('" + VO.GetString("Ecom:VariantOption.ImgSmall.Clean") + "');\""; 515 } 516 } 517 518 if (VG.GetString("Ecom:VariantGroup.ID").ToLower().Contains("fasthed") || VG.GetString("Ecom:VariantGroup.Name").ToLower().Contains("farve") && variantCount > 5) 519 { 520 <div class="option d-flex w-100 p-2 bg-grey color-primary pointer" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VOId', @ObservableToSet, '@VOName', @ObservableToSetId)"> 521 @if (!String.IsNullOrEmpty(VariantPreview)) 522 { 523 <span class="option-preview mr-2" @VariantPreview></span> 524 } 525 @VOName 526 </div> 527 } 528 else if (VG.GetString("Ecom:VariantGroup.Name").ToLower().Contains("farve") && variantCount <= 5) 529 { 530 bool selectedVariant = VO.GetBoolean("Ecom:VariantOption.Selected"); 531 string selectedVariantClass = ""; 532 if (selectedVariant) 533 { 534 selectedVariantClass = "selected"; 535 } 536 537 if (variantIdWithColorOptionId.IsNullOrEmpty() == false) 538 { 539 <div id="@VOId" class="variantToggle product-item__variant large @selectedVariantClass" style="background-color: @variantOptionColor;" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VOId', @ObservableToSet, '@VOName', @ObservableToSetId, $element)"><i class="fa-solid fa-check"></i></div> 540 } 541 } 542 else if (!VG.GetString("Ecom:VariantGroup.ID").ToLower().Contains("fasthed") || VG.GetString("Ecom:VariantGroup.Name").ToLower().Contains("farve")) 543 { 544 bool selectedVariant = VO.GetBoolean("Ecom:VariantOption.Selected"); 545 string selectedVariantClass = ""; 546 if (selectedVariant) 547 { 548 selectedVariantClass = "selected"; 549 } 550 551 <div id="@VOId" class="variantToggle product-item__variant--radiobutton @selectedVariantClass mb-2" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VOId', @ObservableToSet, '@VOName', @ObservableToSetId, $element)"> 552 <span class="radiobutton"></span>@VOName 553 </div> 554 } 555 } 556 </div> 557 </div> 558 } 559 } 560 else if (GetLoop("VariantGroups").Any(x => x.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("farve")) && GetLoop("VariantGroups").Any(x => x.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("materiale"))) 561 { 562 <div class="mt-3"> 563 <p class="mb-1">@Translate("CurrentDesignName", "Valgte design: ")</p> 564 <p class="font-weight-bold">@CurrentVariantName</p> 565 </div> 566 <div class="d-flex"> 567 <div class="btn btn-primary" data-bind="click: ToggleVariantPicker">@Translate("ChooseNewDesign", "V&aelig;lg design")</div> 568 </div> 569 } 570 else 571 { 572 var SelectedVariantId = GetString("Ecom:Product.VariantID"); 573 var SelectedVariant = GetLoop("Co3VariantCombinations").Where(x => x.GetString("Ecom:VariantCombination.VariantID") == SelectedVariantId).FirstOrDefault(); 574 var SelectedVariantName = ""; 575 if (SelectedVariant != null) 576 { 577 SelectedVariantName = SelectedVariant.GetString("Ecom:VariantCombination.VariantText"); 578 } 579 <div class="d-none" data-bind="setInitValue: { observable: SelectedVariantOption0, value: '@SelectedVariantName' }"></div> 580 <div class="d-none" data-bind="setInitValue: { observable: SelectedVariantOptionId0, value: '@SelectedVariantId' }"></div> 581 582 <div class="position-relative"> 583 <div class="variant-dropdown p-2 box-shadow mt-3 d-flex justify-content-between align-items-center pointer js-variant-dropdown"> 584 <p class="m-0"><span class="font-weight-bold">@Translate("FallbackVariantsText", "VARIANTER")</span> - <span data-bind="text: SelectedVariantOption0">@SelectedVariantName</span></p> 585 <i class="fas fa-chevron-down"></i> 586 </div> 587 <div class="variant-options bg-white"> 588 @foreach (var Variant in GetLoop("Co3VariantCombinations")) 589 { 590 string VariantName = Variant.GetString("Ecom:VariantCombination.VariantText"); 591 string VCId = Variant.GetString("Ecom:VariantCombination.VariantID"); 592 <div class="option color-primary pointer d-block p-2 bg-grey" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VCId', SelectedVariantOption0, '@VariantName', SelectedVariantOptionId0)">@VariantName</div> 593 } 594 </div> 595 </div> 596 } 597 </div> 598 } 599 600 @if (GetInteger("Ecom:Product.RelatedCount") > 0) 601 { 602 <div class="optionalselectors position-relative border-grey border-bottom-0 p-4"> 603 <div class="optional-selectors__header"> 604 <span class="font-weight-bold fs0">@Translate("Tilvalg", "Tilvalg")</span> 605 <span class="variant-selector__toggle" data-bind="click: ToggleOptionalInfo"> 606 <span class="fas fa-info-circle"></span> 607 </span> 608 </div> 609 <div class="optional-selectors__body"> 610 @foreach (LoopItem relatedGroup in GetLoop("ProductRelatedGroups").Where(g => g.GetLoop("Products").Count > 0)) 611 { 612 string groupName = relatedGroup.GetString("Ecom:Product:RelatedGroup.Name"); 613 string groupNameInLowerCase = groupName.ToLower().Replace(" ", "-"); 614 615 <div class="optionalselectors--selector d-flex align-items-center mb-4 position-relative js-optional-selector" data-group-name="@groupNameInLowerCase"> 616 <div class="optionalselectors--selector__label u-inline-block d-flex"> 617 @groupName 618 <span class="optionalselector-remove js-optional-selector-remove optionalselector-remove__@groupNameInLowerCase d-none" data-bind="click: RemoveOptionalProduct"><i class="fa-solid fa-circle-xmark"></i></span> 619 </div> 620 <div class="variant-dropdown border-grey p-2 d-flex justify-content-between align-items-center pointer js-variant-dropdown js-optional-dropdown"> 621 <p class="m-0"><span>@Translate("Vælg", "Vælg")</span></p> 622 <svg class="svg-inline--fa fa-chevron-down fa-w-14" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-down" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" data-fa-i2svg=""><path fill="currentColor" d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"></path></svg><!-- <i class="fas fa-chevron-down"></i> Font Awesome fontawesome.com --> 623 </div> 624 <div class="variant-options bg-white"> 625 @foreach (LoopItem product in relatedGroup.GetLoop("Products")) 626 { 627 string optionalProductId = product.GetString("Ecom:Product.ID"); 628 string optionalProductName = product.GetString("Ecom:Product.Name"); 629 string optionalProductPrice = MoblerHelpers.formatPrice(product.GetString("Ecom:Product.Price.PriceWithVAT.Value")); 630 string optionalProductPriceUnformatted = product.GetString("Ecom:Product.Price.Price.Value"); 631 string optionalProductPriceBefore = product.GetString("CampaignModule:Product.CampaignProduct.NormalPrice"); 632 string optionalProductPriceDiscount = product.GetString("CampaignModule:Product.CampaignProduct.DiscountAmount.FormattedRetail"); 633 string optionalProductDiscountText = ""; 634 if (!String.IsNullOrEmpty(optionalProductPriceDiscount)) 635 { 636 optionalProductDiscountText = "(SPAR: " + optionalProductPriceDiscount + ")"; 637 } 638 string optionalProductVariantId = product.GetString("Ecom:Product.VariantID"); 639 string optionalProductVariantText = product.GetString("Ecom:Product.VariantText"); 640 641 <div class="option d-flex w-100 p-2 bg-grey color-primary pointer" id="@optionalProductId@optionalProductVariantId" data-bind="click: UpdateOptionalProduct.bind($data, '@optionalProductId', '@optionalProductVariantId', '@optionalProductName', '@optionalProductVariantText', '@optionalProductPrice', @optionalProductPriceUnformatted, '@optionalProductPriceBefore', '@optionalProductPriceDiscount', '@groupNameInLowerCase')"> 642 @optionalProductName @optionalProductVariantText - @optionalProductPrice @optionalProductDiscountText 643 </div> 644 } 645 </div> 646 </div> 647 } 648 </div> 649 </div> 650 } 651 652 <div class="d-flex flex-wrap flex-column justify-content-end border-grey p-4"> 653 @if (ForSale) 654 { 655 <div class="addtocart-price"> 656 <div class="d-flex align-items-center"> 657 <div class="d-flex justify-content-between w-100"> 658 <div class="quantity-controls d-flex align-items-center"> 659 <div class="control minus" data-bind="click: DecreaseQuantity"> 660 - 661 </div> 662 <input type="text" name="Quantity" value="1" data-bind="value: Quantity"/> 663 <div class="control plus" data-bind="click: IncrementQuantity"> 664 + 665 </div> 666 </div> 667 @{ 668 string addToCartButtonClass = BlackFridayTheme == "True" ? "btn-black-friday bf-bg-black" : "brand-primary-outline font-weight-bold"; 669 } 670 <p class="btn @addToCartButtonClass add-to-cart m-0 d-flex align-items-center px-4" data-bind="click: AddToCart.bind($data, '@DataLayerPrice')"> 671 @Translate("ProductAddToCart", "L&aelig;g i kurv") 672 </p> 673 </div> 674 </div> 675 <div class="d-flex flex-wrap flex-column justify-content-between mt-4 unimportant-hidden"> 676 <p class="price font-weight-bold m-0"> 677 <span class="unimportant-hidden" data-bind="css: { 'd-inline': SplashType() == 1 }">@Translate("ProductNow", "NU") </span> 678 <span class="total-price" data-bind="text: Price"></span> 679 <span id="priceWithoutAddons" class="unimportant-hidden" data-bind="text: PriceDouble"></span> 680 </p> 681 @if (campaignTextClean == "KOMBI") 682 { 683 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 5 }"></div> 684 <div class="d-none" data-bind="setInitValue: { observable: BeforePriceDouble, value: @normalPrice }"></div> 685 <div class="d-none" data-bind="setInitValue: { observable: BeforePrice, value: '@normalPriceFormatted' }"></div> 686 <div class="d-none" data-bind="setInitValue: { observable: SavingDouble, value: @spar }"></div> 687 <div class="d-none" data-bind="setInitValue: { observable: Saving, value: '@sparFormatted' }"></div> 688 } 689 else if (spar > 0) 690 { 691 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 1 }"></div> 692 <div class="d-none" data-bind="setInitValue: { observable: BeforePriceDouble, value: @normalPrice }"></div> 693 <div class="d-none" data-bind="setInitValue: { observable: BeforePrice, value: '@normalPriceFormatted' }"></div> 694 <div class="d-none" data-bind="setInitValue: { observable: SavingDouble, value: @spar }"></div> 695 <div class="d-none" data-bind="setInitValue: { observable: Saving, value: '@sparFormatted' }"></div> 696 } 697 else if (NewItem) 698 { 699 if (NewItemExpiryDate > DateTime.Now) 700 { 701 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 2 }"></div> 702 } 703 } 704 else if (LowPrice) 705 { 706 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 3 }"></div> 707 } 708 else if (CostPrice > 0) 709 { 710 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 4 }"></div> 711 } 712 713 <div class="w-100 unimportant-hidden" data-bind="css: { 'd-flex': SplashType() == 1 || SplashType() == 5}"> 714 <p class="color-subtle fs0 m-0 text-uppercase mr-3">@Translate("PriceBefore", "Før") <span class="before-price" data-bind="text: BeforePrice"></span></p> 715 <p class="splash fs0 text-uppercase m-0 px-2">@Translate("PriceSaving", "Spar") <span class="total-saving" data-bind="text: Saving"></span></p> 716 </div> 717 718 <div class="price-info fs-s mt-4"> 719 @if (excludeBedAccessories) 720 { 721 <p class="mb-1 color-subtle price-info-text js-update-price-info-text">@Translate("Ecom:Product.Pricing.Excludes.Beds", "Prisen er ekskl. ben og gavl.")</p> 722 } 723 @if (hasVariants) 724 { 725 <div class="variant-price-disclaimer color-subtle fs-s mb-1">@Translate("VariantPriceDisclaimer", "Prisen kan variere efter materialevalg")</div> 726 } 727 </div> 728 729 @if (!string.IsNullOrEmpty(campaignDateStart) && !string.IsNullOrEmpty(campaignDateEnd) && !string.IsNullOrEmpty(campaignText)) 730 { 731 <div class="d-none" data-bind="setInitValue: { observable: CampaignText, value: '@campaignText' }"></div> 732 <div class="price-info fs-xs"> 733 <p class="mb-1"><span class="dot dot-yellow"></span> <span data-bind="text: CampaignText"></span></p> 734 </div> 735 } 736 else 737 { 738 <div class="d-none" data-bind="setInitValue: { observable: CampaignText, value: '' }"></div> 739 } 740 @* <p data-bind="text: CampaignText"></p> *@ 741 </div> 742 743 <div class="optionalproducts d-none"> 744 <hr /> 745 <h5>@Translate("Tilvalg", "Tilvalg")</h5> 746 <div class="optionalproduct"></div> 747 <p><strong>Sum af tilvalg: </strong><span id="optionalPrice"></span></p> 748 </div> 749 750 @if (!string.IsNullOrEmpty(PayeverWidget.WidgetId) && !string.IsNullOrEmpty(PayeverWidget.BusinessId) && !string.IsNullOrEmpty(PayeverWidget.CheckoutId)) 751 { 752 <div> 753 <div class="payever-widget-finexp" 754 data-widgetid="@PayeverWidget.WidgetId" 755 data-checkoutid="@PayeverWidget.CheckoutId" 756 data-business="@PayeverWidget.BusinessId" 757 data-type="text" 758 data-reference="order-id" 759 data-amount="@GetString("Ecom:Product.Price.Price").Replace(".", string.Empty).Replace(",", ".")"></div> 760 <script> 761 var script = document.createElement('script'); 762 script.src = 'https://widgets.payever.org/finance-express/widget.min.js'; 763 script.onload = function() { 764 PayeverPaymentWidgetLoader.init( 765 '.payever-widget-finexp' 766 ); 767 }; 768 document.head.appendChild(script); 769 </script> 770 </div> 771 } 772 773 @if ((QuickDelivery || DisplayAverageDeliveryTime) && !HideDelivery) 774 { 775 <div class="w-100 mt-3"> 776 <div class="delivery-information"> 777 <svg class="delivery-icon mr-2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" fill="@DeliveryColor" x="0px" y="0px" width="30px" height="30px" viewBox="0 0 612 612" style="enable-background:new 0 0 612 612;" xml:space="preserve"> 778 <g><g> 779 <path d="M226.764,375.35c-28.249,0-51.078,22.91-51.078,51.16c0,28.166,22.829,51.078,51.078,51.078s51.078-22.912,51.078-51.078 C277.841,398.26,255.013,375.35,226.764,375.35z M226.764,452.049c-14.125,0-25.54-11.498-25.54-25.541 c0-14.123,11.415-25.539,25.54-25.539c14.124,0,25.539,11.416,25.539,25.539C252.302,440.551,240.888,452.049,226.764,452.049z M612,337.561v54.541c0,13.605-11.029,24.635-24.636,24.635h-26.36c-4.763-32.684-32.929-57.812-66.927-57.812 c-33.914,0-62.082,25.129-66.845,57.812H293.625c-4.763-32.684-32.93-57.812-66.845-57.812c-33.915,0-62.082,25.129-66.844,57.812 h-33.012c-13.606,0-24.635-11.029-24.635-24.635v-54.541H612L612,337.561z M494.143,375.35c-28.249,0-51.16,22.91-51.16,51.16 c0,28.166,22.912,51.078,51.16,51.078c28.166,0,51.077-22.912,51.077-51.078C545.22,398.26,522.309,375.35,494.143,375.35z M494.143,452.049c-14.125,0-25.539-11.498-25.539-25.541c0-14.123,11.414-25.539,25.539-25.539 c14.042,0,25.539,11.416,25.539,25.539C519.682,440.551,508.185,452.049,494.143,452.049z M602.293,282.637l-96.817-95.751 c-6.159-6.077-14.453-9.526-23.076-9.526h-48.86v-18.313c0-13.631-11.004-24.635-24.635-24.635H126.907 c-13.55,0-24.635,11.005-24.635,24.635v3.86L2.3,174.429l177.146,23.068L0,215.323l178.814,25.423L0,256.25l102.278,19.29 l-0.007,48.403h509.712v-17.985C611.983,297.171,608.452,288.796,602.293,282.637z M560.084,285.839h-93.697 c-2.135,0-3.86-1.724-3.86-3.859v-72.347c0-2.135,1.725-3.86,3.86-3.86h17.82c0.985,0,1.971,0.411,2.71,1.068l75.796,72.347 C565.257,281.569,563.532,285.839,560.084,285.839z" /> 780 </g></g> 781 </svg> 782 <p class="delivery-text @DeliveryFontWeightModifier">@DeliveryTime - <a href="#" class="text-underline" data-bind="click: ToggleDeliveryInfo" style="color: @DeliveryColor">@Translate("Product.DeliveryInfo.ReadmoreText", "L&aelig;s mere")</a></p> 783 </div> 784 </div> 785 } 786 </div> 787 } 788 else 789 { 790 <p>@Translate("Ecom:Product.NotForSaleMessage", "Produktet kan ikke købes.")</p> 791 } 792 </div> 793 794 @if (seeProductInStore != "") 795 { 796 <div class="d-flex flex-wrap flex-column justify-content-end border-grey p-4 mt-2"> 797 <div class="align-self-center w-100"> 798 <a href="@seeProductInStore" class="btn brand-primary-outline see-product-btn font-weight-bold add-to-cart m-0 d-flex align-items-center justify-content-center w-100 px-4">@Translate("Se produktet i en af vores butikker", "Se produktet i en af vores butikker")</a> 799 </div> 800 </div> 801 } 802 </div> 803 </div> 804 805 <div class="delivery-information-popup" data-bind="css: { 'd-flex': DeliveryInfoOpen }, click: ToggleDeliveryInfo"> 806 <div class="description-content bg-white px-3 py-4 px-lg-4 position-relative" data-bind="click: OpenDeliveryInfo, clickBubble: false"> 807 <div class="modal-closer-custom" data-bind="click: ToggleDeliveryInfo, clickBubble: false"> 808 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/close.svg" /> 809 </div> 810 @if (QuickDelivery) 811 { 812 <div> 813 @QuickDeliveryDescription 814 </div> 815 } 816 else if (DisplayAverageDeliveryTime) 817 { 818 <div> 819 @NormalDeliveryDescription 820 </div> 821 } 822 </div> 823 </div> 824 825 <div class="variant-information-popup" data-bind="css: { 'd-flex': VariantInfoOpen }, click: ToggleVariantInfo"> 826 <div class="description-content bg-white px-3 py-4 px-lg-4 position-relative" data-bind="click: OpenVariantInfo, clickBubble: false"> 827 <div class="modal-closer-custom" data-bind="click: ToggleVariantInfo, clickBubble: false"> 828 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/close.svg" /> 829 </div> 830 <p></p> 831 </div> 832 </div> 833 834 <div class="delivery-information-popup" data-bind="css: { 'd-flex': OptionalInfoOpen }, click: ToggleOptionalInfo"> 835 <div class="description-content bg-white px-3 py-4 px-lg-4 position-relative" data-bind="click: OpenOptionalInfo, clickBubble: false"> 836 <div class="modal-closer-custom" data-bind="click: ToggleOptionalInfo, clickBubble: false"> 837 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/close.svg" /> 838 </div> 839 <div> 840 @Translate("TilvalgInfoboks", "Tilvalg tekst") 841 </div> 842 </div> 843 </div> 844 845 @if (CostPrice > 0) 846 { 847 <div class="w-100 mt-3"> 848 849 <div class="delivery-information"> 850 <div class="live-price-animation"></div> 851 <p class="delivery-text">@Translate("Product.PriceInfo.RecommendedPriceInfo", "Aktuel dagspris - ")<a href="#" class="text-underline" data-bind="click: TogglePriceInfo">@Translate("Product.PriceInfo.RecommendedPriceLink", "L&aelig;s mere")</a></p> 852 </div> 853 854 </div> 855 } 856 857 <div class="w-100"> 858 @if (GetBoolean("Ecom:Product:Field.Farvevarianter1.Value")) 859 { 860 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver1.png" /> 861 <p class="mb-0">@Translate("ProductColor1Text", "F&aring;s i flere forskellige varianter og moduler, bes&oslash;g dit lokale M&oslash;blér bolighus og f&aring; vejledning til design af din sofa.")</p> 862 } 863 else if (GetBoolean("Ecom:Product:Field.Farvevarianter2.Value")) 864 { 865 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver2.png" /> 866 <p class="mb-0">@Translate("ProductColor2Text", "Farve 2 hj&aelig;lpetekst")</p> 867 } 868 else if (GetBoolean("Ecom:Product:Field.Farvevarianter3.Value")) 869 { 870 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver3.png" /> 871 <p class="mb-0">@Translate("ProductColor3Text", "Farve 3 hj&aelig;lpetekst")</p> 872 } 873 else if (GetBoolean("Ecom:Product:Field.Farvevarianter4.Value")) 874 { 875 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver4.png" /> 876 <p class="mb-0">@Translate("ProductColor4Text", "Farve 4 hj&aelig;lpetekst")</p> 877 } 878 else if (GetBoolean("Ecom:Product:Field.Farvevarianter5.Value")) 879 { 880 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver5.png" /> 881 <p class="mb-0">@Translate("ProductColor5Text", "Farve 5 hj&aelig;lpetekst")</p> 882 } 883 </div> 884 @SnippetEnd("PricesContainer") 885 886 @SnippetStart("ProductDetailsMeta") 887 @if (!string.IsNullOrEmpty(MetaDescription)) 888 { 889 <meta name="description" content="@MetaDescription" /> 890 } 891 @SnippetEnd("ProductDetailsMeta") 892 893 @SnippetStart("OgTags") 894 <meta property="og:type" content="product" /> 895 <meta property="og:description" content="@Regex.Replace(ShortDescription, "<.*?>", String.Empty)" /> 896 <meta property="og:image" content="@OgImage" /> 897 @SnippetEnd("OgTags") 898 899 @using System.Collections 900 @using Dynamicweb.Core 901 @using Dynamicweb.Ecommerce 902 @using Mobler.Website.CustomModules.MoblerHelpers 903 @using Dynamicweb.Ecommerce.Products 904 @using Dynamicweb.Ecommerce.Variants 905 @using Humanizer 906 @using Mobler.Website.CustomCode 907 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 908 909 @using Mobler.Website.CustomModules.MoblerHelpers 910 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 911 912 @helper RenderPricing(LoopItem product, bool hasVariants) 913 { 914 // Theming 915 string blackFridayTheme = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("BlackFridayTheme"); 916 917 // Pricing 918 DateTime newItemExpiryDate = product.GetDate( "Ecom:Product:Field.NewItemExpiryDate" ); 919 bool hasNewItemExpiryDate = newItemExpiryDate.Date > DateTime.Now.Date; 920 bool newItem = product.GetBoolean("Ecom:Product:Field.NewItem") && hasNewItemExpiryDate; 921 bool LowPrice = product.GetBoolean("Ecom:Product:Field.Splash3"); 922 double CostPrice = product.GetDouble("Ecom:Product:Field.FirstwebCostPrice.Value.Raw"); 923 string PriceSaving = product.GetString("Ecom:Product:Field.Spar.Value"); 924 double ActualPrice = product.GetDouble("Ecom:Product.Price.Price"); 925 926 // Initialize variables 927 double spar = 0; 928 double price = 0; 929 double normalPrice = 0; 930 931 string priceFormatted = ""; 932 string sparFormatted = ""; 933 string normalPriceFormatted = ""; 934 935 string campaignColor = ""; 936 string campaignText = ""; 937 string campaignDate = ""; 938 939 bool CampaignActiveOnProduct = product.GetBoolean("CampaignModule:Product.CampaignActiveOnProduct"); 940 if (!CampaignActiveOnProduct) 941 { 942 price = ActualPrice; 943 priceFormatted = MoblerHelpers.formatPrice(price); 944 } 945 else 946 { 947 normalPrice = product.GetDouble("CampaignModule:Product.CampaignProduct.NormalPrice"); 948 normalPriceFormatted = product.GetString("CampaignModule:Product.CampaignProduct.NormalPrice.FormattedRetail"); 949 950 price = product.GetDouble("CampaignModule:Product.CampaignProduct.CampaignPrice"); 951 priceFormatted = product.GetString("CampaignModule:Product.CampaignProduct.CampaignPrice.FormattedRetail"); 952 953 spar = product.GetDouble("CampaignModule:Product.CampaignProduct.DiscountAmount"); 954 sparFormatted = product.GetString("CampaignModule:Product.CampaignProduct.DiscountAmount.FormattedRetail"); 955 956 campaignColor = product.GetString("CampaignModule:Product.Campaign.Color"); 957 campaignText = product.GetString("CampaignModule:Product.Campaign.Text"); 958 } 959 960 // Set Splash Types 961 string splashType = ""; 962 if (campaignText == "KOMBI") 963 { 964 splashType = "combo"; 965 } 966 else if (CostPrice > 0) 967 { 968 splashType = "priceshape"; 969 } 970 else if (spar > 0) 971 { 972 splashType = "offer"; 973 } 974 else if (newItem) 975 { 976 splashType = "new"; 977 } 978 else if (LowPrice) 979 { 980 splashType = "low"; 981 } 982 983 <div> 984 <p class="product-item__price fs3 font-weight-bold"> 985 @if (hasVariants) 986 { 987 <span class="font-weight-semibold fs0 mr-2">@Translate("ProductPrice.From", "Fra")</span> 988 } 989 @priceFormatted 990 </p> 991 @if (splashType == "combo") 992 { 993 <div class="splash splash--on-top"> 994 <p class="m-0">@Translate("ProductCombinationOffer", "Sætpris")</p> 995 </div> 996 <div class="d-flex justify-content-between mb-2"> 997 <p class="color-subtle fs0 m-0 text-uppercase">@Translate("PriceBefore", "Før") @normalPriceFormatted</p> 998 <p class="splash fs0 text-uppercase m-0 px-2">@Translate("PriceSaving", "Spar") @sparFormatted</p> 999 </div> 1000 } 1001 else if (splashType == "priceshape") 1002 { 1003 string DailyPriceBackgroundColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("AktuelDagsprisBackgroundColor"); 1004 string DailyPriceTextColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("AktuelDagsprisTextColor"); 1005 1006 <div class="splash splash--on-top price-shape" style="background-color: @DailyPriceBackgroundColor"> 1007 <p class="m-0" style="color: @DailyPriceTextColor;">@Translate("ProductDailyPriceSplash", "Dagspris")</p> 1008 </div> 1009 } 1010 else if (splashType == "offer") 1011 { 1012 if (blackFridayTheme == "True") 1013 { 1014 <div class="splash splash--on-top bf-bg-black bf-color-white"> 1015 <p class="m-0">@Translate("ProductOffer", "Tilbud")</p> 1016 </div> 1017 } 1018 else 1019 { 1020 <div class="splash splash--on-top p-1"> 1021 <p class="m-0">@Translate("ProductOffer", "Tilbud")</p> 1022 </div> 1023 } 1024 <div class="d-flex justify-content-between mb-2"> 1025 <p class="color-subtle fs0 m-0 text-uppercase">@Translate("PriceBefore", "Før") @normalPriceFormatted</p> 1026 <p class="splash fs0 m-0 text-uppercase px-2">@Translate("PriceSaving", "Spar") @sparFormatted</p> 1027 </div> 1028 } 1029 else if (splashType == "new") 1030 { 1031 <div class="splash splash--on-top p-1 new-item"> 1032 <p class="m-0">@Translate("ProductNew", "Nyhed")</p> 1033 </div> 1034 } 1035 else if (splashType == "low") 1036 { 1037 <div class="splash splash--on-top p-1 low-price"> 1038 <p class="m-0">@Translate("ProductLowPrice", "Fast lavpris")</p> 1039 </div> 1040 } 1041 </div> 1042 } 1043 1044 1045 @helper RenderProduct(LoopItem product, Boolean powerStep = false) 1046 { 1047 // Group Specific - Exclude Bed Accessories 1048 bool excludeBedAccessories = product.GetBoolean("Ecom:Product.CategoryField.Senge.ExcludeBedAccessories.Value"); 1049 1050 // Product General Info 1051 string productId = product.GetString("Ecom:Product.ID"); 1052 string productName = product.GetString("Ecom:Product.Name"); 1053 string productLink = product.GetString("Ecom:Product.Link.Clean"); 1054 string shortDescription = product.GetString("Ecom:Product.ShortDescription"); 1055 string languageId = product.GetString("Ecom:Product.LanguageID"); 1056 1057 // Variants 1058 string defaultVariantId = product.GetString("Ecom:Product.DefaultVariantComboID"); 1059 string variantId = product.GetString("Ecom:Product.VariantID"); 1060 if (String.IsNullOrEmpty(variantId)) { 1061 variantId = defaultVariantId; 1062 } 1063 if (!String.IsNullOrEmpty(variantId)) { 1064 productLink = productLink + "&variantid=" + variantId; 1065 } 1066 1067 // Product Images 1068 List<string> images = MoblerHelpers.GetProductImages(productId, variantId); 1069 string productImage = string.Format("/Admin/Public/GetImage.ashx?Image={0}&Width=280&height=220&Format=png&Crop=5&resolution=50", images.FirstOrDefault()); //MoblerHelpers.GetProductListImageWithMainImage(ProductID, ProductNumber); 1070 1071 // Product Dimensions 1072 string productDepth = product.GetString("Ecom:Product:Field.dybdeint.Value.Clean"); 1073 string productHeight = product.GetString("Ecom:Product:Field.hoejdeint.Value.Clean"); 1074 string productWidth = product.GetString("Ecom:Product:Field.breddeint.Value.Clean"); 1075 bool hasProductDepth = !string.IsNullOrWhiteSpace(productDepth) && productDepth != "0"; 1076 bool hasProductHeight = !string.IsNullOrWhiteSpace(productHeight) && productHeight != "0"; 1077 bool hasProductWidth = !string.IsNullOrWhiteSpace(productWidth) && productWidth != "0"; 1078 1079 // Campaign 1080 string campaignDateStart = ""; 1081 string campaignDateEnd = ""; 1082 1083 bool campaignActiveOnProduct = product.GetBoolean("CampaignModule:Product.CampaignActiveOnProduct"); 1084 if (campaignActiveOnProduct) 1085 { 1086 campaignDateStart = product.GetString("CampaignModule:Product.CampaignProduct.Campaign.Start"); 1087 campaignDateEnd = product.GetString("CampaignModule:Product.CampaignProduct.Campaign.End"); 1088 } 1089 1090 bool hasCampaignDateStart = !string.IsNullOrWhiteSpace(campaignDateStart); 1091 1092 bool hasCampaignDateEnd = !string.IsNullOrWhiteSpace(campaignDateEnd); 1093 string campaignText = ""; 1094 if (hasCampaignDateStart && hasCampaignDateStart) 1095 { 1096 campaignText = $"{Translate("Campaign.BeforeDate.Text", "Gældende fra:")} {campaignDateStart} {Translate("Campaign.BeforeDate.Text2", "t.o.m.")} {campaignDateEnd}"; 1097 } 1098 1099 <div class="col-12 col-sm-6 col-lg-3 product-item js-product-list-item"> 1100 <div class="product-item__header"> 1101 <a href="@productLink" class="product-item__image"> 1102 <img class="js-product-image-@productId" src="@productImage" alt="@productName" loading="lazy"/> 1103 </a> 1104 @{ 1105 int colorOptionsToShow = 4; 1106 List<string> variantCombinationVariantIds = product.GetLoop("Co3VariantCombinations").Select(p => p.GetString("Ecom:VariantCombination.VariantID")).ToList(); 1107 bool hasVariants = false; 1108 } 1109 @if (variantCombinationVariantIds.Any() && !powerStep) 1110 { 1111 hasVariants = true; 1112 1113 <div class="product-item__variants d-flex align-items-center"> 1114 @foreach (LoopItem vg in product.GetLoop("VariantGroups")) 1115 { 1116 int variantOptionWithColorCount = 0; 1117 1118 @* Only show variants with hex colors *@ 1119 foreach (LoopItem variantOption in vg.GetLoop("VariantAvailableOptions")) 1120 { 1121 <p class="unimportant-hidden">@variantOptionWithColorCount</p> 1122 string variantOptionColor = variantOption.GetString("Ecom:VariantOption.ColorHex"); 1123 1124 // Get count of variants with color 1125 if (variantOptionColor.Any()) 1126 { 1127 variantOptionWithColorCount++; 1128 } 1129 // Only show this specific amount of variants 1130 if (variantOptionColor.Any() && variantOptionWithColorCount < colorOptionsToShow) 1131 { 1132 // Get variant option id, then compare with variant combinations, to get the link to the specific variant 1133 string variantOptionId = variantOption.GetString("Ecom:VariantOption.ID"); 1134 string variantIdWithColorOptionId = variantCombinationVariantIds.FirstOrDefault(vid => vid.Contains(variantOptionId)); 1135 1136 if (variantIdWithColorOptionId.IsNullOrEmpty() == false) 1137 { 1138 string variantLink = product.GetString("Ecom:Product.Link.Clean") + "&variantid=" + variantIdWithColorOptionId; 1139 <a href="@variantLink" class="product-item__variant" style="background-color: @variantOptionColor;"></a> 1140 } 1141 } 1142 else if (variantOptionColor.Any() && variantOptionWithColorCount == colorOptionsToShow) 1143 { 1144 <a href="@productLink" class="fs2 product-item__more-variants">+</a> 1145 } 1146 else 1147 { 1148 break; 1149 } 1150 } 1151 } 1152 @if (hasVariants) 1153 { 1154 <a href="@productLink" class="ml-4 fs-s"> 1155 <i class="fas fa-pen mr-1 fs-2"></i> 1156 @Translate("Ecom:Product.Pricing.Designer", "Design selv") 1157 </a> 1158 } 1159 </div> 1160 } 1161 </div> 1162 1163 <div class="product-item__body"> 1164 <a href="@productLink" class="product-item__title"> 1165 <h3 class="fs0">@productName</h3> 1166 </a> 1167 <div class="product-item__description fs0 color-subtle">@shortDescription</div> 1168 @if (hasProductDepth && !powerStep || hasProductHeight && !powerStep || hasProductWidth && !powerStep) 1169 { 1170 <p class="product-item__dimensions fs0 color-subtle"> 1171 @if (hasProductDepth) 1172 { 1173 <span>D/L: @productDepth</span> 1174 } 1175 @if (hasProductHeight) 1176 { 1177 <span>H: @productHeight</span> 1178 } 1179 @if (hasProductWidth) 1180 { 1181 <span>B: @productWidth</span> 1182 } 1183 </p> 1184 } 1185 </div> 1186 1187 <div class="product-item__footer"> 1188 @RenderPricing(product, hasVariants) 1189 1190 @if (excludeBedAccessories && !powerStep) 1191 { 1192 <p class="color-subtle fs-s m-0">@Translate("Ecom:Product.Pricing.Excludes.Beds", "Prisen er ekskl. ben og gavl.")</p> 1193 } 1194 @if (hasVariants && !powerStep) 1195 { 1196 <div class="variant-price-disclaimer color-subtle fs-s">@Translate("VariantPriceDisclaimer", "Prisen kan variere efter materialevalg")</div> 1197 } 1198 @if (hasCampaignDateStart && hasCampaignDateEnd && !powerStep) 1199 { 1200 <div class="product-item__campaign"> 1201 <p class="color-subtle fs-s">@campaignText</p> 1202 </div> 1203 } 1204 </div> 1205 </div> 1206 } 1207 1208 @using Mobler.Website.CustomModules.MoblerHelpers 1209 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1210 1211 @helper RenderBlogTeaser(Firstweb.Custom.CustomCode.Frontend.Helpers.Blog Blog) 1212 { 1213 string PageId = GetGlobalValue( "Global:Page.ID" ); 1214 string CleanLink = Blog.Link.Replace("default.aspx?id", "Default.aspx?Id"); 1215 <div class="col-12 col-md-4 px-0 px-md-3 mb-4"> 1216 <a href="@CleanLink" class="blog d-block"> 1217 <div class="image" style="background-image:url('@Blog.Image')"> 1218 <img class="d-none" src="@Blog.Image" alt="Alternate Text" /> 1219 </div> 1220 <div class="text"> 1221 <div class="positioning"> 1222 <h4 class="col-10 col-md-9 px-2 pt-3 bg-white font-weight-bold text-center mx-auto">@Blog.Header</h4> 1223 @if ( PageId != "7613" ) 1224 { 1225 <p class="text-center color-subtle">@Blog.Date</p> 1226 } 1227 <p class="text-center font-weight-bold m-0 color-primary">@Translate("BlogReadMore", "L&aelig;s mere her")</p> 1228 </div> 1229 </div> 1230 </a> 1231 </div> 1232 } 1233 1234 @helper RenderLargeBlogTeaser(Firstweb.Custom.CustomCode.Frontend.Helpers.Blog Blog, string ImagePosition) 1235 { 1236 string ImageClass = ImagePosition == "Left" ? "" : "offset-md-4"; 1237 string TextClass = ImagePosition == "Left" ? "" : "left"; 1238 string Image = "/Admin/Public/GetImage.ashx?Image=" + Blog.Image + "&Height=400&Crop=0"; 1239 string CleanLink = Blog.Link.Replace("default.aspx?id", "Default.aspx?Id"); 1240 <div class="col-12 blog"> 1241 <div class="row"> 1242 <div class="col-12 col-md-8 px-0 px-md-3 @ImageClass"> 1243 <div class="image-container" style="background-image:url('@Image')"> 1244 <img class="img-fluid" src="@Image" alt="@Blog.Header" /> 1245 </div> 1246 </div> 1247 <div class="col-12 col-md-6 text-container mb-5 mb-md-0 @TextClass"> 1248 <div class="text bg-white p-3"> 1249 <div> 1250 <h4>@Blog.Header</h4> 1251 @Blog.Teaser 1252 </div> 1253 <a class="font-weight-bold" href="@CleanLink">@Translate("BlogReadMore", "L&aelig;s mere her")</a> 1254 </div> 1255 </div> 1256 </div> 1257 </div> 1258 } 1259 1260 @helper RenderLatestBlogsTeasers() 1261 { 1262 var LatestBlogs = Firstweb.Custom.CustomCode.Frontend.Helpers.Blogs.GetLatestBlogs(); 1263 foreach (var Blog in LatestBlogs) 1264 { 1265 @RenderBlogTeaser(Blog) 1266 } 1267 } 1268 1269 1270 <div class="container d-none d-md-block"> 1271 <div class="bread"> 1272 <p class="color-subtle">@Translate("Breadcrumb.CurrentPage", "Her er du:")</p> 1273 <p class="bread-item color-subtle"> 1274 <a href="/"> 1275 @Translate("Breadcrumb.Frontpage", "Forside") 1276 </a> 1277 </p> 1278 @foreach (var Group in ParentGroups) 1279 { 1280 <p class="bread-item color-subtle"> 1281 @if (Group == ParentGroups.First()) 1282 { 1283 @Group.Name 1284 ShowOnPageUrl = Group.ProductGroupFieldValues.GetProductGroupFieldValue("FirstwebGroupPrimaryPage").Value.ToString(); 1285 } 1286 else 1287 { 1288 <a href="/@ShowOnPageUrl&GroupId=@Group.Id"> 1289 @Group.Name 1290 </a> 1291 } 1292 </p> 1293 } 1294 <p class="active color-subtle">@ProductName</p> 1295 </div> 1296 </div> 1297 1298 <div class="container my-5 product-details position-relative" data-bind="viewModel: 'ProductViewModel'"> 1299 <div class="d-none" data-bind="setInitValue: { observable: CartPageId, value: '@AjaxCartPageId' }"></div> 1300 <div class="d-none" data-bind="setInitValue: { observable: MiniCart, value: '.js-mini-cart-lines' }"></div> 1301 <div class="d-none" data-bind="setInitValue: { observable: CartCount, value: '.js-cart-count' }"></div> 1302 <div class="d-none" data-bind="setInitValue: { observable: CustomersAlsoSawLines, value: '.js-customers-also-saw-lines' }"></div> 1303 <div class="d-none" data-bind="setInitValue: { observable: CustomersAlsoSawPage, value: '@CustomersAlsoSawPageId' }"></div> 1304 <div class="d-none" data-bind="setInitValue: { observable: RelewiseRecommandationsEndpoint, value: '@relewiseRecommandationsEndpoint' }"></div> 1305 <div class="d-none" data-bind="setInitValue: { observable: MainProductId, value: '@ProductID' }"></div> 1306 <div class="d-none" data-bind="setInitValue: { observable: VariantsEndpoint, value: '@VariantsEndpoint' }"></div> 1307 <div class="d-none" data-bind="setInitValue: { observable: VariantDetailsEndpoint, value: '@VariantDetailsEndpoint' }"></div> 1308 <div class="d-none" data-bind="setInitValue: { observable: TeaserText, value: '@TrimmedTeaser' }"></div> 1309 <div class="d-none" data-bind="setInitValue: { observable: ProductName, value: '@TrimmedName' }"></div> 1310 <div class="d-none" data-bind="setInitValue: { observable: ProductNumber, value: '@ProductNumber' }"></div> 1311 <div class="d-none" data-bind="setInitValue: { observable: VariantId, value: '@VariantId' }"></div> 1312 <div class="d-none" data-bind="setInitValue: { observable: Price, value: '@priceFormatted' }"></div> 1313 <div class="d-none" data-bind="setInitValue: { observable: PriceDouble, value: '@price' }"></div> 1314 1315 <div class="d-none js-update-cart" data-bind="setInitValue: { observable: CartEndpoint, value: '@GetCartEndpoint' }, click: GetCart"></div> 1316 1317 <h1 class="header fs4 mb-5" data-bind="text: ProductName">@ProductName</h1> 1318 <p class="color-subtle fs0 mt-0 mb-2">@Translate("ProductProductNumber", "Produktnummer:") <span data-bind="text: ProductNumber">@ProductNumber</span></p> 1319 <div class="short-description mb-4 fs2 content-left"> 1320 @ShortDescription 1321 <p class="m-0"> 1322 @if ( !string.IsNullOrWhiteSpace( GetString( "Ecom:Product:Field.dybdeint.Value.Clean" ) ) ) 1323 { 1324 if ( GetString( "Ecom:Product:Field.dybdeint.Value.Clean" ) != "0" ) 1325 { 1326 <span>D/L: @GetValue( "Ecom:Product:Field.dybdeint.Value.Clean" )</span> 1327 } 1328 } 1329 @if ( !string.IsNullOrWhiteSpace( GetString( "Ecom:Product:Field.hoejdeint.Value.Clean" ) ) ) 1330 { 1331 if ( GetString( "Ecom:Product:Field.hoejdeint.Value.Clean" ) != "0" ) 1332 { 1333 <span>H: @GetValue( "Ecom:Product:Field.hoejdeint.Value.Clean" )</span> 1334 } 1335 } 1336 @if ( !string.IsNullOrWhiteSpace( GetString( "Ecom:Product:Field.breddeint.Value.Clean" ) ) ) 1337 { 1338 if ( GetString( "Ecom:Product:Field.breddeint.Value.Clean" ) != "0" ) 1339 { 1340 <span>B: @GetValue( "Ecom:Product:Field.breddeint.Value.Clean" )</span> 1341 } 1342 } 1343 </p> 1344 </div> 1345 1346 <div class="d-flex flex-wrap product-top"> 1347 <div class="image-container position-relative overflow-hidden"> 1348 <div class="splash splash--on-top unimportant-hidden" data-bind="css: { 'd-flex': SplashType() == 1 }"><p class="m-0">@Translate("ProductOffer", "Tilbud")</p></div> 1349 <div class="splash splash--on-top unimportant-hidden new-item" data-bind="css: { 'd-flex': SplashType() == 2 }"><p class="m-0">@Translate("ProductNew", "Nyhed")</p></div> 1350 <div class="splash splash--on-top unimportant-hidden low-price" data-bind="css: { 'd-flex': SplashType() == 3 }"><p class="m-0">@Translate("ProductLowPrice", "Fast lavpris")</p></div> 1351 <div class="splash splash--on-top unimportant-hidden price-shape" data-bind="css: { 'd-flex': SplashType() == 4 }" style="background-color: @DailyPriceBackgroundColor;"><p class="m-0" style="color: @DailyPriceTextColor;">@Translate("ProductDailyPriceSplash", "Dagspris")</p></div> 1352 <div class="splash splash--on-top unimportant-hidden splash--small" data-bind="css: { 'd-flex': SplashType() == 5}"><p class="m-0">@Translate("ProductCombinationOffer", "Sætpris")</p></div> 1353 1354 <div id="imageSlider" class="carousel slide" data-ride="carousel" data-interval="5000"> 1355 <div class="carousel-inner align-items-center" data-bind="if: Images().length == 0"> 1356 1357 @foreach (var Image in Images) 1358 { 1359 if (First) 1360 { 1361 <a href="/Admin/Public/GetImage.ashx?Image=@Image&width=2000" class="mb-3 mb-lg-0 carousel-item active" data-gallery> 1362 <img class="product-image main-image" src="/Admin/Public/GetImage.ashx?Image=@Image&width=800&height=500&crop=5" alt="@ProductName" /> 1363 </a> 1364 First = false; 1365 FirstImage = "/Admin/Public/GetImage.ashx?Image=" + Image + "&width=800&height=500&crop=5"; 1366 } 1367 else 1368 { 1369 <a href="/Admin/Public/GetImage.ashx?Image=@Image&width=1600" class="mb-3 mb-lg-0 carousel-item" data-gallery> 1370 <img class="product-image main-image" src="/Admin/Public/GetImage.ashx?Image=@Image&width=800&height=500&crop=5" alt="@ProductName" /> 1371 </a> 1372 } 1373 1374 } 1375 1376 </div> 1377 <div class="carousel-inner align-items-center d-flex js-ko-carousel" data-bind="foreach: Images()"> 1378 1379 <a data-bind="attr: { href: '/Admin/Public/GetImage.ashx?Image=' + $data + '&width=1600' }" class="mb-3 mb-lg-0 carousel-item active" data-gallery> 1380 <img class="product-image main-image" data-bind="attr: { src: '/Admin/Public/GetImage.ashx?Image=' + $data + '&width=800&height=500&crop=5' }" /> 1381 </a> 1382 1383 </div> 1384 </div> 1385 1386 @if (Images.Count > 0) 1387 { 1388 <div class="row small-gutter carousel-row mb-2" data-bind="css: { 'd-none': Images().length > 0 }"> 1389 @if (Images.Count > 0) 1390 { 1391 foreach (var Image in Images) 1392 { 1393 if (FirstIndicator) 1394 { 1395 <div data-target="#imageSlider" data-slide-to="@IndicatorIncrementer" class="col-4 mt-lg-3 cursor-pointer active"> 1396 <div class="secondary-image"> 1397 <img class="product-image" src="/Admin/Public/GetImage.ashx?Image=@Image&width=400&height=230&crop=5" alt="@ProductName" /> 1398 </div> 1399 </div> 1400 FirstIndicator = false; 1401 } 1402 else 1403 { 1404 <div data-target="#imageSlider" data-slide-to="@IndicatorIncrementer" class="col-4 mt-lg-3 cursor-pointer"> 1405 <div class="secondary-image"> 1406 <img class="product-image" src="/Admin/Public/GetImage.ashx?Image=@Image&width=160&height=100&crop=5" alt="@ProductName" /> 1407 </div> 1408 </div> 1409 } 1410 IndicatorIncrementer++; 1411 } 1412 } 1413 1414 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoKlip.Value"))) 1415 { 1416 string BackgroundSize = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoBillede.Value.Clean")) ? "cover" : "contain"; 1417 string OverlayImage = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoBillede.Value.Clean")) ? GetString("Ecom:Product:Field.VideoBillede.Value.Clean") : FirstImage; 1418 <div class="youtube-video-container col-4 mt-lg-3" data-bind="youtubeVideo: { videoId: '@GetString("Ecom:Product:Field.VideoKlip.Value")', overlayId: 'js-video-overlay', playerId: 'player' }"> 1419 <div id="js-video-overlay" class="video-overlay pointer" style="background-image:url('@OverlayImage');background-size: @BackgroundSize;"> 1420 <div class="visual-overlay d-flex flex-column justify-content-center align-items-center h-100 w-100"> 1421 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/Play.svg" /> 1422 </div> 1423 </div> 1424 </div> 1425 } 1426 1427 </div> 1428 1429 <div class="row small-gutter carousel-row mb-2 unimportant-hidden" data-bind="css: { 'd-flex': Images().length > 0 }"> 1430 <span class="images" style="display:contents;" data-bind="foreach: Images()"> 1431 <!-- ko if: $index() == 0 --> 1432 <div data-target="#imageSlider" class="col-4 mt-lg-3 cursor-pointer active" data-bind="click: $parent.ChangeSlide.bind($data, $index())"> 1433 <div class="secondary-image"> 1434 <img class="product-image" data-bind="attr: { src: '/Admin/Public/GetImage.ashx?Image=' + $data + '&width=400&height=230&crop=5' }" alt="@ProductName" /> 1435 </div> 1436 </div> 1437 <!-- /ko --> 1438 <!-- ko if: $index() != 0 --> 1439 <div data-target="#imageSlider" class="col-4 mt-lg-3 cursor-pointer" data-bind="click: $parent.ChangeSlide.bind($data, $index())"> 1440 <div class="secondary-image"> 1441 <img class="product-image" data-bind="attr: { src: '/Admin/Public/GetImage.ashx?Image=' + $data + '&width=400&height=230&crop=5' }" alt="@ProductName" /> 1442 </div> 1443 </div> 1444 <!-- /ko --> 1445 </span> 1446 1447 @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoKlip.Value"))) 1448 { 1449 string BackgroundSize = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoBillede.Value.Clean")) ? "cover" : "contain"; 1450 string OverlayImage = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoBillede.Value.Clean")) ? GetString("Ecom:Product:Field.VideoBillede.Value.Clean") : FirstImage; 1451 <div class="youtube-video-container mt-lg-3" data-bind="youtubeVideo: { videoId: '@GetString("Ecom:Product:Field.VideoKlip.Value")', overlayId: 'js-videovariant-overlay', playerId: 'player' }"> 1452 <div id="js-videovariant-overlay" class="video-overlay pointer" style="background-image:url('@OverlayImage');background-size: @BackgroundSize;"> 1453 <div class="visual-overlay d-flex flex-column justify-content-center align-items-center h-100 w-100"> 1454 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/Play.svg" /> 1455 <p class="mt-3 mb-0 color-white">@Translate("Product.WatchVideo", "Se video")</p> 1456 </div> 1457 </div> 1458 </div> 1459 } 1460 </div> 1461 } 1462 1463 <div class="shortcuts d-flex"> 1464 <div class="shortcuts__header fs0"><b>@Translate( "ShortCuts", "Genveje:" )</b></div> 1465 <div class="shortcuts__body"> 1466 @if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProviderLink.Value.Clean"))) 1467 { 1468 <div class="shortcut"><i class="fa-solid fa-pen"></i> <a href="@GetString("Ecom:Product:Field.ProviderLink.Value.Clean")" target="_blank">@Translate("Product.DesignYourself.Title", "Design selv")</a></div> 1469 } 1470 <div class="shortcut" data-bind="click: ScrollToElement.bind($element, specifications)"><i class="fa fa-clipboard"></i> <a href="#">@Translate("Product.Specifications.Title", "Specifikationer" )</a></div> 1471 @if ( !String.IsNullOrEmpty( ProductCatalogLink ) ) 1472 { 1473 <div class="shortcut"><i class="fa fa-book-open"></i> <a href="@ProductCatalogLink" target="_blank">@Translate( "Product.InspirationBrochure.Title", "Inspirationsbrochure" )</a></div> 1474 } 1475 </div> 1476 </div> 1477 1478 @* <div class="pl-lg-4 prices-container flex-wrap flex-column mt-3 mt-lg-0 position-relative d-flex d-lg-none"> *@ 1479 @* @RenderSnippet("PricesContainer") *@ 1480 @* </div> *@ 1481 1482 <div class="product-bottom-details"> 1483 <div class="d-flex flex-wrap mt-5"> 1484 <div id="js-full-description"> 1485 <h2 class="fs3 mb-2 font-weight-bold">@Translate("Product.ProductDescription.Title", "Produktbeskrivelse")</h2> 1486 <div class="usps d-flex mt-4 mb-4"> 1487 <div class="usps--usp d-flex align-items-center"><i class="@usp1IconClass"></i><strong>@usp1IconText</strong></div> 1488 <div class="usps--usp d-flex align-items-center"><i class="@usp2IconClass"></i><strong>@usp2IconText</strong></div> 1489 <div class="usps--usp d-flex align-items-center"><i class="@usp3IconClass"></i><strong>@usp3IconText</strong></div> 1490 </div> 1491 1492 <div class="product-description"> 1493 <div class="product-description--inner read-more-container"> 1494 <div class="unimportant-hidden" data-bind="html: FullDescription, css: { 'd-block': FullDescription().length > 0 }"></div> 1495 </div> 1496 <p class="read-more"><a href="#" class="text-underline" data-bind="click: ProductDescriptionReadMore.bind($data, $element)">@Translate("Product.Description.ReadMore.Title", "Læs hele beskrivelsen")</a></p> 1497 </div> 1498 1499 <div class="product-description" data-bind="css: { 'd-none': FullDescription().length > 0 }"> 1500 <div class="product-description--inner read-more-container"> 1501 @LongDescription 1502 @if ( !string.IsNullOrEmpty( productionDescription ) ) 1503 { 1504 <h4 class="mt-4">@Translate( "Product.ProductionDescription.Title", "Produktionsbeskrivelse" )</h4> 1505 @:@productionDescription 1506 } 1507 </div> 1508 <p class="read-more"><a href="#" class="text-underline" data-bind="click: ProductDescriptionReadMore.bind($data, $element)">@Translate( "Product.ProductDescription.ReadMore.Title", "Læs hele beskrivelsen" )</a></p> 1509 </div> 1510 </div> 1511 1512 </div> 1513 1514 <div class="d-flex flex-wrap mt-5"> 1515 <div id="specifications" class="specifications-container w-100"> 1516 <h2 class="fs3 mb-4 font-weight-bold">@Translate("Product.Specifications.Title", "Specifikationer")</h2> 1517 <div class="product-specifications"> 1518 @* Render product specifications from variants *@ 1519 <dl class="d-flex flex-wrap w-100 read-more-container unimportant-hidden" data-bind="foreach: Specifications"> 1520 <dt class="w-50 border-top" data-bind="text: Name"></dt> 1521 <dd class="w-50 border-top" data-bind="text: Value"></dd> 1522 </dl> 1523 1524 <dl class="d-flex flex-wrap w-100 read-more-container" data-bind="css: { 'd-none': Specifications().length > 0 }"> 1525 @foreach (LoopItem displayGroup in GetLoop("FieldDisplayGroups")) 1526 { 1527 foreach (LoopItem field in displayGroup.GetLoop("Fields")) 1528 { 1529 if (!field.GetString("Ecom:FieldDisplayGroup.Field.Value").IsNullOrEmpty() && field.GetString("Ecom:FieldDisplayGroup.Field.Value") != "0" && !field.GetString("Ecom:FieldDisplayGroup.Field.Value").Contains(",,")) 1530 { 1531 <dt class="w-50 border-top">@field.GetString("Ecom:FieldDisplayGroup.Field.Name")</dt> 1532 <dd class="w-50 border-top"> 1533 @if (field.GetBoolean("Ecom:FieldDisplayGroup.Field.IsList")) 1534 { 1535 @field.GetString("Ecom:FieldDisplayGroup.Field.OptionLabel") 1536 } 1537 else 1538 { 1539 @field.GetString("Ecom:FieldDisplayGroup.Field.Value") 1540 } 1541 </dd> 1542 } 1543 } 1544 } 1545 </dl> 1546 <p class="read-more"><a href="#" class="text-underline" data-bind="click: ProductDescriptionReadMore.bind($data, $element)">@Translate("Product.Specifications.ReadMore.Title", "Vis alle specifikationer")</a></p> 1547 </div> 1548 </div> 1549 </div> 1550 </div> 1551 </div> 1552 1553 <div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls"> 1554 <div class="slides"></div> 1555 <h3 class="title"></h3> 1556 <a class="prev">&#8249;</a> 1557 <a class="next">&#8250;</a> 1558 <a class="close">x</a> 1559 <a class="play-pause"></a> 1560 <ol class="indicator"></ol> 1561 </div> 1562 1563 <div class="pl-lg-4 prices-container flex-wrap flex-column mt-3 mt-lg-0 position-relative"> 1564 @RenderSnippet("PricesContainer") 1565 </div> 1566 </div> 1567 @if (!string.IsNullOrEmpty(productCatalogueImage)) 1568 { 1569 <img id="GroupCatalogueImage" class="unimportant-hidden" src="/Admin/Public/GetImage.ashx?Image=/Files/Images/@productCatalogueImage&Width=320&height=200&Format=png&Crop=5&resolution=50" /> 1570 } 1571 @if (uspPageId > 0) 1572 { 1573 <div class="productdetail-usps mt-8 d-flex"> 1574 <div class="row"> 1575 @RenderPageContent(uspPageId) 1576 </div> 1577 </div> 1578 } 1579 1580 @if (showRecommendations) 1581 { 1582 <div id="customersAlsoViewed" class="related-products unimportant-hidden"> 1583 <div class="related-products__header mb-4"> 1584 <h4>@Translate("Product:RelewiseCustomersAlsoViewed.Headline", "Andre har også set")</h4> 1585 </div> 1586 <div id="customersAlsoViewedContainer" class="related-products__body"> 1587 </div> 1588 </div> 1589 } 1590 1591 @if (showRecommendations && !userIsAnonymous) 1592 { 1593 <div id="recentlyViewedProducts" class="related-products unimportant-hidden"> 1594 <div class="related-products__header mb-4"> 1595 <h4>@Translate("Product:RelewiseLatestVisitedProducts.Headline", "Dine seneste besøgte produkter")</h4> 1596 </div> 1597 <div id="recentlyViewedProductsContainer" class="related-products__body"> 1598 1599 </div> 1600 </div> 1601 } 1602 1603 <div class="after-add-to-cart bg-white box-shadow" data-bind="css: { 'd-block': ProductAddedToCart }"> 1604 <div class="closer fs3 pointer" data-bind="click: ProductAddedToCart(false)"> 1605 <i class="fas fa-times-circle color-primary"></i> 1606 </div> 1607 <div class="after-add-to-cart__inner"> 1608 <div class="p-3"> 1609 <p class="font-weight-bold fs4 text-uppercase m-0"> 1610 <i class="fas fa-check-circle color-primary"></i> 1611 @Translate("ProductProductAddedToCart", "Varen er lagt i indk&oslash;bskurven") 1612 </p> 1613 </div> 1614 <div class="mini-cart large-cart"> 1615 1616 <div class="position-relative"> 1617 <div class="cart-command-loader unimportant-hidden justify-content-center align-items-center" data-bind="css: { 'd-flex': Loading }"> 1618 <div class="d-flex align-items-center"> 1619 <p class="m-0 mr-2">@Translate("Cart.UpdatingCart", "Opdaterer kurv")</p> 1620 <i class="fas fa-circle-notch fa-spin"></i> 1621 </div> 1622 </div> 1623 1624 <div class="lines" data-bind="foreach: Orderlines"> 1625 <div class="cartline d-flex justify-content-between align-items-center px-3 py-2 position-relative bg-grey"> 1626 <span class="delete-orderline color-subtle cursor-pointer mr-2" data-bind="click: $parent.DeleteOrderline.bind($data, OrderlineId)"> 1627 <i class="fas fa-times"></i> 1628 </span> 1629 <div class="product-image w-10"> 1630 <img class="img-fluid" data-bind="attr: { src: ImagePath }"/> 1631 </div> 1632 <div class="flex-fill px-3 w-75"> 1633 <p class="font-weight-bold m-0" data-bind="text: ProductName"></p> 1634 <p class="m-0 color-subtle small-quantity-indicator"><span data-bind="text: Quantity"></span> stk. a <span data-bind="text: QuantityPrice"></span></p> 1635 <div class="variant-dimensions" data-bind="foreach: VariantDimensions"> 1636 <p class="m-0 color-subtle color-dark-grey font-weight-bold"> 1637 <span data-bind="text: Label"></span> 1638 <span class="font-weight-normal" data-bind="text: Value"></span> 1639 </p> 1640 </div> 1641 </div> 1642 <div class="qty-counter mr-1"> 1643 <div class="d-flex"> 1644 <div class="quantity-controls d-flex align-items-center mr-3"> 1645 <div class="control minus" data-bind="click: $parent.QuantityControl.bind($data, -1, OrderlineId)"> 1646 - 1647 </div> 1648 <input disabled type="text" name="Quantity" value="1" data-bind="value: Quantity, attr: { 'data-id': 'js-input-' + OrderlineId }"/> 1649 <div class="control plus" data-bind="click: $parent.QuantityControl.bind($data, 1, OrderlineId)"> 1650 + 1651 </div> 1652 </div> 1653 </div> 1654 </div> 1655 1656 <p class="fs0 m-0 orderline-price" data-bind="text: OrderlinePrice"></p> 1657 </div> 1658 </div> 1659 @if (BlackFridayTheme == "True") 1660 { 1661 <div class="bf-bg-black p-3 d-flex justify-content-between align-items-center price-summary"> 1662 <p class="m-0 color-white fs-12px font-weight-semibold">@Translate("MiniCartTotal", "Din kurv i alt (ex. fragt)")</p> 1663 <p class="m-0 color-white fs1 font-weight-bold" data-bind="text: CartTotalNoFees"></p> 1664 </div> 1665 } 1666 else 1667 { 1668 <div class="bg-brand p-3 d-flex justify-content-between align-items-center price-summary"> 1669 <p class="m-0 color-white fs-12px font-weight-semibold">@Translate("MiniCartTotal", "Din kurv i alt (ex. fragt)")</p> 1670 <p class="m-0 color-white fs1 font-extra-bold" data-bind="text: CartTotalNoFees"></p> 1671 </div> 1672 } 1673 </div> 1674 1675 </div> 1676 1677 <div id="purchasedWith" class="power-step unimportant-hidden"> 1678 <div class="power-step__header"> 1679 <h4>@Translate("Checkout.PowerStep.Title", "Andre har også købt")</h4> 1680 </div> 1681 <div id="purchasedWithContainer"> 1682 </div> 1683 </div> 1684 1685 <div class="p-3 d-flex justify-content-between"> 1686 <p class="pointer py-2 px-3 bg-dark-grey color-white rounded m-0" data-bind="click: ProductAddedToCart(false)">@Translate("MiniCartContinueShopping", "Handel videre")</p> 1687 1688 @if (BlackFridayTheme == "True") 1689 { 1690 <a href="@CartPage" class="pointer py-2 px-3 bf-bg-black color-white rounded d-block no-underline">@Translate("MiniCartGoToCheckout", "G&aring; til kassen")</a> 1691 } 1692 else 1693 { 1694 <a href="@CartPage" class="pointer py-2 px-3 bg-brand color-white rounded d-block no-underline">@Translate("MiniCartGoToCheckout", "G&aring; til kassen")</a> 1695 } 1696 1697 </div> 1698 <div class="js-customers-also-saw-lines"></div> 1699 </div> 1700 </div> 1701 <div class="variant-picker" data-bind="css: { 'open': VariantPickerOpen }"> 1702 <div class="closer color-primary fs5 pointer" data-bind="click: ToggleVariantPicker"> 1703 <i class="fas fa-times-circle"></i> 1704 </div> 1705 <div class="container py-5 position-relative"> 1706 <h3 class="fs4 text-center">Design din @ProductName</h3> 1707 @{ 1708 var ColorDimensions = GetLoop( "VariantGroups" ).Where( g => g.GetString( "Ecom:VariantGroup.Name" ).ToLower().Contains( "farve" ) ); 1709 var NonColorDimensions = GetLoop( "VariantGroups" ).Where( g => !g.GetString( "Ecom:VariantGroup.Name" ).ToLower().Contains( "farve" ) ); 1710 int FilterCounter = 0; 1711 string RowClass = NonColorDimensions.Any() && ColorDimensions.Any() ? "flex-row-reverse" : ""; 1712 } 1713 <div class="row mt-5 @RowClass"> 1714 @if ( ColorDimensions.Any() ) 1715 { 1716 <div class="col-12 col-md-8"> 1717 @foreach ( var VariantDimension in ColorDimensions ) 1718 { 1719 string DimensionName = VariantDimension.GetString( "Ecom:VariantGroup.Name" ); 1720 string FilterName = "filter-" + FilterCounter; 1721 FilterCounter++; 1722 <div class="mb-5 mb-md-0"> 1723 <p class="font-weight-bold fs2 mb-2">@DimensionName</p> 1724 <div class="row custom-row"> 1725 @foreach ( var VariantOption in VariantDimension.GetLoop( "VariantAvailableOptions" ).OrderBy( v => v.GetString( "Ecom:VariantOption.Name" ) ) ) 1726 { 1727 string VariantOptionName = VariantOption.GetString( "Ecom:VariantOption.Name" ); 1728 string VariantOptionId = VariantOption.GetString( "Ecom:VariantOption.ID" ); 1729 string Preview = VariantOption.GetString( "Ecom:VariantOption.ImgSmall.Clean" ); 1730 string PreviewCss = ""; 1731 if ( !String.IsNullOrEmpty( Preview ) ) 1732 { 1733 if ( Preview.StartsWith( "#" ) ) 1734 { 1735 PreviewCss = "style= \"background-color: " + Preview + ";\""; 1736 } 1737 else 1738 { 1739 PreviewCss = "style=\"background-image: url('" + Preview + "');\""; 1740 } 1741 } 1742 <div class="col-2 col-sm-3 col-md-2 mb-3 d-flex flex-column justify-content-end pointer color-variant" data-bind="click: AddToFilter.bind($data, $element, '@FilterName', '@VariantOptionId')"> 1743 <p class="mb-0 color-variant-name d-none d-sm-block">@VariantOptionName</p> 1744 <div class="variant-preview position-relative d-flex" @PreviewCss></div> 1745 </div> 1746 } 1747 </div> 1748 </div> 1749 } 1750 </div> 1751 } 1752 @if ( NonColorDimensions.Any() ) 1753 { 1754 <div class="col-12 col-sm-6 col-md-4"> 1755 @foreach ( var VariantDimension in NonColorDimensions ) 1756 { 1757 string DimensionName = VariantDimension.GetString( "Ecom:VariantGroup.Name" ); 1758 string FilterName = "filter-" + FilterCounter; 1759 FilterCounter++; 1760 <div class="mb-5"> 1761 <p class="font-weight-bold fs2 mb-2">@DimensionName</p> 1762 <div class="row custom-row"> 1763 @foreach ( var VariantOption in VariantDimension.GetLoop( "VariantAvailableOptions" ).OrderBy( v => v.GetString( "Ecom:VariantOption.Name" ) ) ) 1764 { 1765 string VariantOptionName = VariantOption.GetString( "Ecom:VariantOption.Name" ); 1766 string VariantOptionId = VariantOption.GetString( "Ecom:VariantOption.ID" ); 1767 string Preview = VariantOption.GetString( "Ecom:VariantOption.ImgSmall.Clean" ); 1768 string PreviewCss = ""; 1769 if ( !String.IsNullOrEmpty( Preview ) ) 1770 { 1771 if ( Preview.StartsWith( "#" ) ) 1772 { 1773 PreviewCss = "style= \"background-color: " + Preview + ";\""; 1774 } 1775 else 1776 { 1777 PreviewCss = "style=\"background-image: url('/Files" + Preview + "');\""; 1778 } 1779 } 1780 if ( DimensionName == "STØRRELSE" ) 1781 { 1782 <div class="col-6 col-sm-4 mb-3 d-flex flex-column justify-content-end pointer size-variant" data-bind="click: AddToFilter.bind($data, $element, '@FilterName', '@VariantOptionId')"> 1783 <div class="variant-preview position-relative d-flex justify-content-center align-items-center" @PreviewCss> 1784 <p class="mb-0 color-variant-name font-weight-bold">@VariantOptionName</p> 1785 </div> 1786 </div> 1787 } 1788 else 1789 { 1790 <div class="col-6 col-sm-4 mb-3 d-flex flex-column justify-content-end pointer" data-bind="click: AddToFilter.bind($data, $element, '@FilterName', '@VariantOptionId')"> 1791 <p class="mb-0 color-variant-name">@VariantOptionName</p> 1792 <div class="variant-preview position-relative d-flex" @PreviewCss></div> 1793 </div> 1794 } 1795 } 1796 </div> 1797 </div> 1798 } 1799 </div> 1800 } 1801 1802 <div class="col-12 d-flex justify-content-end"> 1803 <p class="color-primary pointer my-3" data-bind="click: ResetFilters">Nulstil</p> 1804 </div> 1805 </div> 1806 <p class="font-weight-bold fs2 mt-5"> 1807 @Translate( "ChooseProduct", "V&aelig;lg produkt" ) 1808 </p> 1809 <div class="row align-items-end" data-bind="foreach: FilteredVariants"> 1810 <div class="col-12 col-sm-6 col-md-3 mb-3"> 1811 <a class="color-black no-underline" data-bind="attr: { href: Link }"> 1812 <p class="fs0 font-weight-bold m-0" data-bind="text: Name"></p> 1813 <img class="img-fluid box-shadow my-1" data-bind="attr: { src: Image }" /> 1814 <div class="d-flex justify-content-center mt-2"> 1815 <div class="btn btn-primary">@Translate( "VariantChooseProduct", "V&aelig;lg" )</div> 1816 </div> 1817 </a> 1818 </div> 1819 </div> 1820 <div data-bind="visible: FilteredVariants().length == 0"> 1821 <p class="font-weight-bold mt-3 fs3">@Translate( "VariantsNoResults", "Filtreringen gav ingen resultater" )</p> 1822 </div> 1823 </div> 1824 </div> 1825 1826 <div class="add-to-cart-overlay" data-bind="css: { 'd-block': ProcessingAjax }"> 1827 <p class="fs4 m-0 color-white">@Translate("ProductAjaxAddingToCart", "Tilf&oslash;jer til kurv") <i class="fa fa-circle-notch fa-spin ml-3 fs5"></i></p> 1828 </div> 1829 1830 1831 <div class="add-to-cart-overlay" data-bind="css: { 'd-block': ProcessingVariantDetailsAjax }"> 1832 <p class="fs4 m-0 color-white">@Translate("ProductAjaxGettingVariant", "Henter variant") <i class="fa fa-circle-notch fa-spin ml-3 fs5"></i></p> 1833 </div> 1834 </div> 1835 1836 <div class="modal fade video-modal" id="videoModal" tabindex="-1" role="dialog" aria-labelledby="video-modal" aria-hidden="true"> 1837 <div class="modal-dialog modal-dialog-centered" role="document"> 1838 <div class="modal-content"> 1839 <div class="modal-body"> 1840 <div id="player"></div> 1841 </div> 1842 </div> 1843 </div> 1844 </div> 1845 1846 @SnippetStart("DataLayerOverwrites") 1847 <script> 1848 ecomm_pagetype = "Product"; 1849 ecomm_totalvalue = @GetString("Ecom:Product.Price.Price").Replace(".","").Replace(",","."); 1850 ecomm_prodid = "@GetString("Ecom:Product.ID")"; 1851 </script> 1852 @SnippetEnd("DataLayerOverwrites") 1853 1854 <script> 1855 var dataLayer = window.dataLayer || []; 1856 dataLayer.push({ 1857 'event': 'product', 1858 'ecommerce': { 1859 'detail': { 1860 'actionField': { 1861 'list': '@DataLayerParentGroups' 1862 }, 1863 'products': [{ 1864 'id': '@ProductID', 1865 'name': '@ProductName', 1866 'image': '@OgImage', 1867 'brand': '@BrandName', 1868 'variant': '@CurrentVariantName', 1869 'category': '@DataLayerParentGroup', 1870 'price': '@DataLayerPrice' 1871 }] 1872 } 1873 }, 1874 'page': { 1875 'type': 'product', 1876 'environment': 'production' 1877 } 1878 }); 1879 </script> 1880