Error executing template "Designs/Keflico/eCom/Product/Product.cshtml"
System.InvalidOperationException: Sequence contains no elements
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at CompiledRazorTemplates.Dynamic.RazorEngine_5903a55ba4c143e1ac88c4d8d7bada0b.Execute() in D:\dynamicweb.net\Solutions\keflico.live\Files\Templates\Designs\Keflico\eCom\Product\Product.cshtml:line 1103
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 System.Web.Helpers;
3 @using System.IO;
4
5 @using Dynamicweb.Rendering;
6 @using Dynamicweb.Ecommerce.ProductCatalog;
7 @using Dynamicweb.Ecommerce.Variants;
8 @using Dynamicweb.Core;
9
10 @{
11 System.Web.HttpCookie lastProductIdCookie = new System.Web.HttpCookie("LastProductIdCookie");
12 lastProductIdCookie.Value = GetString("Ecom:Product.ID");
13 lastProductIdCookie.Expires = DateTime.MinValue;
14 HttpContext.Current.Response.Cookies.Add(lastProductIdCookie);
15
16 var viewmodelSettings = new ProductViewModelSettings(Dynamicweb.Ecommerce.Common.Context.LanguageID, Dynamicweb.Ecommerce.Common.Context.Currency.Code, Dynamicweb.Ecommerce.Common.Context.Country.Code2, Pageview.Area.EcomShopId, Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUserId());
17 var productViewmodel = Dynamicweb.Ecommerce.ProductCatalog.ViewModelFactory.CreateView(viewmodelSettings, GetString("Ecom:Product.ID"), GetString("Ecom:Product.VariantId"), "");
18 var combination = new VariantCombination(GetString("Ecom:Product.ID"));
19 IList<VariantCombination> productVariants = new List<VariantCombination>();
20 var singleVariant = new VariantCombination();
21
22 if(combination != null && combination.Product != null) {
23 productVariants = combination.Product.VariantCombinations;
24 }
25
26 if(productVariants.Count == 1) {
27 singleVariant = productVariants.FirstOrDefault();
28 }
29
30 string CartPage = Pageview.Area.Item["CartPage"].ToString();
31 string cartCount = GetGlobalValue("Global:eCommerce.Order.OrderLines.TotalProductQuantity");
32
33 if(string.IsNullOrWhiteSpace(cartCount)) {
34 cartCount = "0";
35 }
36
37 string EcomPage = Pageview.Area.Item["EcomPage"].ToString();
38 string VariantsLookup = "/" + Pageview.Area.Item["Variantslookup"].ToString();
39 string BundleLookup = "/" + Pageview.Area.Item["Bundlelookup"].ToString();
40 string PriceLookup = "/" + Pageview.Area.Item["Pricelookup"].ToString();
41 string productNumber = GetString("Ecom:Product.Number");
42 string dbNumber = GetString("Ecom:Product:Field.ProductDbNumber.Value");
43 string productId = GetString("Ecom:Product.ID");
44 string productName = GetString("Ecom:Product.Name");
45 string primaryGroup = GetString("Ecom:Product.PrimaryGroupID").ToLower();
46 string formAction = "/" + CartPage;
47 string priceCurrencySymbol = GetString("Ecom:Product.Currency.Symbol");
48 string loopCounter = GetString("Ecom:Product.LoopCounter");
49 string inputName = "Quantity" + loopCounter;
50 var categories = GetLoop("AssociatedGroups");
51 var mainCategory = (LoopItem)null;
52 var productLayout = !string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductLayout")) ? GetString("Ecom:Product:Field.ProductLayout") : primaryGroup;
53
54 string labelCode = GetString("Ecom:Product:Field.ProductPurchaseCode");
55
56 var breadcrumbs = new List<LoopItem>();
57
58 foreach(var cat in categories) {
59 if(cat.GetString("Ecom:Group.ID").ToLower() == primaryGroup) {
60 mainCategory = cat;
61 }
62 }
63
64 if(mainCategory != null) {
65 breadcrumbs.Add(mainCategory);
66
67 foreach(var child in mainCategory.GetLoop("Childgroups")) {
68 foreach(var category in categories) {
69 if(category.GetString("Ecom:Group.ID").ToLower() == child.GetString("Ecom:Group.ID").ToLower()) {
70 breadcrumbs.Add(category);
71 }
72 }
73 }
74 }
75
76 bool enquireProduct = false;
77 bool isSunDryProduct = System.Convert.ToBoolean(GetString("Ecom:Product:Field.ProductSundryItem"));
78 bool isBundleOnly = System.Convert.ToBoolean(GetString("Ecom:Product:Field.BundleOnly"));
79
80 var totalStock = GetDouble("Ecom:Product.Stock");
81 totalStock += GetDouble("Ecom:Product:Field.StockSea.Value");
82
83 int totalStockWareHouse = GetInteger("Ecom:Product.Stock");
84 int totalStockSea = GetInteger("Ecom:Product:Field.StockSea.Value");
85
86 if(primaryGroup != "group32") {
87 totalStock += GetDouble("Ecom:Product:Field.ProductPieceOnPurchase.Value");
88 totalStockSea += int.Parse(GetString("Ecom:Product:Field.ProductPieceOnPurchase.Value").Replace(",", string.Empty));
89 }
90
91 bool isSingleVariant = GetInteger("Ecom:Product.VariantCount") == 1 ? true : false;
92
93 double singleVariantStock = 0;
94 int singleVariantStockSea = 0;
95
96 if(isSingleVariant) {
97 singleVariantStock = singleVariant.Product.UnitStock;
98 singleVariantStockSea = !String.IsNullOrWhiteSpace(singleVariant.Product.ProductFieldValues.GetProductFieldValue("ProductPieceOnPurchase").Value.ToString()) ? Convert.ToInt32(singleVariant.Product.ProductFieldValues.GetProductFieldValue("ProductPieceOnPurchase").Value.ToString().Replace(",", "")) : 0;
99
100 totalStock += singleVariantStock;
101 totalStock += singleVariantStockSea;
102 }
103
104 string halfParcelAmount = GetString("Ecom:Product:Field.ProductNumberPerHalfPackage.Value.Raw");
105 string completeParcelAmount = GetString("Ecom:Product:Field.ProductNumberPerPackage");
106
107 string standardPrice = GetString("Ecom:Product.Price.PriceWithoutVAT");
108 string standardPriceJS = !string.IsNullOrWhiteSpace(GetString("Ecom:Product.Discount.Price.PriceWithoutVAT.Value")) ? GetString("Ecom:Product.Discount.Price.PriceWithoutVAT.Value").Replace(",", ".") : "0";
109 string halfPrice = !string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductPriceHalfParcel")) ? GetString("Ecom:Product:Field.ProductPriceHalfParcel").Replace(".","-").Replace(",", ".").Replace("-", ",") : "0";
110 string fullPrice = !string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductPriceCompleteParcel")) ? GetString("Ecom:Product:Field.ProductPriceCompleteParcel").Replace(".","-").Replace(",", ".").Replace("-", ",") : "0";
111 string bundlePrice = GetString("Ecom:Product:Field.ProductPriceBundle.Value").Replace(",", "-").Replace(".", ",").Replace("-", ".");
112 string bundlePriceJS = !string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductPriceBundle.Value")) ? GetString("Ecom:Product:Field.ProductPriceBundle.Value").Replace(",", "") : "0";
113 string above100Price = !string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductPriceAbove100SQM")) ? GetString("Ecom:Product:Field.ProductPriceAbove100SQM") : "0";
114 string above100PriceJS = !string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductPriceAbove100SQM.Value.Raw")) ? GetString("Ecom:Product:Field.ProductPriceAbove100SQM.Value.Raw").Replace(",", ".") : "0";
115 string above3000Price = !string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductPriceAbove3000M.Value")) ? GetString("Ecom:Product:Field.ProductPriceAbove3000M.Value").Replace(".", ",") : "0";
116
117 string salesUnit = GetString("Ecom:Product.DefaultUnitName").ToLower();
118 string salesUnitCode = GetString("Ecom:Product:Field.ProductLengthUnitCode");
119
120 string configuratorUrl = GetString("Ecom:Product:Field.ProductConfiguratorUrl");
121
122 string fscLink = Pageview.Area.Item["FSC"].ToString();
123 string pefcLink = Pageview.Area.Item["PEFC"].ToString();
124 string ecoNordicLink = Pageview.Area.Item["EcoNordic"].ToString();
125 string cradleToCradleLink = Pageview.Area.Item["CradleToCradle"].ToString();
126
127 bool hasNewDownloads = false;
128 bool hasDownloads = false;
129
130 foreach(var fileCat in GetLoop("ImageCategories")) {
131
132 if(fileCat.GetString("Category.SystemName").StartsWith("docView_") && fileCat.GetLoop("Category.Images").Count() > 0) {
133 hasNewDownloads = true;
134 hasDownloads = false;
135 break;
136 }
137 else if(fileCat.GetString("Category.SystemName") != "Images" && fileCat.GetLoop("Category.Images").Count() > 0) {
138 hasDownloads = true;
139 }
140 }
141
142 bool isloggedin = false;
143
144 if (!string.IsNullOrWhiteSpace(GetGlobalValue("Global:Extranet.UserName").ToString())) {
145 isloggedin = true;
146 }
147
148 if(GetString("Ecom:Product:Field.EcomProduct").Contains("forespoerg")) {
149 enquireProduct = true;
150 }
151
152 if(isSunDryProduct) {
153 enquireProduct = true;
154 }
155
156 if(labelCode.ToLower() == "skaffe" || labelCode.ToLower() == "relatordre") {
157 enquireProduct = true;
158 }
159 }
160
161 @SnippetStart("PageTemplate")
162 product-page
163 @SnippetEnd("PageTemplate")
164
165 <article class="module module-sand product-details">
166 <div class="breadcrumbs">
167 <ul class="breadcrumbs__list">
168 <li class="breadcrumbs__item">
169 <a href="@EcomPage">@Translate("Translate_Breadcrumb_Products")</a>
170 </li>
171
172 @if(breadcrumbs.Count > 0) {
173 foreach(var group in breadcrumbs) {
174 <li class="breadcrumbs__item">
175 <a href="@group.GetString("Ecom:Group.Link.Clean")">@group.GetString("Ecom:Group.Name")</a>
176 </li>
177 }
178 }
179 <li class="breadcrumbs__item active">@productName</li>
180 </ul>
181 </div>
182 <div class="product-details__container">
183 @switch (labelCode.ToLower())
184 {
185 case "prøver":
186 <div class="product-details__label-code label-code label-code--samples">@Translate("LabelCode_" + labelCode.ToLower().Replace("ø", "oe"))</div>
187 break;
188 case "skaffe":
189 case "relatordre":
190 <div class="product-details__label-code label-code">@Translate("LabelCode_" + labelCode.ToLower())</div>
191 break;
192 default:
193 break;
194 }
195 <div class="product-details__media" data-igo-gallery>
196 @if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product.ImageDefault.Clean")))
197 {
198 <picture class="product-details__image-wrap" data-igo-image="@GetString("Ecom:Product.ImageDefault.Clean")">
199 <img src="@GetString("Ecom:Product.ImageDefault.Clean")" alt="@productName" loading="lazy">
200 </picture>
201 }
202 @foreach (var category in GetLoop("ImageCategories"))
203 {
204 if (category.GetString("Category.SystemName") == "Images")
205 {
206 foreach (var image in category.GetLoop("Category.Images"))
207 {
208 <picture class="product-details__image-wrap" data-igo-image="@image.GetString("Ecom:Product:Detail.Image.Clean")">
209 <img src="@image.GetString("Ecom:Product:Detail.Image.Clean")" alt="@productName" loading="lazy">
210 </picture>
211 }
212 }
213 }
214 <div class="product-details__media-steps">
215 <span class="disclaimer">* @Translate("Translate_Product_Page_ImageDisclaimer")</span>
216 <span class="current">1/1</span>
217 </div>
218 </div>
219 <div class="product-details__info">
220 <div class="product-details__info-labels">
221 @if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductCertification")) && GetString("Ecom:Product:Field.ProductCertification") != "-1")
222 {
223 string certification = GetString("Ecom:Product:Field.ProductCertification").ToLower();
224 if (certification.Contains("pefc"))
225 {
226 <a href="@pefcLink" target="_blank">
227 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/pefc-logo.svg")))
228 {
229 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/pefc-logo.svg"))
230 }
231 </a>
232 }
233 else if (certification.Contains("fsc"))
234 {
235 <a href="@fscLink" target="_blank">
236 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/fsc-logo.svg")))
237 {
238 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/fsc-logo.svg"))
239 }
240 </a>
241 }
242 }
243 @if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductNordicEcoLabel")) && GetString("Ecom:Product:Field.ProductNordicEcoLabel") != "-1")
244 {
245 <a href="@ecoNordicLink" target="_blank">
246 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/svanemaerket-logo.svg")))
247 {
248 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/svanemaerket-logo.svg"))
249 }
250 </a>
251 }
252 @if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductCradleToCradle.Value")) && GetString("Ecom:Product:Field.ProductCradleToCradle.Value") != "-1" && GetString("Ecom:Product:Field.ProductCradleToCradle.Value") != "N/A")
253 {
254 <a href="@cradleToCradleLink" target="_blank">
255 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/cradle-logo.svg")))
256 {
257 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/cradle-logo.svg"))
258 }
259 </a>
260 }
261 </div>
262 <div class="product-details__info-meta">
263 <ul class="product-details__info-meta-list">
264 <li id="productNumber">@Translate("Translate_Product_Page_ProductNumber"): @productNumber</li>
265 @if (!string.IsNullOrWhiteSpace(dbNumber))
266 {
267 <li>@GetString("Ecom:Product:Field.ProductDbNumber.Name"): @dbNumber</li>
268 }
269 </ul>
270 </div>
271 <h1 id="productName" class="product-details__info-title">@productName</h1>
272 <div class="product-details__info-size">@GetString("Ecom:Product:Field.Name2")</div>
273
274 @switch (productLayout)
275 {
276 case "group1": // Hårdtræ
277 if (isloggedin)
278 {
279 if ((standardPriceJS != "0" && !isBundleOnly) || bundlePriceJS != "0")
280 {
281 <div class="product-details__info-price-container">
282 <div class="product-details__info-price-heading">
283 @Translate("Translate_ProductPage_PriceDefinition_HardWood")
284 <span class="tooltip">
285 <span class="tooltip__icon">
286 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
287 {
288 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
289 }
290 </span>
291 <span class="tooltip__text tooltip__text--top">
292 @Translate("Translate_ProductPage_PriceDefinition_HardWood_Tooltip")
293 </span>
294 </span>
295 </div>
296 @if (standardPriceJS != "0" && !isBundleOnly)
297 {
298 <div class="product-details__info-price-option">
299 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_Breakup")</div>
300 <div class="product-details__info-price-option-price">@standardPrice @priceCurrencySymbol pr. @salesUnit</div>
301 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
302 </div>
303 }
304 @if (bundlePriceJS != "0")
305 {
306 if (bundlePrice.Contains(","))
307 {
308 string[] sp = bundlePrice.Split(',');
309
310 if (sp[1].Length == 1)
311 {
312 bundlePrice += "0";
313 }
314 }
315 else
316 {
317 bundlePrice += ",00";
318 }
319
320 <div class="product-details__info-price-option">
321 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_Bundle")</div>
322 <div class="product-details__info-price-option-price">@bundlePrice @priceCurrencySymbol pr. @salesUnit</div>
323 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
324 </div>
325 }
326 </div>
327 }
328 }
329
330 if (standardPriceJS == "0" && bundlePriceJS == "0")
331 {
332 enquireProduct = true;
333 }
334
335 <div id="product-order-button" style="min-height: 64px;">
336 @if (enquireProduct)
337 {
338 <a data-action="open-content" data-target="#enquireForm" class="product-details__info-button btn btn--block btn-secondary product-order-form-button">@Translate("Translate_Product_Page_EnquireButton")</a>
339 }
340 else
341 {
342 <div style="display: none;" class="loader"></div>
343 <a style="display: none;" href="#" class="product-details__info-button btn btn--block btn-secondary product-order-button">@Translate("Translate_Product_Page_OrderButton")</a>
344 <a style="display: none;" data-action="open-content" data-target="#enquireForm" class="product-details__info-button btn btn--block btn-secondary product-order-form-button">@Translate("Translate_Product_Page_EnquireButton")</a>
345 }
346 </div>
347
348 break;
349
350 case "group32": // Terrasse
351
352 if (isloggedin)
353 {
354 if (standardPriceJS != "0" || above100PriceJS != "0")
355 {
356 <div class="product-details__info-price-container">
357 <div class="product-details__info-price-heading">
358 @Translate("Translate_ProductPage_PriceDefinition_Terrasse")
359
360 @if (primaryGroup == "group32")
361 {
362 <span class="tooltip">
363 <span class="tooltip__icon">
364 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
365 {
366 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
367 }
368 </span>
369 <span class="tooltip__text tooltip__text--top">
370 @Translate("Translate_ProductPage_PriceDefinition_Terrasse_Tooltip")
371 </span>
372 </span>
373 }
374 else
375 {
376 <span class="tooltip">
377 <span class="tooltip__icon">
378 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
379 {
380 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
381 }
382 </span>
383 <span class="tooltip__text tooltip__text--top">
384 @Translate("Translate_ProductPage_PriceDefinition_Facade_Tooltip")
385 </span>
386 </span>
387 }
388 </div>
389
390 @if (standardPriceJS != "0")
391 {
392 <div class="product-details__info-price-option">
393 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_Under100")</div>
394 <div class="product-details__info-price-option-price">@standardPrice @priceCurrencySymbol pr. @salesUnit</div>
395 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
396 </div>
397 }
398
399 @if (above100PriceJS != "0")
400 {
401 if (above100Price.Contains(","))
402 {
403 string[] sp = above100Price.Split(',');
404
405 if (sp[1].Length == 1)
406 {
407 above100Price += "0";
408 }
409 }
410 else
411 {
412 above100Price += ",00";
413 }
414
415 <div class="product-details__info-price-option">
416 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_Above100")</div>
417 <div class="product-details__info-price-option-price">@above100Price @priceCurrencySymbol pr. @salesUnit</div>
418 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
419 </div>
420 }
421 </div>
422 }
423 }
424
425 if (standardPriceJS == "0" && above100PriceJS == "0")
426 {
427 enquireProduct = true;
428 }
429
430 <div id="product-order-button" style="min-height: 64px;">
431 @if (enquireProduct)
432 {
433 <a data-action="open-content" data-target="#enquireForm" class="product-details__info-button btn btn--block btn-secondary product-order-form-button">@Translate("Translate_Product_Page_EnquireButton")</a>
434 }
435 else
436 {
437 <div style="display: none;" class="loader"></div>
438 <a style="display: none;" href="#" class="product-details__info-button btn btn--block btn-secondary product-order-button">@Translate("Translate_Product_Page_OrderButton")</a>
439 <a style="display: none;" data-action="open-content" data-target="#enquireForm" class="product-details__info-button btn btn--block btn-secondary product-order-form-button">@Translate("Translate_Product_Page_EnquireButton")</a>
440 }
441 </div>
442
443 break;
444
445 case "group73": // Facadebeklædning
446 if (isloggedin)
447 {
448 if (standardPriceJS != "0" || above100PriceJS != "0" || above3000Price != "0")
449 {
450 <div class="product-details__info-price-container">
451 <div class="product-details__info-price-heading">
452 @Translate("Translate_ProductPage_PriceDefinition_Terrasse")
453
454 @if (primaryGroup == "group32")
455 {
456 <span class="tooltip">
457 <span class="tooltip__icon">
458 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
459 {
460 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
461 }
462 </span>
463 <span class="tooltip__text tooltip__text--top">
464 @Translate("Translate_ProductPage_PriceDefinition_Terrasse_Tooltip")
465 </span>
466 </span>
467 }
468 else
469 {
470 <span class="tooltip">
471 <span class="tooltip__icon">
472 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
473 {
474 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
475 }
476 </span>
477 <span class="tooltip__text tooltip__text--top">
478 @Translate("Translate_ProductPage_PriceDefinition_Facade_Tooltip")
479 </span>
480 </span>
481 }
482 </div>
483
484 @if (standardPriceJS != "0")
485 {
486 <div class="product-details__info-price-option">
487 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_Under1000")</div>
488 <div class="product-details__info-price-option-price">@standardPrice @priceCurrencySymbol pr. @salesUnit</div>
489 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
490 </div>
491 }
492
493 @if (above100PriceJS != "0")
494 {
495 if (above100Price.Contains(","))
496 {
497 string[] sp = above100Price.Split(',');
498
499 if (sp[1].Length == 1)
500 {
501 above100Price += "0";
502 }
503 }
504 else
505 {
506 above100Price += ",00";
507 }
508
509 <div class="product-details__info-price-option">
510 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_Between1000and3000")</div>
511 <div class="product-details__info-price-option-price">@above100Price @priceCurrencySymbol pr. @salesUnit</div>
512 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
513 </div>
514 }
515
516 @if (above3000Price != "0")
517 {
518 if (above3000Price.Contains(","))
519 {
520 string[] tp = above3000Price.Split(',');
521
522 if (tp[1].Length == 1)
523 {
524 above3000Price += "0";
525 }
526 }
527 else
528 {
529 above3000Price += ",00";
530 }
531
532 <div class="product-details__info-price-option">
533 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_Above3000")</div>
534 <div class="product-details__info-price-option-price">@above3000Price @priceCurrencySymbol pr. @salesUnit</div>
535 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
536 </div>
537 }
538 </div>
539 }
540 }
541
542 if (standardPriceJS == "0" && above100PriceJS == "0" && above3000Price == "0")
543 {
544 enquireProduct = true;
545 }
546
547 <div id="product-order-button" style="min-height: 64px;">
548 @if (enquireProduct)
549 {
550 <a data-action="open-content" data-target="#enquireForm" class="product-details__info-button btn btn--block btn-secondary product-order-form-button">@Translate("Translate_Product_Page_EnquireButton")</a>
551 }
552 else
553 {
554 <div style="display: none;" class="loader"></div>
555 <a style="display: none;" href="#" class="product-details__info-button btn btn--block btn-secondary product-order-button">@Translate("Translate_Product_Page_OrderButton")</a>
556 <a style="display: none;" data-action="open-content" data-target="#enquireForm" class="product-details__info-button btn btn--block btn-secondary product-order-form-button">@Translate("Translate_Product_Page_EnquireButton")</a>
557 }
558 </div>
559
560 break;
561
562 case "group52": // Plader
563 case "group66": // Dekorative Overflader
564
565 if (isloggedin)
566 {
567 if (standardPriceJS != "0" || halfPrice != "0" || fullPrice != "0")
568 {
569 <div class="product-details__info-price-container">
570 <div class="product-details__info-price-heading">
571 @Translate("Translate_ProductPage_PriceDefinition_Plader")
572 @if (primaryGroup == "group52")
573 {
574 <span class="tooltip">
575 <span class="tooltip__icon">
576 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
577 {
578 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
579 }
580 </span>
581 <span class="tooltip__text tooltip__text--top">
582 @Translate("Translate_ProductPage_PriceDefinition_Plader_Tooltip")
583 </span>
584 </span>
585 }
586 else
587 {
588 <span class="tooltip">
589 <span class="tooltip__icon">
590 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
591 {
592 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
593 }
594 </span>
595 <span class="tooltip__text tooltip__text--top">
596 @Translate("Translate_ProductPage_PriceDefinition_Overflader_Tooltip")
597 </span>
598 </span>
599 }
600 </div>
601
602 @if (standardPriceJS != "0")
603 {
604 <div class="product-details__info-price-option">
605 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_PriceUnit_Anbrud")</div>
606 <div class="product-details__info-price-option-price">@standardPrice @priceCurrencySymbol pr. @salesUnit</div>
607 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
608 </div>
609 }
610
611 @if (halfPrice != "0")
612 {
613 if (halfPrice.Contains(","))
614 {
615 string[] sp = halfPrice.Split(',');
616
617 if (sp[1].Length == 1)
618 {
619 halfPrice += "0";
620 }
621 }
622 else
623 {
624 halfPrice += ",00";
625 }
626
627 <div class="product-details__info-price-option">
628 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_PriceUnit_HalfParcel") (@halfParcelAmount @Translate("Translate_Ecom_Piece"))</div>
629 <div class="product-details__info-price-option-price">@halfPrice @priceCurrencySymbol pr. @salesUnit</div>
630 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
631 </div>
632 }
633
634 @if (fullPrice != "0")
635 {
636 if (fullPrice.Contains(","))
637 {
638 string[] sp = fullPrice.Split(',');
639
640 if (sp[1].Length == 1)
641 {
642 fullPrice += "0";
643 }
644 }
645 else
646 {
647 fullPrice += ",00";
648 }
649
650 <div class="product-details__info-price-option">
651 <div class="product-details__info-price-option-title">@Translate("Translate_ProductPage_PriceUnit_CompleteParcel") (@completeParcelAmount @Translate("Translate_Ecom_Piece"))</div>
652 <div class="product-details__info-price-option-price">@fullPrice @priceCurrencySymbol pr. @salesUnit</div>
653 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
654 </div>
655 }
656 </div>
657 }
658 }
659
660 <div class="product-details__info-quantity">
661 @{
662 if (standardPriceJS == "0" && halfPrice == "0" && fullPrice == "0")
663 {
664 enquireProduct = true;
665 }
666 }
667 @if (totalStock > 0 && isloggedin && !enquireProduct)
668 {
669 <form class="form" action="@(formAction)&Redirect=@(CartPage)" method="post" name="@productId" id="@productId">
670 <input type="hidden" name="CartCmd" value="addMulti" />
671
672 @if (isSingleVariant)
673 {
674 <input type="hidden" name="ProductLoopCounter@(loopCounter)" id="ProductLoopCounter@(loopCounter)" value="@loopCounter">
675 <input type="hidden" name="ProductID@(loopCounter)" id="ProductID@(loopCounter)" value="@productId">
676 <input type="hidden" name="VariantID@(loopCounter)" id="VariantID@(loopCounter)" value="@singleVariant.VariantId">
677 }
678 else
679 {
680 @GetString("Ecom:Product.Form.Multi.HiddenFields")
681 }
682
683 <div class="counter">
684 <a class="substract">-</a>
685 <input name="@inputName" id="Quantity" class="amount" type="tel" value="1">
686 <label for="Quanity" class="unit">@Translate("Translate_Piece_Short")</label>
687 <a class="add">+</a>
688 </div>
689 <button type="submit" id="product-order-button" class="product-details__info-button btn btn--block btn-secondary">Bestil</button>
690 </form>
691 }
692 else
693 {
694 <a href="#product-inquire-form" id="product-order-button" data-action="open-content" data-target="#enquireForm" class="product-details__info-button btn btn--block btn-secondary">@Translate("Translate_Product_Page_EnquireButton")</a>
695 }
696 </div>
697
698 break;
699
700 case "group126": // Tilbehør
701
702 if (isloggedin)
703 {
704 if (standardPriceJS != "0")
705 {
706 <div class="product-details__info-price-container">
707 <div class="product-details__info-price-heading">
708 @Translate("Translate_ProductPage_PriceDefinition_Andet")
709 <span class="tooltip">
710 <span class="tooltip__icon">
711 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
712 {
713 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
714 }
715 </span>
716 <span class="tooltip__text tooltip__text--top">
717 @Translate("Translate_ProductPage_PriceDefinition_Andet_Tooltip")
718 </span>
719 </span>
720 </div>
721 <div class="product-details__info-price-option">
722 <div class="product-details__info-price-option-price">@standardPrice @priceCurrencySymbol pr. @salesUnit</div>
723 <div class="product-details__info-price-option-vat">@Translate("Translate_Ecom_ExVat")</div>
724 </div>
725 </div>
726 }
727 }
728
729 <div class="product-details__info-quantity">
730 @{
731 if (standardPriceJS == "0")
732 {
733 enquireProduct = true;
734 }
735 }
736 @if (totalStock > 0 && isloggedin && !enquireProduct)
737 {
738 <form class="form" action="@(formAction)&Redirect=@(CartPage)" method="post" name="@productId" id="@productId">
739 <input type="hidden" name="CartCmd" value="addMulti" />
740 @GetString("Ecom:Product.Form.Multi.HiddenFields")
741 <div class="counter">
742 <a class="substract">-</a>
743 <input name="@inputName" id="Quantity" class="amount" type="tel" value="1">
744 <label for="Quanity" class="unit">@Translate("Translate_Piece_Short")</label>
745 <a class="add">+</a>
746 </div>
747 <button type="submit" id="product-order-button" class="product-details__info-button btn btn--block btn-secondary">Bestil</button>
748 </form>
749 }
750 else
751 {
752 <a href="#product-inquire-form" id="product-order-button" data-action="open-content" data-target="#enquireForm" class="product-details__info-button btn btn--block btn-secondary">@Translate("Translate_Product_Page_EnquireButton")</a>
753 }
754 </div>
755 break;
756
757 default:
758
759 <h1>Produkt mangler at få valgt primær gruppe</h1>
760 break;
761 }
762
763 <div class="product-details__info-more">
764 @switch (productLayout)
765 {
766 case "group52": // Plader
767 case "group66": // Dekorative Overflader
768 case "group126": // Tilbehør
769 var warehouseStock = GetDouble("Ecom:Product.Stock");
770 var seaStock = int.Parse(GetString("Ecom:Product:Field.ProductPieceOnPurchase.Value").Replace(",", string.Empty));
771
772 if (isSingleVariant)
773 {
774 warehouseStock = singleVariantStock;
775 seaStock = totalStockSea;
776 }
777
778 string displayWarehouseStock = warehouseStock.ToString("N0");
779 string displaySeaStock = seaStock.ToString("N0");
780
781 if (isloggedin)
782 {
783 if (warehouseStock > 500)
784 {
785 displayWarehouseStock = "+500";
786 }
787
788 if (seaStock > 500)
789 {
790 displaySeaStock = "+500";
791 }
792 }
793 else
794 {
795 if (warehouseStock > 100)
796 {
797 displayWarehouseStock = "+100";
798 }
799
800 if (seaStock > 100)
801 {
802 displaySeaStock = "+100";
803 }
804 }
805
806 if(labelCode.ToLower() != "skaffe" && labelCode.ToLower() != "relatordre") {
807 <div class="product-details__info-stock product-details__info-stock--inline">
808 <div class="option option--in-house">
809 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 23.818">
810 <g class="warehouse" transform="translate(-551.005 -159.082)">
811 <path class="box box--top" d="M563.005,177.15h-5.25a.75.75,0,0,0-.75.75v4.5a.75.75,0,0,0,.75.75h4.5a.75.75,0,0,0,.75-.75Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
812 <path class="box box--bottom-right" d="M568.255,177.15h-5.25v5.25a.75.75,0,0,0,.75.75h4.5a.75.75,0,0,0,.75-.75v-4.5A.75.75,0,0,0,568.255,177.15Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
813 <path class="box box--bottom-left" d="M565.255,171.15h-4.5a.75.75,0,0,0-.75.75v5.25h6V171.9A.75.75,0,0,0,565.255,171.15Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
814 <path class="building" d="M574.255,183.15v-15.6a1.5,1.5,0,0,0-.794-1.324l-9.75-5.2a1.5,1.5,0,0,0-1.411,0l-9.75,5.2a1.5,1.5,0,0,0-.795,1.324v15.6" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
815 </g>
816 </svg>
817 <span>@Translate("Translate_ProductPage_StockOnWarehouse")</span> @displayWarehouseStock @Translate("Translate_Ecom_Piece")
818 </div>
819 <div class="option option--in-route">
820 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 16.5">
821 <g class="truck" transform="translate(-215 -899.75)">
822 <path class="back" d="M238.25,909.5V902a1.5,1.5,0,0,0-1.5-1.5h-12a1.5,1.5,0,0,0-1.5,1.5v6" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
823 <path class="front" d="M223.25,908v-6h-3a4.5,4.5,0,0,0-4.5,4.5v6a1.5,1.5,0,0,0,1.5,1.5H218" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
824 <path class="window" d="M215.75,908h3a1.5,1.5,0,0,0,1.5-1.5V902" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
825 <path class="wheel wheel--front" d="M222.5,915.5a2.25,2.25,0,1,0-2.25-2.25A2.25,2.25,0,0,0,222.5,915.5Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
826 <path class="wheel wheel--back" d="M234.5,915.5a2.25,2.25,0,1,0-2.25-2.25A2.25,2.25,0,0,0,234.5,915.5Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
827 <path class="axis" d="M227,914h3" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
828 </g>
829 </svg>
830 <span>@Translate("Translate_ProductPage_StockOnSea")</span> @displaySeaStock @Translate("Translate_Ecom_Piece")
831 </div>
832 </div>
833 }
834
835 break;
836
837 default:
838 if(labelCode.ToLower() != "skaffe" && labelCode.ToLower() != "relatordre") {
839 <a href="#" class="product-details__info-stock product-order-button">
840 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 23.818">
841 <g class="warehouse" transform="translate(-551.005 -159.082)">
842 <path class="box box--top" d="M563.005,177.15h-5.25a.75.75,0,0,0-.75.75v4.5a.75.75,0,0,0,.75.75h4.5a.75.75,0,0,0,.75-.75Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
843 <path class="box box--bottom-right" d="M568.255,177.15h-5.25v5.25a.75.75,0,0,0,.75.75h4.5a.75.75,0,0,0,.75-.75v-4.5A.75.75,0,0,0,568.255,177.15Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
844 <path class="box box--bottom-left" d="M565.255,171.15h-4.5a.75.75,0,0,0-.75.75v5.25h6V171.9A.75.75,0,0,0,565.255,171.15Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
845 <path class="building" d="M574.255,183.15v-15.6a1.5,1.5,0,0,0-.794-1.324l-9.75-5.2a1.5,1.5,0,0,0-1.411,0l-9.75,5.2a1.5,1.5,0,0,0-.795,1.324v15.6" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
846 </g>
847 </svg>
848
849 @Translate("Translate_Product_Page_StockStatus")
850
851 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.006 11.031">
852 <g class="arrow" transform="translate(441 901.014) rotate(180)">
853 <path class="angle" d="M-17182.074-20447.988l4.809-4.809,4.809,4.809" transform="translate(20875.289 -16281.768) rotate(-90)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" />
854 <line class="line" x2="17" transform="translate(423.5 895.5)" stroke-linecap="round" stroke-width="1" />
855 </g>
856 </svg>
857 </a>
858 }
859 break;
860 }
861
862 <div class="product-details__info-delivery">
863 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 16.5">
864 <g class="truck" transform="translate(-215 -899.75)">
865 <path class="back" d="M238.25,909.5V902a1.5,1.5,0,0,0-1.5-1.5h-12a1.5,1.5,0,0,0-1.5,1.5v6" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
866 <path class="front" d="M223.25,908v-6h-3a4.5,4.5,0,0,0-4.5,4.5v6a1.5,1.5,0,0,0,1.5,1.5H218" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
867 <path class="window" d="M215.75,908h3a1.5,1.5,0,0,0,1.5-1.5V902" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
868 <path class="wheel wheel--front" d="M222.5,915.5a2.25,2.25,0,1,0-2.25-2.25A2.25,2.25,0,0,0,222.5,915.5Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
869 <path class="wheel wheel--back" d="M234.5,915.5a2.25,2.25,0,1,0-2.25-2.25A2.25,2.25,0,0,0,234.5,915.5Z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
870 <path class="axis" d="M227,914h3" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" />
871 </g>
872 </svg>
873
874 @if(labelCode.ToLower() == "skaffe" || labelCode.ToLower() == "relatordre") {
875 @Translate("Translate_Product_Page_DeliveryInformation")<text> </text> @GetString("Ecom:Product:Field.Leveringstid")
876 } else {
877 @Translate("Translate_Product_Page_DeliveryInformation")
878 }
879
880 <span class="tooltip">
881 <span class="tooltip__icon">
882 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
883 {
884 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
885 }
886 </span>
887 <span class="tooltip__text tooltip__text--left">
888 @if(labelCode.ToLower() == "skaffe" || labelCode.ToLower() == "relatordre") {
889 <p>@Translate("Translate_ProductPage_DeliverInfo_Skaffe")</p>
890 } else {
891 <p>@Translate("Translate_ProductPage_DeliveryInfo")</p>
892 }
893 </span>
894 </span>
895 </div>
896
897
898 <a class="product-details__info-reseller" href="https://keflico.com/find-forhandler">
899 <svg width="800px" height="800px" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" stroke-width="3" stroke="#000000" fill="none">
900 <path d="M52,27.18V52.76a2.92,2.92,0,0,1-3,2.84H15a2.92,2.92,0,0,1-3-2.84V27.17"></path>
901 <polyline points="26.26 55.52 26.26 38.45 37.84 38.45 37.84 55.52"></polyline>
902 <path d="M8.44,19.18s-1.1,7.76,6.45,8.94a7.17,7.17,0,0,0,6.1-2A7.43,7.43,0,0,0,32,26a7.4,7.4,0,0,0,5,2.49,11.82,11.82,0,0,0,5.9-2.15,6.66,6.66,0,0,0,4.67,2.15,8,8,0,0,0,7.93-9.3L50.78,9.05a1,1,0,0,0-.94-.65H14a1,1,0,0,0-.94.66Z"></path>
903 <line x1="8.44" y1="19.18" x2="55.54" y2="19.18"></line>
904 <line x1="21.04" y1="19.18" x2="21.04" y2="8.4"></line>
905 <line x1="32.05" y1="19.18" x2="32.05" y2="8.4"></line>
906 <line x1="43.01" y1="19.18" x2="43.01" y2="8.4"></line>
907 </svg>
908
909 @Translate("Translate_Product_Page_Reseller")
910
911 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.006 11.031">
912 <g class="arrow" transform="translate(441 901.014) rotate(180)">
913 <path class="angle" d="M-17182.074-20447.988l4.809-4.809,4.809,4.809" transform="translate(20875.289 -16281.768) rotate(-90)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" />
914 <line class="line" x2="17" transform="translate(423.5 895.5)" stroke-linecap="round" stroke-width="1" />
915 </g>
916 </svg>
917 </a>
918
919 @if (!string.IsNullOrEmpty(configuratorUrl))
920 {
921 <a class="product-details__info-configurator" href="@configuratorUrl">
922 <svg width="800px" height="800px" viewBox="0 0 32 32" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg820" version="1.1">
923 <defs id="defs814">
924 <linearGradient gradientTransform="matrix(1.25 0 0 1.2 -484.714 468.561)" gradientUnits="userSpaceOnUse" y2="520.79797" x2="401.57144" y1="535.79797" x1="401.57144" id="linearGradient4358" xlink:href="#linearGradient4424"></linearGradient>
925 <linearGradient id="linearGradient4424">
926 <stop style="stop-color:#60a5e7;stop-opacity:0" offset="0" id="stop4426"></stop>
927 <stop style="stop-color:#a6f3fb;stop-opacity:.25773194" offset="1" id="stop4428"></stop>
928 </linearGradient>
929 </defs>
930 <g transform="translate(0 -1090.52)" id="layer1">
931 <path id="rect2370" transform="translate(0 1090.52)" d="M2 4v24h28V4zm2 2h24v20H4z" style="opacity:1;vector-effect:none;fill:#373737;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:3.20000005;stroke-opacity:1"></path>
932 <path id="path2381" d="M22.424 1100.096a1.996 1.996 0 0 0-2.829 0l-.707.707-7.778 7.778 2.828 2.829 7.779-7.778.707-.708a1.996 1.996 0 0 0 0-2.828zm-12.021 9.192-1.414 4.243 4.242-1.414z" style="fill:#373737;fill-opacity:1;stroke:none;stroke-width:1.26491106px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"></path>
933 </g>
934 </svg>
935
936 @Translate("Translate_Product_Page_Configurator")
937
938 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.006 11.031">
939 <g class="arrow" transform="translate(441 901.014) rotate(180)">
940 <path class="angle" d="M-17182.074-20447.988l4.809-4.809,4.809,4.809" transform="translate(20875.289 -16281.768) rotate(-90)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" />
941 <line class="line" x2="17" transform="translate(423.5 895.5)" stroke-linecap="round" stroke-width="1" />
942 </g>
943 </svg>
944 </a>
945 }
946 <button id="downloadPdfButton" class="product-details__info-download-pdf">
947 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
948 <g class="download-icon" transform="translate(2 2)">
949 <path class="arrow" d="M10 0 L10 16 M5 11 L10 16 L15 11"
950 fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
951 <path class="line" d="M0 20 L20 20"
952 fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
953 </g>
954 </svg>
955 Download PDF
956 </button>
957 </div>
958 </div>
959
960 <script>
961 document.addEventListener('DOMContentLoaded', function() {
962 var downloadButton = document.getElementById('downloadPdfButton');
963 if (downloadButton) {
964 downloadButton.addEventListener('click', function(e) {
965 e.preventDefault(); // Prevent the default action
966
967 // Get the product number and name
968 var productNumber = '@productId';
969 var productName = '@productName';
970
971 // Function to replace Danish characters
972 function replaceDanishChars(str) {
973 return str
974 .replace(/æ/g, 'ae')
975 .replace(/ø/g, 'oe')
976 .replace(/å/g, 'aa')
977 .replace(/Æ/g, 'Ae')
978 .replace(/Ø/g, 'Oe')
979 .replace(/Å/g, 'Aa');
980 }
981
982 // Clean up the product name for use in a filename
983 var cleanProductName = replaceDanishChars(productName)
984 .replace(/[^\w\s-]/g, '') // Remove special characters
985 .trim() // Remove leading and trailing spaces
986 .replace(/\s+/g, '-') // Replace spaces with hyphens
987 .toLowerCase(); // Convert to lowercase
988
989 // Capitalize the first letter of cleanProductName
990 cleanProductName = cleanProductName.charAt(0).toUpperCase() + cleanProductName.slice(1);
991
992 // Construct the filename with _Keflico at the end
993 var filename = `${productNumber}_${cleanProductName}_Keflico.pdf`;
994
995 // Encode the filename for use in a URL
996 var encodedFilename = encodeURIComponent(filename);
997
998 // Navigate to the new URL to trigger the PDF download
999 window.location.href = `/Default.aspx?ID=1243&ProductID=${productNumber}&PDF=True&filename=${encodedFilename}&topBottomMargin=10`;
1000 });
1001 }
1002 });
1003 </script>
1004 </article>
1005 <article class="module module-sand product-description">
1006 <div class="tabs">
1007 <div class="tabs__nav">
1008 <ul role="tablist" class="tabs__list" data-action="tabs">
1009 <li role="none" class="tabs__item">
1010 <a href="#description" class="tab tab--active" role="tab" id="description-tab" aria-controls="description" aria-selected="true">
1011 <span class="tabs__item__text--web">@Translate("Translate_Product_Page_ProductDescription")</span>
1012 <span class="tabs__item__text--mobile">@Translate("Translate_Product_Page_ProductDescription_Short")</span>
1013 </a>
1014 </li>
1015 <li role="none" class="tabs__item">
1016 <a href="#technical" class="tab" role="tab" id="technical-tab" aria-controls="technical" aria-selected="false">
1017 <span class="tabs__item__text--web">@Translate("Translate_Product_Page_TechnicalSpecifications")</span>
1018 <span class="tabs__item__text--mobile">@Translate("Translate_Product_Page_TechnicalSpecifications_Short")</span>
1019 </a>
1020 </li>
1021 @if (hasNewDownloads)
1022 {
1023 <li role="none" class="tabs__item">
1024 <a href="#documents" class="tab" role="tab" id="documents-tab" aria-controls="documents" aria-selected="false">
1025 <span class="tabs__item__text--web">@Translate("Translate_Product_Page_Documents")</span>
1026 <span class="tabs__item__text--mobile">@Translate("Translate_Product_Page_Documents_Short")</span>
1027 </a>
1028 </li>
1029 }
1030 <li role="none" class="tabs__item">
1031 <a href="#more-info" class="tab" role="tab" id="more-info-tab" aria-controls="more-info" aria-selected="false">
1032 <span class="tabs__item__text--web">@Translate("Translate_Product_Page_MoreInformation")</span>
1033 <span class="tabs__item__text--mobile">@Translate("Translate_Product_Page_MoreInformation_Short")</span>
1034 </a>
1035 </li>
1036 </ul>
1037
1038 </div>
1039 <div id="description" class="tab__content tab__content--active" role="tabpanel" aria-hidden="false" aria-labelledby="description-tab">
1040 <h2>@Translate("Translate_Product_Page_ProductDescription")</h2>
1041 <div class="tab__content-wrapper">
1042 <div class="rich-text">
1043 <div class="large-text">@GetString("Ecom:Product.LongDescription")</div>
1044 @GetString("Ecom:Product:Field.ProductDescriptionShortLongText.Value")
1045 </div>
1046
1047 @if (hasDownloads)
1048 {
1049 <div class="tab__content-sidebar">
1050 <strong>@Translate("Translate__Product_Page_Downloads")</strong>
1051 <ul class="tab__content-list">
1052 @foreach (var fileCat in GetLoop("ImageCategories"))
1053 {
1054 if (fileCat.GetString("Category.SystemName") != "Images")
1055 {
1056 foreach (var file in fileCat.GetLoop("Category.Images"))
1057 {
1058 string fileLink = file.GetString("Ecom:Product:Detail.Image.Clean");
1059 string fileName = file.GetString("Ecom:Product:Detail.Name");
1060
1061 if (String.IsNullOrWhiteSpace(fileName))
1062 {
1063 fileName = Path.GetFileNameWithoutExtension(fileLink);
1064 }
1065
1066 <li>
1067 <a class="swap-link" href="@fileLink" data-link="@fileLink" target="_blank">
1068 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/file.svg")))
1069 {
1070 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/file.svg"))
1071 }
1072 @fileName.Replace("-", " ").Replace("_", " ")
1073 </a>
1074 </li>
1075 }
1076 }
1077 }
1078
1079 </ul>
1080 </div>
1081 }
1082 </div>
1083 </div>
1084 <div id="technical" class="tab__content technical-specs" role="tabpanel" aria-hidden="false" aria-labelledby="technical-tab">
1085 <div class="rich-text">
1086 <h2>@Translate("Translate_Product_Page_TechnicalSpecifications")</h2>
1087
1088 @{
1089 CategoryFieldViewModel specs = productViewmodel.FieldDisplayGroups.Values.Where(x => x.Id.ToLower() == "technicalspecifications").FirstOrDefault();
1090 CategoryFieldViewModel specsWithInfo = productViewmodel.FieldDisplayGroups.Values.Where(x => x.Id.ToLower() == "technicalspecificationswithinfo").FirstOrDefault();
1091 }
1092
1093 @if (specs != null)
1094 {
1095 <ul class="product-description__technical-list">
1096 @foreach (var field in specs.Fields.Values)
1097 {
1098 if (field.Type.ToLower() == "list")
1099 {
1100 List<FieldOptionValueViewModel> fieldValue = (List<FieldOptionValueViewModel>)field.Value;
1101 int i = 0;
1102
1103 if (fieldValue.First().Value.ToString() != "-1" && fieldValue.Where(x => x.Name.ToLower() == "ingen").Count() == 0)
1104 {
1105 <li class="product-description__technical-list-item">
1106 <div class="key">@field.Name</div>
1107 <div class="value">
1108 <span class="line">
1109 @foreach (FieldOptionValueViewModel info in fieldValue)
1110 {
1111 if (i > 0)
1112 {
1113 @(", " + info.Name)
1114 }
1115 else
1116 {
1117 @info.Name
1118 }
1119 i++;
1120 }
1121 </span>
1122 </div>
1123 </li>
1124 }
1125 }
1126 else
1127 {
1128 if (field.Value.ToString() != "0" && field.Value.ToString().ToLower() != "ingen")
1129 {
1130 <li class="product-description__technical-list-item">
1131 @if (field.Name.ToLower() == "number")
1132 {
1133 <div class="key">@Translate("Translate_General_ProductNumber")</div>
1134 }
1135 else if (field.Name.ToLower() == "weight")
1136 {
1137 <div class="key">@Translate("Translate_General_Weight")</div>
1138 }
1139 else
1140 {
1141 <div class="key">@field.Name</div>
1142 }
1143 <div class="value">
1144 <span class="line">@field.Value</span>
1145 </div>
1146 </li>
1147 }
1148 }
1149 }
1150 </ul>
1151 }
1152 @if (specsWithInfo != null)
1153 {
1154 <ul class="product-description__technical-list">
1155 @foreach (var field in specsWithInfo.Fields.Values)
1156 {
1157 if (field.Type.ToLower() == "list")
1158 {
1159 List<FieldOptionValueViewModel> fieldValue = (List<FieldOptionValueViewModel>)field.Value;
1160 int i = 0;
1161
1162 if (fieldValue.First().Value.ToString() != "-1" && fieldValue.Where(x => x.Name.ToLower() == "ingen").Count() == 0)
1163 {
1164 <li class="product-description__technical-list-item">
1165 <div class="key">@field.Name</div>
1166 <div class="value">
1167 <span class="line with-toolip">
1168 @foreach (FieldOptionValueViewModel info in fieldValue)
1169 {
1170 if (i > 0)
1171 {
1172 @(", " + info.Name)
1173 }
1174 else
1175 {
1176 @info.Name
1177 }
1178 i++;
1179 }
1180 <span class="tooltip">
1181 <span class="tooltip__icon">
1182 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
1183 {
1184 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
1185 }
1186 </span>
1187 <span class="tooltip__text tooltip__text--left">
1188 <p>@Translate("Translate_Product_Spec_Info_" + field.SystemName)</p>
1189 </span>
1190 </span>
1191 </span>
1192 </div>
1193 </li>
1194 }
1195 }
1196 else
1197 {
1198 if (field.Value.ToString() != "0" && field.Value.ToString().ToLower() != "ingen")
1199 {
1200 <li class="product-description__technical-list-item">
1201 <div class="key">@field.Name</div>
1202 <div class="value">
1203 <span class="line with-tooltip">
1204 @if (field.SystemName.ToLower() == "productdensity")
1205 {
1206 @field.Value.ToString().Replace(",", ".")
1207 }
1208 else
1209 {
1210 @field.Value
1211 }
1212 <span class="tooltip">
1213 <span class="tooltip__icon">
1214 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg")))
1215 {
1216 @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/info.svg"))
1217 }
1218 </span>
1219 <span class="tooltip__text tooltip__text--left">
1220 <p>@Translate("Translate_Product_Spec_Info_" + field.SystemName)</p>
1221 </span>
1222 </span>
1223 </span>
1224 </div>
1225 </li>
1226 }
1227 }
1228 }
1229 </ul>
1230 }
1231 </div>
1232 </div>
1233 @if (hasNewDownloads)
1234 {
1235 <div id="documents" class="tab__content documents" role="tabpanel" aria-hidden="false" aria-labelledby="documents-tab">
1236 <div class="rich-text">
1237 <h2>@Translate("Translate_Product_Page_Documents")</h2>
1238
1239 <ul class="tab__content-list product-description__documents-list">
1240 @foreach (var fileCat in GetLoop("ImageCategories"))
1241 {
1242 if (fileCat.GetString("Category.SystemName").StartsWith("docView_") && fileCat.GetLoop("Category.Images").Count() > 0)
1243 {
1244 <li class="product-description__documents-list-item">
1245 <p class="product-description__documents-list-item-title">@fileCat.GetString("Category.Name")</p>
1246 @foreach (var file in fileCat.GetLoop("Category.Images"))
1247 {
1248 string fileLink = file.GetString("Ecom:Product:Detail.Image.Clean");
1249 string fileName = file.GetString("Ecom:Product:Detail.Name");
1250
1251 if (String.IsNullOrWhiteSpace(fileName))
1252 {
1253 fileName = Path.GetFileNameWithoutExtension(fileLink);
1254 }
1255
1256 if (!String.IsNullOrEmpty(fileLink))
1257 {
1258 <a class="swap-link" href="@fileLink" data-link="@fileLink" target="_blank">
1259 @GetFileIcon(fileLink)
1260 @fileName.Replace("-", " ").Replace("_", " ")
1261 </a>
1262 }
1263 }
1264 </li>
1265 }
1266 }
1267 </ul>
1268 </div>
1269 </div>
1270 }
1271
1272 <div id="more-info" class="tab__content more-info-content" role="tabpanel" aria-hidden="false" aria-labelledby="more-info-tab">
1273 <div class="rich-text">
1274 <h2>@Translate("Translate_Product_Page_MoreInformation")</h2>
1275 @{
1276 CategoryFieldViewModel moreInfo = productViewmodel.FieldDisplayGroups.Values.Where(x => x.Id.ToLower() == "yderlig_information").FirstOrDefault();
1277
1278 if (moreInfo != null && moreInfo.Fields != null)
1279 {
1280 var groups = moreInfo.Fields.Values;
1281
1282 foreach (var group in groups)
1283 {
1284 <strong>@Translate("Translate_ProductPage_" + group.SystemName)</strong>
1285 @group.Value
1286 }
1287 }
1288 }
1289 </div>
1290 </div>
1291
1292 </article>
1293
1294 <div id="related-products">
1295 <article v-if="relatedProducts && relatedProducts.length > 0 && relatedList.length > 0" class="module module-sand-light related-products">
1296 <div class="rich-text">
1297 <h2 v-html="relatedGroups.find(x => x.Id == 'RELGRP2').Name"></h2>
1298 </div>
1299 <div class="card-swiper swiper" data-action="async-swiper">
1300 <div class="swiper-wrapper">
1301 <div v-for="product in relatedList" :key="product.Id" class="card-swiper__card swiper-slide">
1302 <picture v-if="product.DefaultImage.Value != ''" class="card-swiper__card-media">
1303 <source :srcset="productImage(product.DefaultImage.Value, 'lg')" media="(min-width: 1536px)">
1304 <source :srcset="productImage(product.DefaultImage.Value, 'md')" media="(min-width: 992px)">
1305 <source :srcset="productImage(product.DefaultImage.Value, 'sm')" media="(min-width: 768px)">
1306 <img :src="productImage(product.DefaultImage.Value, 'default')" :alt="product.Name">
1307 </picture>
1308 <div v-else class="card__picture card__picture--dummie"></div>
1309 <div class="card-swiper__card-info">
1310 <div class="card-swiper__card-preline">@Translate("Translate_Product_Page_ProductNumber"): {{ product.Number }}</div>
1311 <h4 class="card-swiper__card-headline">{{ product.Name }}</h4>
1312 <div class="card-swiper__card-teaser">{{ product.ProductFields.Name2.Value }}</div>
1313 <a class="card-swiper__card-link" :href="'/@(EcomPage)&ProductID=' + product.Id">@Translate("Translate_Product_Page_ProductLink")</a>
1314 </div>
1315 </div>
1316 </div>
1317 <div class="swiper-pagination"></div>
1318 </div>
1319 </article>
1320 <article v-if="relatedProducts && relatedProducts.length > 0 && accessoriesList.length > 0" class="module accessories-products" :class="{ 'module-sand': relatedList.length > 0, 'module-sand-light': relatedList.length == 0}">
1321 <div class="rich-text">
1322 <h2 v-html="relatedGroups.find(x => x.Id == 'RELGRP1').Name"></h2>
1323 </div>
1324 <div class="card-swiper swiper" data-action="async-swiper">
1325 <div class="swiper-wrapper">
1326 <div v-for="product in accessoriesList" :key="product.Id" class="card-swiper__card swiper-slide">
1327 <picture v-if="product.DefaultImage.Value != ''" class="card__picture">
1328 <source :srcset="productImage(product.DefaultImage.Value, 'lg')" media="(min-width: 1536px)">
1329 <source :srcset="productImage(product.DefaultImage.Value, 'md')" media="(min-width: 992px)">
1330 <source :srcset="productImage(product.DefaultImage.Value, 'sm')" media="(min-width: 768px)">
1331 <img :src="productImage(product.DefaultImage.Value, 'default')" :alt="product.Name">
1332 </picture>
1333 <div v-else class="card__picture card__picture--dummie"></div>
1334 <div class="card-swiper__card-info">
1335 <div class="card-swiper__card-preline">@Translate("Translate_Product_Page_ProductNumber"): {{ product.Number }}</div>
1336 <h4 class="card-swiper__card-headline">{{ product.Name }}</h4>
1337 <div class="card-swiper__card-teaser">{{ product.ProductFields.Name2.Value }}</div>
1338 <a class="card-swiper__card-link" :href="'/@(EcomPage)&ProductID=' + product.Id">@Translate("Translate_Product_Page_ProductLink")</a>
1339 </div>
1340 </div>
1341 </div>
1342 <div class="swiper-pagination"></div>
1343 </div>
1344 </article>
1345 @RenderItemList(new {
1346 ItemType = "Case",
1347 ListSourceType = "SelfArea",
1348 ItemFieldsList = "Headline,MainImage,Types,WoodTypes",
1349 ListTemplate = "itempublisher/list/productInspiration.cshtml",
1350 ListOrderBy = "Sort",
1351 ListPageSize = 100,
1352 Filter = BuildFilterString(primaryGroup)
1353 })
1354 </div>
1355
1356 @RenderSnippet("EnquireProductForm")
1357
1358 <div class="product-floating-bar">
1359 <div class="product-floating-bar__text">@productName @GetString("Ecom:Product:Field.Name2")</div>
1360 @if(totalStock > 0 && isloggedin && !enquireProduct) {
1361 if(primaryGroup == "group1" || primaryGroup == "group32" || primaryGroup == "group73") {
1362 <a class="btn btn-secondary product-floating-bar__button product-order-button">@Translate("Translate_Product_Page_OrderButton")</a>
1363 } else {
1364 <a href="#main" class="btn btn-secondary product-floating-bar__button">@Translate("Translate_Product_Page_OrderButton")</a>
1365 }
1366 } else {
1367 <a data-action="open-content" data-target="#enquireForm" class="btn btn-secondary product-floating-bar__button">@Translate("Translate_Product_Page_EnquireButton")</a>
1368 }
1369 </div>
1370
1371 @SnippetStart("JavaScripts")
1372 <script type="module" async>
1373 import Swiper from 'https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.esm.browser.min.js';
1374
1375 new Vue({
1376 el: "#related-products",
1377 name: "Related Products",
1378 data() {
1379 return {
1380 relatedGroups: null,
1381 relatedProducts: null,
1382 }
1383 },
1384 computed: {
1385 relatedList() {
1386 let list = [];
1387
1388 if(this.relatedProducts && this.relatedProducts.length > 0) {
1389 this.relatedProducts.forEach(product => {
1390 if(product.Active && Object.keys(product.PrimaryOrDefaultGroup).length > 0) {
1391 let group = this.relatedGroups.find(x => x.Id == "RELGRP2");
1392
1393 if(group && group.Products.find(x => x.ProductId == product.Id)) {
1394 list.push(product);
1395 }
1396 }
1397 })
1398 }
1399
1400 return list;
1401 },
1402 accessoriesList() {
1403 let list = [];
1404
1405 if(this.relatedProducts && this.relatedProducts.length > 0) {
1406 this.relatedProducts.forEach(product => {
1407 if(product.Active && Object.keys(product.PrimaryOrDefaultGroup).length > 0) {
1408 let group = this.relatedGroups.find(x => x.Id == "RELGRP1");
1409
1410 if(group && group.Products.find(x => x.ProductId == product.Id)) {
1411 list.push(product);
1412 }
1413 }
1414 })
1415 }
1416
1417 return list;
1418 }
1419 },
1420 async mounted() {
1421 await fetch(`/dwapi/ecommerce/products/@(productNumber)`)
1422 .then(response => response.json())
1423 .then(response => {
1424 this.relatedGroups = response.RelatedGroups;
1425 })
1426
1427 await fetch(`/dwapi/ecommerce/products/@(productNumber)/related?ShopId=@(Pageview.Area.EcomShopId)`)
1428 .then(response => response.json())
1429 .then(response => {
1430 if(response.TotalProductsCount > 0) {
1431 this.relatedProducts = response.Products;
1432 }
1433 })
1434 .catch(error => {
1435 console.log(error)
1436 })
1437
1438 const productsSliders = document.querySelectorAll('[data-action="async-swiper"]');
1439
1440 productsSliders.forEach(swiperContainer => {
1441 const productSlider = new Swiper(swiperContainer, {
1442 pagination: {
1443 el: '.swiper-pagination',
1444 type: 'progressbar'
1445 },
1446 slidesPerView: 'auto', // Slide sizes are controlled with css - not here
1447 speed: 500,
1448 parallax: true,
1449 centeredSlides: false,
1450 });
1451 });
1452 },
1453 methods: {
1454 productImage(path, size) {
1455 let imagePath = "/admin/public/getimage.ashx?Image=" + encodeURIComponent(path);
1456
1457 switch(size) {
1458 case 'lg':
1459 imagePath += '&Width=416&Height=416&Crop=0&Compression=100';
1460 break;
1461 case 'md':
1462 imagePath += '&Width=310&Height=310&Crop=0&Compression=100';
1463 break;
1464 case 'sm':
1465 imagePath += '&Width=&230Height=230&Crop=0&Compression=100';
1466 break;
1467 default:
1468 imagePath += '&Width=560&Height=560&Crop=0&Compression=100';
1469 break;
1470 }
1471
1472 return imagePath;
1473 }
1474 }
1475 })
1476 </script>
1477
1478 @SnippetEnd("Javascripts")
1479
1480 @if(productLayout != "group32" && productLayout != "group73" && productLayout != "group1") {
1481 @SnippetStart("JavaScripts")
1482 <script>
1483 const orderButton = document.getElementById("product-order-button");
1484
1485 if(orderButton) {
1486 const form = orderButton.closest('form');
1487
1488 orderButton.addEventListener('click', (event) => {
1489 event.preventDefault();
1490
1491 const formData = new FormData(form);
1492 const qty = parseInt(formData.get('Quantity1'))
1493
1494 const price = @GetString("Ecom:Product.Discount.Price.PriceWithoutVAT.Value").Replace(",", ".");
1495 const halfPrice = @GetString("Ecom:Product:Field.ProductPriceHalfParcel").Replace(",", "");
1496 const fullPrice = @GetString("Ecom:Product:Field.ProductPriceCompleteParcel").Replace(",", "");
1497
1498 const halfParcel = @halfParcelAmount;
1499 const fullParcel = @completeParcelAmount;
1500
1501 const salesUnit = "@salesUnit";
1502 const productLength = @GetString("Ecom:Product:Field.ProductLengthSale.Value.Raw");
1503 const lengthUnit = "@GetString("Ecom:Product:Field.ProductLengthUnitCode.Value")";
1504
1505 let value = 0;
1506
1507 addToValue(qty)
1508
1509 function addToValue(remainingQty) {
1510 if(salesUnit == "m") {
1511 value += remainingQty * (productLength/1000) * price;
1512 } else {
1513 value += remainingQty * price;
1514 }
1515 }
1516
1517 dataLayer.push({ ecommerce: null }); // Clear the previous ecommerce object.
1518 dataLayer.push({
1519 event: "add_to_cart",
1520 ecommerce: {
1521 currency: "@GetString("Ecom:Product.Currency.Code")",
1522 value: value,
1523 items: [
1524 {
1525 item_id: "@productNumber",
1526 item_name: "@productName",
1527 quantity: qty
1528
1529 }
1530 ]
1531 }
1532 });
1533 form.submit()
1534 });
1535 }
1536 </script>
1537 @SnippetEnd("Javascripts")
1538 }
1539
1540 @if(productLayout == "group32" || productLayout == "group73" || productLayout == "group1") {
1541 <div id="orderFlowApp" class="product-modal" :class="{ 'not-logged-in': !isLoggedIn, 'upsell js-slide-in' : showAccessories || showStep1 }">
1542 <div v-if="showAccessories" class="product-modal__content product-modal__upsell-section">
1543 <div class="product-modal__content-top">
1544 <a href="/" class="navigation__logo">
1545 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/keflico_logo.svg")))
1546 {
1547 <text>@System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/keflico_logo.svg"))</text>
1548 }
1549 </a>
1550 <a href="@CartPage" class="navigation__cart">
1551 <svg xmlns="http://www.w3.org/2000/svg" width="21.773" height="19.513" viewBox="0 0 21.773 19.513">
1552 <g transform="translate(0.75 0.75)">
1553 <path d="M122.747,269.657h9.076a1.359,1.359,0,0,0,1.342-1.148l1.28-5.631a.994.994,0,0,0-.982-1.148h-13.3" transform="translate(-114.186 -258.966)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1554 <path d="M88.321,247h2.551a.748.748,0,0,1,.724.563l1.973,8.555" transform="translate(-88.321 -247)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1555 <path d="M115.7,293.281l1.193,4.686h.043" transform="translate(-110.564 -284.597)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1556 <path d="M125.924,329.157a1.433,1.433,0,1,1-1.433-1.433A1.433,1.433,0,0,1,125.924,329.157Z" transform="translate(-116.54 -312.578)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1557 <path d="M169.05,329.157a1.433,1.433,0,1,1-1.433-1.433A1.433,1.433,0,0,1,169.05,329.157Z" transform="translate(-151.574 -312.578)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1558 <line x2="11.102" transform="translate(6.374 13.37)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1559 </g>
1560 </svg>
1561 <span class="cart-qty" data-count="@cartCount">@cartCount</span>
1562 </a>
1563 <a href="#" class="navigation__return product-modal__back-link" @@click="showAccessories = false">
1564 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20.006 12.445">
1565 <g transform="translate(-421.494 -889.275)">
1566 <path d="M-17182.074-20447.988l4.809-4.809,4.809,4.809" transform="translate(20875.289 -16281.768) rotate(-90)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
1567 <line x2="17" transform="translate(423.5 895.5)" fill="none" stroke="#000" stroke-linecap="round" stroke-width="2" />
1568 </g>
1569 </svg>
1570 </a>
1571 <div v-if="accessoriesList.length > 0" class="breadcrumbs breadcrumbs--no-seperator">
1572 <ul class="breadcrumbs__list">
1573 <li class="breadcrumbs__item">1. Vælg produkter</li>
1574 <li class="breadcrumbs__item active">2. Vælg tilbehør</li>
1575 </ul>
1576 </div>
1577 </div>
1578 <div class="upsell-section__top">
1579 <h1 class="upsell-section__title" v-html="'@Translate("Translate_OrderFlow_ProductsAdded")'.replace('{0}', '<span>' + productsAdded + '</span>')">Du har lagt <span>{{ productsAdded }}</span> varer i kurven</h1>
1580 <h2 class="upsell-section__subtitle">@Translate("Translate_OrderFlow_UpsellReminder")</h2>
1581 </div>
1582 <div class="upsell-section__card-list">
1583
1584 <div v-for="(product, index) in accessoriesList" class="upsell-card stock-card" :class="{ active: currentMobileProduct == product.Number, dirty: getQty(product.Number) > 0 }" @@click="toggleBar(product.Number)">
1585 <div class="counter-amount" v-if="getQty(product.Number) > 0">{{ getQty(product.Number) }}</div>
1586 <div class="upsell__content-info">
1587 <div class="upsell__content-info-media">
1588 <a :href="'/@(EcomPage)&ProductID=' + product.Number" target="_blank">
1589 <img :src="'/admin/public/getimage.ashx?Image=' + product.DefaultImage.Value + '&width=175&height=175&Crop=0&Compression=100'" :alt="product.Name" loading="lazy">
1590 </a>
1591 </div>
1592 <div class="upsell__content-info-container">
1593 <div class="product-details__info-meta">
1594 <ul class="product-details__info-meta-list">
1595 <li>@Translate("Translate_Product_Page_ProductNumber") {{ product.Number }}</li>
1596 @if(!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductDbNumber.Value"))) {
1597 <li>@GetString("Ecom:Product:Field.ProductDbNumber.Name") {{ product.EAN }}</li>
1598 }
1599 </ul>
1600 </div>
1601 <div class="product-details__info-title">{{ product.Name }}</div>
1602 <div class="product-details__info-size">{{ product.ProductFields.Name2.Value }}</div>
1603 <div class="product-details__info-quantity">
1604 <div class="info-quantity" v-if="product.ProductFields.ProductNumberPerPackage.Value && product.ProductFields.ProductNumberPerPackage.Value > 0">{{ product.ProductFields.ProductNumberPerPackage.Value }} @Translate("Translate_General_Pieces")</div>
1605 <div class="info-price" v-if="product.Price.Price">{{ prettyPrice(product.Price.Price) }} @priceCurrencySymbol</div>
1606 </div>
1607 <div class="product-details__info-actions" v-if="product.Price.Price && product.Price.Price > 0 && !product.VariantInfo.VariantInfo">
1608 <vue-counter :ref="'accCounter' + product.Number" :min="0" @@valueupdate="updateAccButton($event, product.Number)"></vue-counter>
1609 <a href="#" class="confirm disabled" :ref="'confirmBtn' + product.Number" @@click="addAcc($event, product.Number)">
1610 <svg v-if="pickedAcc.find(x => x.id == product.Number)" enable-background="new 0 0 24 24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
1611 <path fill="currentColor" d="m19.6025 12.6348c-.5586-.085-1.0547.2979-1.1348.8438-.2012 1.3711-.834 2.6221-1.8301 3.6182-2.5352 2.5352-6.6572 2.5332-9.1914 0-2.5337-2.5342-2.5337-6.6577 0-9.1914.9531-.9526 2.1563-1.5737 3.5029-1.7998.5791-.1099 1.2017-.1289 1.8477-.0557.887.1021 1.7126.3964 2.466.8285l-1.3019.2223c-.5439.0933-.9102.6099-.8164 1.1543.083.4873.5059.8315.9844.8315.0557 0 .1123-.0044.1699-.0142l3.4902-.5967c.2607-.0449.4941-.1914.6475-.4082.1533-.2163.2139-.4849.1689-.7466l-.5977-3.4897c-.0918-.5439-.6016-.9082-1.1543-.8169-.5439.0933-.9102.6104-.8164 1.1548l.1573.9185c-.9679-.543-2.0356-.8943-3.17-1.0249-.8496-.0967-1.6738-.0698-2.4282.0747-1.7368.291-3.3149 1.105-4.564 2.354-3.3135 3.3135-3.3135 8.7051 0 12.0195 1.6567 1.6572 3.8335 2.4854 6.0098 2.4854 2.1768 0 4.3525-.8281 6.0098-2.4854 1.3018-1.3018 2.1299-2.9414 2.3945-4.7412.0802-.5469-.2978-1.0548-.8437-1.1348z"/>
1612 </svg>
1613 <svg v-else xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21.773 19.513">
1614 <g transform="translate(-87.571 -246.25)">
1615 <g transform="translate(88.321 247)">
1616 <path d="M122.747,269.657h9.076a1.359,1.359,0,0,0,1.342-1.148l1.28-5.631a.994.994,0,0,0-.982-1.148h-13.3" transform="translate(-114.186 -258.966)" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1617 <path d="M88.321,247h2.551a.748.748,0,0,1,.724.563l1.973,8.555" transform="translate(-88.321 -247)" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1618 <path d="M115.7,293.281l1.193,4.686h.043" transform="translate(-110.564 -284.597)" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1619 <path d="M125.924,329.157a1.433,1.433,0,1,1-1.433-1.433A1.433,1.433,0,0,1,125.924,329.157Z" transform="translate(-116.54 -312.578)" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1620 <path d="M169.05,329.157a1.433,1.433,0,1,1-1.433-1.433A1.433,1.433,0,0,1,169.05,329.157Z" transform="translate(-151.574 -312.578)" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1621 <line x2="11.102" transform="translate(6.374 13.37)" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1622 </g>
1623 </g>
1624 </svg>
1625 </a>
1626 </div>
1627 </div>
1628 </div>
1629 </div>
1630 </div>
1631 <div class="notification-bar">
1632 <div class="notification-bar__text">
1633 @Translate("Translate_OrderFlow_HelpText")
1634 <a href="#product-inquire-form" @@click.prevent="openForm" id="product-orderflow-inquire-button" data-action="open-content" data-target="#enquireForm">@Translate("Translate_Product_Page_EnquireButton")</a>
1635 </div>
1636 </div>
1637 <div class="product-modal__content-bottom"></div>
1638 </div>
1639 <div v-if="!showAccessories" class="product-modal__content">
1640 <div class="product-modal__content-top">
1641 <a href="/" class="navigation__logo">
1642 @if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/keflico_logo.svg")))
1643 {
1644 <text>@System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/keflico_logo.svg"))</text>
1645 }
1646 </a>
1647 <a href="@CartPage" class="navigation__cart">
1648 <svg xmlns="http://www.w3.org/2000/svg" width="21.773" height="19.513" viewBox="0 0 21.773 19.513">
1649 <g transform="translate(0.75 0.75)">
1650 <path d="M122.747,269.657h9.076a1.359,1.359,0,0,0,1.342-1.148l1.28-5.631a.994.994,0,0,0-.982-1.148h-13.3" transform="translate(-114.186 -258.966)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1651 <path d="M88.321,247h2.551a.748.748,0,0,1,.724.563l1.973,8.555" transform="translate(-88.321 -247)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1652 <path d="M115.7,293.281l1.193,4.686h.043" transform="translate(-110.564 -284.597)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1653 <path d="M125.924,329.157a1.433,1.433,0,1,1-1.433-1.433A1.433,1.433,0,0,1,125.924,329.157Z" transform="translate(-116.54 -312.578)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1654 <path d="M169.05,329.157a1.433,1.433,0,1,1-1.433-1.433A1.433,1.433,0,0,1,169.05,329.157Z" transform="translate(-151.574 -312.578)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1655 <line x2="11.102" transform="translate(6.374 13.37)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
1656 </g>
1657 </svg>
1658 <span class="cart-qty" data-count="@cartCount">@cartCount</span>
1659 </a>
1660 <a href="#" class="navigation__return product-modal__back-link" @@click="showAccessories = false">
1661 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20.006 12.445">
1662 <g transform="translate(-421.494 -889.275)">
1663 <path d="M-17182.074-20447.988l4.809-4.809,4.809,4.809" transform="translate(20875.289 -16281.768) rotate(-90)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
1664 <line x2="17" transform="translate(423.5 895.5)" fill="none" stroke="#000" stroke-linecap="round" stroke-width="2" />
1665 </g>
1666 </svg>
1667 </a>
1668 <div v-if="accessoriesList.length > 0" class="breadcrumbs breadcrumbs--no-seperator">
1669 <ul class="breadcrumbs__list">
1670 <li class="breadcrumbs__item active">1. Vælg produkter</li>
1671 <li class="breadcrumbs__item">2. Vælg tilbehør</li>
1672 </ul>
1673 </div>
1674 </div>
1675 <div class="product-modal__content-info">
1676 <div class="product-modal__content-info-media">
1677 <picture v-if="mainProduct.image">
1678 <img :src="mainProduct.image" :alt="mainProduct.name" loading="lazy">
1679 </picture>
1680 </div>
1681 <div class="product-modal__content-info-container">
1682 <div class="product-details__info-meta">
1683 <ul class="product-details__info-meta-list">
1684 <li>{{ mainProduct.number }}</li>
1685 @if(!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProductDbNumber.Value"))) {
1686 <li>{{ mainProduct.dbNumber }}</li>
1687 }
1688 </ul>
1689 </div>
1690 <div class="product-details__info-title">{{ mainProduct.name }}</div>
1691 <div class="product-details__info-size">
1692 @if(primaryGroup == "group1") {
1693 <text>{{ mainProduct.size }}</text>
1694 } else {
1695 <div class="product-details__info-size-thickness">
1696 <strong>@Translate("Translate_OrderFlow_Thickness")</strong>
1697 {{ mainProduct.thickness }} {{ thicknessUnit }}
1698 </div>
1699 <div class="product-details__info-size-width">
1700 <strong>@Translate("Translate_OrderFlow_Width")</strong>
1701 {{ mainProduct.width }} {{ widthUnit }}
1702 </div>
1703 }
1704 </div>
1705 </div>
1706 </div>
1707 <div class="product-modal__content-product-stock">
1708 @if(primaryGroup == "group1") {
1709 <div class="tabs">
1710 <div v-if="bundles.length > 0" class="tabs__nav">
1711 <ul role="tablist" class="tabs__list" data-action="tabs">
1712 <li role="none" class="tabs__item">
1713 @Translate("Translate_OrderFlow_Choose_ProductType")
1714 </li>
1715 <li role="none" class="tabs__item">
1716 <a href="#helbundt" @@click.prevent="showBundles = true;" class="tab" :class="{ 'tab--active': showBundles }" role="tab" id="helbundt-tab" aria-controls="helbundt" aria-selected="true">
1717 <span>@Translate("Translate_OrderFlow_Bundle")</span>
1718 </a>
1719 </li>
1720 @if(!isBundleOnly) {
1721 <li role="none" class="tabs__item">
1722 <a href="#anbrud" @@click.prevent="showBundles = false;" class="tab" :class="{ 'tab--active': !showBundles }" role="tab" id="anbrud-tab" aria-controls="anbrud" aria-selected="false">
1723 <span>@Translate("Translate_OrderFlow_Pieces")</span>
1724 </a>
1725 </li>
1726 }
1727 </ul>
1728 </div>
1729 <div id="helbundt" v-if="bundles.length > 0" class="tab__content" :class="{ 'tab__content--active': showBundles }" role="tabpanel" aria-hidden="false" aria-labelledby="helbundt-tab">
1730 <div class="product-modal__stock">
1731 <div class="product-modal__stock-line product-modal__stock-line--header bundle-header">
1732 <div class="product-modal__stock-cell mobile-cell filler"></div>
1733 <div class="product-modal__stock-cell">@Translate("Translate_OrderFlow_BundleNo")</div>
1734 <div class="product-modal__stock-cell desktop-cell">@Translate("Translate_OrderFlow_Thickness")</div>
1735 <div class="product-modal__stock-cell desktop-cell">@Translate("Translate_OrderFlow_Width")</div>
1736 <div class="product-modal__stock-cell desktop-cell">@Translate("Translate_OrderFlow_Length")</div>
1737 <div v-if="!enquireProduct" class="product-modal__stock-cell desktop-cell">@Translate("Translate_OrderFlow_InStock")</div>
1738 <div v-if="!enquireProduct" class="product-modal__stock-cell">
1739 @Translate("Translate_OrderFlow_OnWayHome"):
1740 <span v-html="onTheWayHome"></span>
1741 </div>
1742 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__stock-cell product-modal__stock-cell--highlighted">@Translate("Translate_OrderFlow_ChooseAmount")</div>
1743 </div>
1744 <div v-if="!loadingBundles" v-for="bundle in sortedBundles" ref="bundle-line" :key="bundle.bundleNo" :class="{ active: currentMobileProduct == bundle.bundleNo, dirty: getQty(bundle.bundleNo) > 0, expanded: isExpanded(bundle.bundleNo) }" class="product-modal__stock-line stock-card stock-bundle-card" @@click="toggleBar(bundle.bundleNo)">
1745 <div class="stock-bundle__header">
1746 <div class="product-modal__stock-cell mobile-cell">
1747 <div class="cell-radio counter-amount bundle-amount" v-html="getQty(bundle.bundleNo) > 0 ? getQty(bundle.bundleNo) : ''" :data-id="bundle.bundleNo"></div>
1748 </div>
1749 <div class="product-modal__stock-cell">
1750 <span class="bundle-toggle" @@click="toggleBundle(bundle.bundleNo)">
1751 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12.446 7.223">
1752 <path d="M0,0,4.809,4.809,9.617,0" transform="translate(11.031 5.809) rotate(180)" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
1753 </svg>
1754 </span>
1755 {{ bundle.bundleNo }}
1756 </div>
1757 <div class="product-modal__stock-cell mobile-cell"></div>
1758 <div class="product-modal__stock-cell mobile-cell"></div>
1759 </div>
1760 <div class="stock-bundle__body">
1761 <div class="stock-bundle__body-columns">
1762 <div class="stock-bundle__cell">
1763 @Translate("Translate_OrderFlow_Dimensions")
1764 </div>
1765 <div class="stock-bundle__cell">
1766 @Translate("Translate_OrderFlow_InStock")
1767 </div>
1768 </div>
1769 <div v-for="(product, index) in bundle.productsInBundle" class="stock-bundle__stick">
1770 <div class="stock-bundle__cell mobile-cell">
1771 <div class="cell-stack">
1772 @Translate("Translate_OrderFlow_Thickness_Short") {{ product.thickness }} {{ thicknessUnit }}
1773 </div>
1774 <div class="cell-stack">
1775 @Translate("Translate_OrderFlow_Width_Short") {{ product.width }} {{ widthUnit }}
1776 </div>
1777 <div class="cell-stack">
1778 @Translate("Translate_OrderFlow_Length_Short") {{ product.length.replace(",", "") }} {{ lenghtUnit }}
1779 </div>
1780 </div>
1781 <div class="stock-bundle__cell desktop-cell">{{ product.thickness }} {{ thicknessUnit }}</div>
1782 <div class="stock-bundle__cell desktop-cell">{{ product.width }} {{ widthUnit }}</div>
1783 <div class="stock-bundle__cell desktop-cell">{{ product.length.replace(",", "") }} {{ lenghtUnit }}</div>
1784 <div v-if="!enquireProduct" class="stock-bundle__cell">{{ product.stock.units > 500 ? '+500' : product.stock.units }} @Translate("Translate_General_Pieces")</div>
1785 <div v-if="!enquireProduct" class="stock-bundle__cell desktop-cell"></div>
1786 <div v-if="isLoggedIn && !enquireProduct" class="stock-bundle__cell product-modal__stock-cell--highlighted desktop-cell">
1787 <vue-counter v-if="index == 0 && isLoggedIn && !enquireProduct" ref="counter" :min="0" :max="1" @@valueupdate="addBundleToTempCart($event, bundle.bundleNo)" />
1788 </div>
1789 </div>
1790 </div>
1791 </div>
1792 <div v-if="loadingBundles" class="bundle-loading">
1793 <span class="loader"></span>
1794 </div>
1795 </div>
1796 </div>
1797 @if(!isBundleOnly) {
1798 <div id="anbrud" class="tab__content" :class="{ 'tab__content--active': !showBundles }" role="tabpanel" aria-hidden="false" aria-labelledby="anbrud-tab">
1799 <div class="product-modal__stock">
1800 <div class="product-modal__stock-line product-modal__stock-line--header">
1801 <div class="product-modal__stock-cell filler mobile-cell" v-if="isLoggedIn && !enquireProduct"></div>
1802 <div class="product-modal__stock-cell mobile-cell">@Translate("Translate_OrderFlow_Dimension")</div>
1803 <div class="product-modal__stock-cell desktop-cell">@Translate("Translate_OrderFlow_Thickness")</div>
1804 <div class="product-modal__stock-cell desktop-cell">@Translate("Translate_OrderFlow_Width")</div>
1805 <div class="product-modal__stock-cell desktop-cell">@Translate("Translate_OrderFlow_Length")</div>
1806 <div v-if="!enquireProduct" class="product-modal__stock-cell">@Translate("Translate_OrderFlow_InStock")</div>
1807 <div v-if="!enquireProduct" class="product-modal__stock-cell">
1808 @Translate("Translate_OrderFlow_OnWayHome"):
1809 <span v-html="onTheWayHome"></span>
1810 </div>
1811 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__stock-cell product-modal__stock-cell--highlighted">@Translate("Translate_OrderFlow_ChooseAmount")</div>
1812 </div>
1813 <div v-for="(variant, index) in sortedVariants" v-if="variant.stock.warehouse > 0" class="product-modal__stock-line stock-card" :class="{ active: currentMobileProduct == variant.id, dirty: getQty(variant.id) > 0 }" @@click="toggleBar(variant.id)" :key="index">
1814 <div class="product-modal__stock-cell quantity" v-if="isLoggedIn && !enquireProduct">
1815 <div class="cell-radio counter-amount" :data-id="variant.id" v-html="getQty(variant.id) > 0 ? getQty(variant.id) : ''"></div>
1816 </div>
1817 <div class="product-modal__stock-cell cell-stack">
1818 <span class="stack">@Translate("Translate_OrderFlow_Thickness_Short") {{ variant.size.thickness }} {{ thicknessUnit }}</span>
1819 <span class="stack">@Translate("Translate_OrderFlow_Width_Short") {{ variant.size.width }} {{ widthUnit }}</span>
1820 <span class="stack">@Translate("Translate_OrderFlow_Length_Short") {{ variant.size.length }} {{ lenghtUnit }}</span>
1821 </div>
1822 <div class="product-modal__stock-cell desktop-cell">{{ variant.size.thickness }} {{ thicknessUnit }}</div>
1823 <div class="product-modal__stock-cell desktop-cell">{{ variant.size.width }} {{ widthUnit }}</div>
1824 <div class="product-modal__stock-cell desktop-cell">{{ variant.size.length }} {{ lenghtUnit }}</div>
1825 <div v-if="!enquireProduct" class="product-modal__stock-cell">{{ calculateStockLevel(variant.stock.warehouse) }} @Translate("Translate_General_Pieces") </div>
1826 <div v-if="!enquireProduct" class="product-modal__stock-cell"></div>
1827 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__stock-cell product-modal__stock-cell--highlighted" :class="{'out-of-stock': variant.stock.warehouse + variant.stock.pieces == 0 || enquireProduct}">
1828 <vue-counter v-if="variant.stock.warehouse + variant.stock.purchase > 0 && isLoggedIn && !enquireProduct" ref="counter" :min="0" @@valueupdate="addToTempCart($event, variant.id)" />
1829 </div>
1830 </div>
1831 </div>
1832 </div>
1833 }
1834 </div>
1835 } else {
1836 <div class="product-modal__stock">
1837 <div class="product-modal__stock-line product-modal__stock-line--header product-modal__stock-line--terrace">
1838 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__stock-cell filler mobile-cell"></div>
1839 <div class="product-modal__stock-cell">@Translate("Translate_OrderFlow_Length")</div>
1840 <div class="product-modal__stock-cell">@Translate("Translate_OrderFlow_InStock")</div>
1841 <div class="product-modal__stock-cell">@Translate("Translate_OrderFlow_OnWayHome")</div>
1842 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__stock-cell product-modal__stock-cell--highlighted">@Translate("Translate_OrderFlow_ChooseAmount")</div>
1843 </div>
1844 <div v-for="(variant, index) in sortedVariants" class="product-modal__stock-line stock-card" v-on="variant.stock.pieces > 0 || variant.stock.warehouse > 0 || variant.stock.sea > 0 ? { click: () => toggleBar(variant.id) } : {}" :class="{ 'out-of-stock': variant.stock.pieces == 0 && variant.stock.warehouse == 0 && variant.stock.sea == 0, dirty: getQty(variant.id) > 0, active: variant.id == currentMobileProduct }" :key="index">
1845 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__stock-cell quantity">
1846 <div class="cell-radio counter-amount" :data-id="variant.id" v-html="getQty(variant.id) > 0 ? getQty(variant.id) : ''"></div>
1847 </div>
1848 <div class="product-modal__stock-cell">{{ variant.size.length }} {{ lenghtUnit }}</div>
1849 <div class="product-modal__stock-cell">{{ calculateStockLevel(variant.stock.warehouse) }}</div>
1850 @if(primaryGroup == "group73") {
1851 <div class="product-modal__stock-cell">{{ variant.stock.purchase > 0 ? "@Translate("Translate_General_Yes")" : "@Translate("Translate_General_No")" }}</div>
1852 } else {
1853 <div class="product-modal__stock-cell">{{ calculateStockLevel(variant.stock.sea) }}</div>
1854 }
1855
1856 @if(primaryGroup == "group32") {
1857 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__stock-cell product-modal__stock-cell--highlighted" :class="{'out-of-stock': variant.stock.warehouse + variant.stock.sea == 0 || enquireProduct}">
1858 <vue-counter v-if="variant.stock.warehouse + variant.stock.sea > 0 && isLoggedIn && !enquireProduct" ref="counter" :min="0" @@valueupdate="addToTempCart($event, variant.id)" />
1859 </div>
1860 } else {
1861 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__stock-cell product-modal__stock-cell--highlighted" :class="{'out-of-stock': variant.stock.warehouse + variant.stock.pieces == 0 || enquireProduct}">
1862 <vue-counter v-if="variant.stock.warehouse + variant.stock.purchase > 0 && isLoggedIn && !enquireProduct" ref="counter" :min="0" @@valueupdate="addToTempCart($event, variant.id)" />
1863 </div>
1864 }
1865 </div>
1866 </div>
1867 }
1868 </div>
1869 <div class="notification-bar">
1870 <div class="notification-bar__text">
1871 @Translate("Translate_OrderFlow_HelpText")
1872 <a href="#product-inquire-form" id="product-orderflow-inquire-button" data-action="open-content" data-target="#enquireForm">@Translate("Translate_Product_Page_EnquireButton")</a>
1873 </div>
1874 </div>
1875 <div class="product-modal__content-bottom"></div>
1876 </div>
1877 <div class="product-modal__side">
1878 <div class="product-modal__side-top">
1879 <a href="#" class="product-modal__back-link" @@click="showAccessories = false">
1880 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20.006 12.445">
1881 <g transform="translate(-421.494 -889.275)">
1882 <path d="M-17182.074-20447.988l4.809-4.809,4.809,4.809" transform="translate(20875.289 -16281.768) rotate(-90)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
1883 <line x2="17" transform="translate(423.5 895.5)" fill="none" stroke="#fff" stroke-linecap="round" stroke-width="2" />
1884 </g>
1885 </svg>
1886 @Translate("Translate_ProductFlow_Back")
1887 </a>
1888 <div class="product-modal__basket-icon">
1889 <span class="icon"></span>
1890 <span class="badge"></span>
1891 </div>
1892 </div>
1893 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__side-basket" :class="{ 'popup--active': showMobileBasket }">
1894 <div v-if="pickedVariants.length > 0" class="side-basket__product">
1895 <div class="side-basket__product-head">
1896 <div class="product-name">{{ mainProduct.name }}</div>
1897 <div class="product-price">
1898 @if(primaryGroup == "group1") {
1899 <span v-if="!loadingPrice">{{ prettyPrice(priceObject.unitPrice) }} @priceCurrencySymbol / {{ mainProduct.prices.unit.label }}</span>
1900 <span v-if="loadingPrice" class="loader"></span>
1901 } else {
1902 <span v-if="!loadingPrice">{{ prettyPrice(priceObject.unitPrice) }} @priceCurrencySymbol / @Translate("Translate_General_RunningMeters")</span>
1903 <span v-if="loadingPrice" class="loader"></span>
1904 }
1905 </div>
1906 <div class="product-toggle" @@click="toggleState">
1907 <span class="close">@Translate("Translate_General_Close")</span>
1908 <span class="open">@Translate("Translate_General_Open")</span>
1909 </div>
1910 </div>
1911 <div v-for="(line, index) in sortedPickedVariants" class="side-basket__product-variant">
1912 @if(primaryGroup == "group1") {
1913 <template v-if="line.bundle">
1914 <div class="size size__header">
1915 <strong>@Translate("Translate_OrderFlow_BundleNo") {{ line.bundleNo }}</strong>
1916 </div>
1917 <template v-for="variant in line.productsInBundle">
1918 <div class="size">
1919 <template v-if="lenghtUnit == 'mm'">
1920 {{ variant.thickness.replace(".", ",") }} x {{ variant.width }} x {{ variant.length.replace(",", "") }}mm
1921 </template>
1922 <template v-else>
1923 {{ variant.thickness.replace(".", ",") }}{{ thicknessUnit }} x {{ variant.width }}{{ widthUnit }} x {{ variant.length.replace(",", "") }} {{ lenghtUnit }}
1924 </template>
1925 </div>
1926 <div class="quantity">{{ prettyNumber(variant.stock.units) }} @Translate("Translate_General_Pieces")</div>
1927 </template>
1928 </template>
1929 <template v-else>
1930 <div class="size size__header">
1931 <strong>@Translate("Translate_OrderFlow_Pieces")</strong>
1932 </div>
1933 <div class="size">{{ line.thickness }} x {{ line.width }} x {{ line.length }}mm</div>
1934 <div class="quantity">{{ prettyNumber(line.qty) }} @Translate("Translate_General_Pieces")</div>
1935 </template>
1936 } else {
1937 <div class="size">{{ mainProduct.thickness }} x {{ mainProduct.width }} x {{ line.length }}mm</div>
1938 <div class="quantity">{{ prettyNumber(line.qty) }} @Translate("Translate_General_Pieces")</div>
1939 }
1940 </div>
1941 <div class="side-basket__product-total">
1942 <div class="product-meters">
1943 @Translate("Translate_General_InTotal")
1944 <span v-if="mainProduct.prices.unit.label == 'm²' || mainProduct.prices.unit.label == 'm'">{{ prettyNumber(calculateMeters()) }} {{ mainProduct.prices.unit.label }}</span>
1945 <span v-else>{{ prettyNumber(calculatePieces()) }} @Translate("Translate_General_Pieces")</span>
1946 </div>
1947 <div class="product-square-meters">
1948 @Translate("Translate_General_TranslatesTo")
1949 <span v-if="mainProduct.prices.unit.label == 'm²' || mainProduct.prices.unit.label == 'm'">{{ prettyNumber(calculateSquareMeters()) }} m<sup>2</sup></span>
1950 <span v-else-if="mainProduct.prices.unit.label == 'm³'">{{ prettyNumber(calculateCubicMeters(), 3) }} m<sup>3</sup></span>
1951 <span v-else-if="mainProduct.prices.unit.label == 'kbf'">{{ prettyNumber(calculateCubicFeet()) }} kbf</span>
1952 </div>
1953 </div>
1954 </div>
1955 <div v-for="product in pickedAcc" class="side-basket__product">
1956 <div class="side-basket__product-head">
1957 <div class="product-name">{{ product.name }}</div>
1958 <div class="product-price">{{ prettyPrice(product.price.unitPrice) }}</div>
1959 <div class="product-toggle" @@click="toggleState">
1960 <span class="close">@Translate("Translate_General_Close")</span>
1961 <span class="open">@Translate("Translate_General_Open")</span>
1962 </div>
1963 </div>
1964 <div class="side-basket__product-variant">
1965 <div class="size">{{ product.name2 }}</div>
1966 <div class="quantity">{{ product.qty }} @Translate("Translate_General_Pieces")</div>
1967 </div>
1968 </div>
1969 <div class="side-basket__summary">
1970 <div class="price-raw">
1971 @Translate("Translate_General_PriceWithoutVat")
1972 <span v-if="!loadingPrice">{{ prettyPrice(priceObject.totalEx) }} @priceCurrencySymbol</span>
1973 <span v-if="loadingPrice" class="loader"></span>
1974 </div>
1975 <div class="vat">
1976 @Translate("Translate_General_Vat")
1977 <span v-if="!loadingPrice">{{ prettyPrice(priceObject.vat) }} @priceCurrencySymbol</span>
1978 <span v-if="loadingPrice" class="loader"></span>
1979 </div>
1980 <div class="price-vat">
1981 @Translate("Translate_General_PriceWithVat")
1982 <span v-if="!loadingPrice">{{ prettyPrice(priceObject.totalInc) }} @priceCurrencySymbol</span>
1983 <span v-if="loadingPrice" class="loader"></span>
1984 </div>
1985 </div>
1986
1987 <div v-if="isLoggedIn && !enquireProduct" class="product-modal__floating-cart">
1988 <div class="floating-cart__bar" :class="{ 'active-bar': showMobileActionBar }">
1989 <div v-if="showMobileActionControls" class="product-modal__stock-control floating-cart__stock-control counter">
1990 <button id="amount-subtract" @@click="currentMobileQty > 0 ? currentMobileQty-- : currentMobileQty = 0" class="substract"><span>−</span></button>
1991 <input id="amount-input" @@keyup="editMobileQty" class="amount" pattern="[0-9.]+" type="tel" data-min="0" min="0" :value="currentMobileQty">
1992 <button id="amount-add" @@click="currentMobileQty++" class="add"><span>+</span></button>
1993 </div>
1994 <div v-if="!showMobileActionControls" @@click="showMobileBasket = !showMobileBasket" class="floating-cart__toggle cart-toggle">
1995 <span v-if="!showMobileBasket" class="cart-toggle--open">Se kurv</span>
1996 <span v-if="showMobileBasket" class="cart-toggle--close">Luk kurv</span>
1997 </div>
1998 <div class="floating-cart__btn-wrapper">
1999 <button v-if="currentActiveMobileButton == 'add'" class="btn btn-secondary floating-cart__btn btn--add" :class="{ disabled: currentMobileQty == 0 }" @@click="updateMobileBasket">Tilføj til kurv</button>
2000 <button v-if="currentActiveMobileButton == 'update'" class="btn btn-secondary floating-cart__btn btn--update" :class="{ disabled: (currentMobileQty == 0 && currentActiveMobileButton == 'add') || currentMobileQty == getQty(currentMobileProduct) }" @@click="updateMobileBasket">Opdatér kurv</button>
2001 <button v-if="currentActiveMobileButton == 'next'" class="btn btn-secondary floating-cart__btn btn--next" @@click="addToBasket">
2002 <template v-if="!loading">Gå videre</template>
2003 <span v-if="loading" class="loader"></span>
2004 </button>
2005 <button v-if="currentActiveMobileButton == 'order' && !showAccessories" class="btn btn-secondary floating-cart__btn btn--order" @@click="addToBasket">
2006 <template v-if="!loading">Gå til bestilling</template>
2007 <span v-if="loading" class="loader"></span>
2008 </button>
2009 <button v-if="currentActiveMobileButton == 'order' && showAccessories" class="btn btn-secondary floating-cart__btn btn--order" @@click="addAccToBasket">
2010 <template v-if="!loading">Gå til bestilling</template>
2011 <span v-if="loading" class="loader"></span>
2012 </button>
2013 </div>
2014 </div>
2015 </div>
2016
2017 <div class="side-basket__actions">
2018 <template v-if="!showAccessories">
2019 <button type="button" @@click="resetBasket" class="btn btn-link btn-link--underlined" :class="{ disabled: pickedVariants.length == 0 }">@Translate("Translate_General_EmptyCart")</button>
2020 <button type="button" :class="{ disabled: pickedVariants.length == 0 }" @@click="addToBasket" class="btn btn-secondary">
2021 <template v-if="!loading">@Translate("Translate_General_AddToCart")</template>
2022 <span v-if="loading" class="loader"></span>
2023 </button>
2024 </template>
2025 <template v-else>
2026 <a href="@CartPage" class="btn btn-link btn-link--underlined">@Translate("Translate_General_GoToCheckout")</a>
2027 <button type="button" @@click="addAccToBasket" class="btn btn-secondary" :class="{ disabled: pickedAcc.length == 0}">
2028 <template v-if="!loading">@Translate("Translate_OrderFlow_AddAccessories")</template>
2029 <span v-if="loading" class="loader"></span>
2030 </button>
2031 </template>
2032 </div>
2033 </div>
2034 </div>
2035 </div>
2036
2037
2038 @SnippetStart("JavaScripts")
2039 <script>
2040 dataLayer.push({ ecommerce: null }); // Clear the previous ecommerce object.
2041 dataLayer.push({
2042 event: "view_item",
2043 ecommerce: {
2044 items: [
2045 {
2046 item_id: "@productNumber",
2047 item_name: "@productName",
2048 }
2049 ]
2050 }
2051 });
2052
2053 </script>
2054 <script async>
2055 const vueCounter = {
2056 name: "VueCounter",
2057 props: ['min', 'max'],
2058 data: () => {
2059 return {
2060 value: 0,
2061 hasError: false,
2062 }
2063 },
2064 methods: {
2065 substract() {
2066 if(this.min || this.min === 0) {
2067 if(this.value > this.min) {
2068 this.value--
2069 } else {
2070 this.handleError();
2071 }
2072 } else {
2073 this.value--
2074 }
2075 },
2076 add() {
2077 if(this.max) {
2078 if(this.value < this.max) {
2079 this.value++
2080 } else {
2081 this.handleError();
2082 }
2083 } else {
2084 this.value++
2085 }
2086 },
2087 handleError() {
2088 this.hasError = true;
2089 setTimeout(() => {
2090 this.hasError = false;
2091 }, 1000);
2092 }
2093 },
2094 watch: {
2095 value(newValue, oldValue) {
2096 this.$emit('valueupdate', newValue)
2097 }
2098 },
2099 template: `<div class="vue-counter" :class="hasError ? 'counter--error' : ''" >
2100 <a class="counter__sub" @@click="substract">-</a>
2101 <input class="counter__value" type="tel" v-model="value" :disabled="value == max ? true : false">
2102 <a class="counter__add" @@click="add">+</a>
2103 </div>`
2104 }
2105
2106 new Vue({
2107 el: '#orderFlowApp',
2108 name: 'Bestillings flow',
2109 components: {
2110 'vue-counter': vueCounter
2111 },
2112 computed: {
2113 lenghtUnit() {
2114 return this.sizeUnitValues[this.mainProduct.sizeUnits.length];
2115 },
2116 widthUnit() {
2117 return this.sizeUnitValues[this.mainProduct.sizeUnits.width];
2118 },
2119 thicknessUnit() {
2120 return this.sizeUnitValues[this.mainProduct.sizeUnits.thickness];
2121 },
2122 sortedVariants() {
2123 return this.variants.sort((a,b) => {
2124 if (a.length !== b.length) {
2125 return a.length - b.length;
2126 } else if (a.width !== b.width) {
2127 return a.width - b.width;
2128 } else {
2129 return a.thickness - b.thickness;
2130 }
2131 }).filter(x => x.size.length > 0);
2132 },
2133 sortedBundles() {
2134 let newBundleList = [];
2135
2136 if(this.bundles.length > 0) {
2137 this.bundles.forEach(bundle => {
2138 const index = newBundleList.findIndex(x => x.bundleNo == bundle.bundleNo);
2139
2140 if(parseFloat(bundle.stock.warehouse) > 0) {
2141 if(index > -1) {
2142 newBundleList[index].productsInBundle.push(
2143 {
2144 length: bundle.length,
2145 width: bundle.width,
2146 thickness: bundle.thickness,
2147 stock: bundle.stock
2148 }
2149 )
2150 } else {
2151 this.toggleBundles.push({
2152 bundle: bundle.bundleNo,
2153 expanded: true,
2154 });
2155 newBundleList.push(
2156 {
2157 bundleNo: bundle.bundleNo,
2158 productsInBundle: [
2159 {
2160 length: bundle.length,
2161 width: bundle.width,
2162 thickness: bundle.thickness,
2163 stock: bundle.stock
2164 }
2165 ]
2166 }
2167 )
2168 }
2169 }
2170 })
2171 }
2172
2173 return newBundleList;
2174 },
2175 sortedPickedVariants() {
2176 return this.pickedVariants.sort((x,y) => x.bundle - y.bundle);
2177 },
2178 ga4Products() {
2179 let list = [];
2180
2181 this.sortedPickedVariants.forEach(product => {
2182 let productObject = {};
2183
2184 if(product.bundle) {
2185 productObject.item_name = this.mainProduct.name;
2186 productObject.item_id = product.bundleNo;
2187 productObject.productsInBundle = product.productsInBundle;
2188 } else {
2189 productObject.item_id = product.id,
2190 productObject.item_name = this.mainProduct.name,
2191 productObject.item_variant = product.variantId,
2192 productObject.quantity = product.qty,
2193 productObject.price = this.priceObject.unitPrice
2194 }
2195
2196 list.push(productObject)
2197 })
2198
2199 return list;
2200 },
2201 onTheWayHome() {
2202 if(this.variants.filter(x => x.stock.pieces > 0).length > 0) {
2203 return "@Translate("Translate_General_Yes")";
2204 }
2205
2206 return "@Translate("Translate_General_No")";
2207 },
2208 accessoriesList() {
2209 let list = [];
2210
2211 if(this.relatedProducts && this.relatedProducts.length > 0) {
2212 this.relatedProducts.forEach(product => {
2213 let group = this.relatedGroups.find(x => x.Id == "RELGRP1");
2214
2215 if(group && group.Products.find(x => x.ProductId == product.Id)) {
2216 list.push(product);
2217 }
2218 })
2219 }
2220
2221 return list;
2222 }
2223 },
2224 mounted() {
2225 this.getVariants(@(productNumber))
2226 @if(primaryGroup == "group1") {
2227 <text>
2228 this.lookUpBundle(@(productNumber));
2229 </text>
2230 }
2231
2232 this.getAccessories();
2233
2234 if(!this.enquireProduct && this.isLoggedIn) {
2235 this.orderButtonSpinner = setTimeout(() => {
2236 document.querySelector('#product-order-button .loader').style.display = "inline-block";
2237 }, 3000);
2238 } else {
2239 document.querySelector('#product-order-button .product-order-form-button').style.display = "block";
2240 }
2241 },
2242 data() {
2243 return {
2244 isLoggedIn: @isloggedin.ToString().ToLower(),
2245 enquireProduct: @enquireProduct.ToString().ToLower(),
2246 lang: document.querySelector('html').getAttribute('data-lang'),
2247 loading: false,
2248 loadingPrice: false,
2249 loadingBundles: false,
2250 loadingVariants: false,
2251 orderLoader: true,
2252 orderButtonSpinner: null,
2253 timeOut: null,
2254 priceObject: {
2255 unitPrice: 0,
2256 totalEx: 0,
2257 vat: 0,
2258 totalInc: 0,
2259 corePrice: 0
2260 },
2261 customerNumber: '@GetGlobalValue("Global:Extranet.CustomerNumber")',
2262 sizeUnitValues: {
2263 'ZOLL/00': '@Translate("Translate_Product_SizeUnit_Inch")',
2264 'ZOLL/01': '@Translate("Translate_Product_SizeUnit_Inch")',
2265 'FUß/00': '@Translate("Translate_Product_SizeUnit_Foot")',
2266 'FUß/01': '@Translate("Translate_Product_SizeUnit_Foot")',
2267 'MM/00': '@Translate("Translate_Product_SizeUnit_Millimeter")',
2268 'MM/01': '@Translate("Translate_Product_SizeUnit_Millimeter")'
2269 },
2270 mainProduct: {
2271 name: '@productName',
2272 id: @productNumber,
2273 number: '@Translate("Translate_Product_Page_ProductNumber"): @productNumber',
2274 dbNumber: '@GetString("Ecom:Product:Field.ProductDbNumber.Name"): @GetString("Ecom:Product:Field.ProductDbNumber.Value")',
2275 width: '@GetString("Ecom:Product:Field.ProductWidthSale.Value.Raw")',
2276 thickness: '@GetString("Ecom:Product:Field.ProductThicknessSale.Value.Raw")',
2277 image: '@GetString("Ecom:Product.ImageDefault.Clean")',
2278 size: @Json.Encode(GetString("Ecom:Product:Field.Name2")),
2279 prices: {
2280 unit: {
2281 code: "@salesUnitCode",
2282 label: "@salesUnit"
2283 },
2284 standard: @standardPriceJS,
2285 above100: @above100PriceJS,
2286 bundle: @bundlePriceJS
2287 },
2288 sizeUnits: {
2289 length: '@GetString("Ecom:Product:Field.ProductLengthUnitCode.Value")',
2290 width: '@GetString("Ecom:Product:Field.ProductWidthUnitCode.Value")',
2291 thickness: '@GetString("Ecom:Product:Field.ProductThicknessUnitCode.Value")',
2292 }
2293 },
2294 relatedGroups: null,
2295 relatedProducts: null,
2296 variants: [],
2297 showAccessories: false,
2298 showStep1: false,
2299 showBundles: false,
2300 bundles: [],
2301 pickedVariants: [],
2302 productsAdded: 0,
2303 pickedAcc: [],
2304 currentMobileProduct: '',
2305 showMobileBasket: false,
2306 showMobileActionBar: false,
2307 showMobileActionControls: false,
2308 currentActiveMobileButton: 'none',
2309 currentMobileQty: 0,
2310 toggleBundles: [],
2311 }
2312 },
2313 methods: {
2314 doesCookieExist(cookieName) {
2315 const cookies = document.cookie.split('; ');
2316 const cookieExists = cookies.some(cookie => cookie.startsWith(cookieName + '='));
2317 return cookieExists;
2318 },
2319 setCookie(name, value, days) {
2320 let expires = "";
2321 if (days) {
2322 const date = new Date();
2323 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
2324 expires = "; expires=" + date.toUTCString();
2325 }
2326 document.cookie = name + "=" + (value || "") + expires + "; path=/";
2327 },
2328 deleteCookie(name) {
2329 document.cookie = name + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
2330 },
2331 async getAccessories() {
2332 await fetch(`/dwapi/ecommerce/products/@(productNumber)`)
2333 .then(response => response.json())
2334 .then(response => {
2335 this.relatedGroups = response.RelatedGroups;
2336 })
2337
2338 await fetch(`/dwapi/ecommerce/products/@(productNumber)/related`)
2339 .then(response => response.json())
2340 .then(response => {
2341 if(response.TotalProductsCount > 0) {
2342 this.relatedProducts = response.Products;
2343 }
2344 })
2345 .catch(error => {
2346 console.log(error)
2347 })
2348 },
2349 getVariants: async function(productNo, url) {
2350 this.loadingVariants = true;
2351 let requestUrl = `@(VariantsLookup)&ICC_itemId=${productNo}`;
2352
2353 if(url && url != "") {
2354 requestUrl = url;
2355 }
2356
2357 if(!this.isLoggedIn) {
2358 if(requestUrl.indexOf('username') < 0) {
2359 requestUrl += '&username=marketing@keflico.com&password=Keflico100%';
2360 }
2361
2362 if (!this.doesCookieExist('tempLogin')) {
2363 this.setCookie('tempLogin', true, 1);
2364 }
2365 }
2366
2367 fetch(requestUrl, {
2368 credentials: "same-origin"
2369 })
2370 .then(response => response.json())
2371 .then(response => {
2372 if(response.variants && response.variants.length > 0) {
2373 this.variants = this.variants.concat(response.variants);
2374
2375 this.orderLoader = false;
2376
2377 if(response.nextPage != "") {
2378 this.getVariants(productNo, response.nextPage);
2379 } else {
2380 this.loadingVariants = false;
2381
2382 if(!this.isLoggedIn) {
2383 fetch('/Admin/Public/ExtranetLogoff.aspx');
2384 }
2385 }
2386 } else {
2387 this.loadingVariants = false;
2388
2389 if(!this.loadingBundles) {
2390 clearTimeout(this.orderButtonSpinner);
2391 document.querySelector('#product-order-button .product-order-form-button').style.display = "block";
2392 document.querySelector('#product-order-button .loader').style.display = "none";
2393 }
2394 }
2395 })
2396 },
2397 lookUpBundle: async function(productNo, url) {
2398 this.loadingBundles = true;
2399 let requestUrl = `@(BundleLookup)&ICC_itemId=${productNo}`;
2400
2401 if(url && url != "") {
2402 requestUrl = url;
2403 }
2404
2405 if(!this.isLoggedIn) {
2406 if(requestUrl.indexOf('username') < 0) {
2407 requestUrl += '&username=marketing@keflico.com&password=Keflico100%';
2408 }
2409
2410 if (!this.doesCookieExist('tempLogin')) {
2411 this.setCookie('tempLogin', true, 1);
2412 }
2413 }
2414
2415 fetch(requestUrl, {
2416 credentials: "same-origin"
2417 })
2418 .then(response => response.json())
2419 .then(response => {
2420 if(response.bundles && response.bundles.length > 0) {
2421
2422 if(response.currentPage = 1) {
2423 this.showBundles = true;
2424 }
2425
2426 this.orderLoader = false;
2427 } else {
2428 if(!this.loadingVariants) {
2429 clearTimeout(this.orderButtonSpinner);
2430 document.querySelector('#product-order-button .product-order-form-button').style.display = "block";
2431 document.querySelector('#product-order-button .loader').style.display = "none";
2432 }
2433 }
2434
2435 this.bundles = this.bundles.concat(response.bundles);
2436
2437 if(response.nextPage != "") {
2438 this.lookUpBundle(productNo, response.nextPage);
2439 } else {
2440 this.loadingBundles = false;
2441
2442 if(!this.isLoggedIn) {
2443 fetch('/Admin/Public/ExtranetLogoff.aspx');
2444 }
2445 }
2446 })
2447 },
2448 tempPriceUpdate() {
2449 let totalAccPrice = 0;
2450
2451 this.pickedAcc.forEach(acc => {
2452 totalAccPrice += parseFloat(acc.price.exVat.replace(',', ''))
2453 })
2454
2455 this.priceObject.totalEx = parseFloat(this.priceObject.corePrice) + totalAccPrice;
2456 this.priceObject.vat = parseFloat(this.priceObject.totalEx) * 0.25;
2457 this.priceObject.totalInc = parseFloat(this.priceObject.totalEx) * 1.25;
2458 },
2459 priceLookUp: async function() {
2460 let x = 1;
2461 let y = 1;
2462 let queryString = "&ICC_userId=" + this.customerNumber + "&ICC_itemId=" + this.mainProduct.id;
2463
2464 this.pickedVariants.forEach(variant => {
2465 if(variant.bundle) {
2466 queryString += "&ICC_bundle" + y + "=" + variant.bundleNo;
2467
2468 y++;
2469 } else {
2470 queryString += "&ICC_variant" + x + "=" + variant.id;
2471 queryString += "&ICC_quantity" + x + "=" + variant.qty;
2472
2473 x++;
2474 }
2475 })
2476
2477 fetch(`@(PriceLookup)${queryString}`)
2478 .then(response => response.json())
2479 .then(response => {
2480 this.priceObject.corePrice = parseFloat(response.totalPriceWithoutVat.replace(",", ""));
2481 this.priceObject.unitPrice = response.unitPrice;
2482 this.priceObject.totalEx = response.totalPriceWithoutVat;
2483 this.priceObject.vat = response.vat;
2484 this.priceObject.totalInc = response.totalPriceWithVat;
2485
2486 this.loadingPrice = false;
2487 })
2488 },
2489 toggleBundle(bundleNo) {
2490 this.toggleBundles.find(x => x.bundle == bundleNo).expanded = !this.toggleBundles.find(x => x.bundle == bundleNo).expanded;
2491 },
2492 isExpanded(bundleNo) {
2493 return this.toggleBundles.find(x => x.bundle == bundleNo).expanded;
2494 },
2495 getQty(variantId) {
2496 let product = this.pickedVariants.find(x => x.id == variantId || x.bundleNo == variantId);
2497 let acc = this.pickedAcc.find(x => x.id == variantId);
2498
2499 if(product || acc) {
2500 if(product) {
2501 if(product.bundle) {
2502 return 1;
2503 }
2504
2505 return product.qty;
2506 } else {
2507 return acc.qty;
2508 }
2509 } else {
2510 return 0;
2511 }
2512 },
2513 toggleBar(productId) {
2514 let product = this.accessoriesList.find(x => x.Id == productId); // product is acc
2515
2516 if((product && product.Price.Price && product.Price.Price > 0 && !product.VariantInfo.VariantInfo) || !product) {
2517 if(this.currentMobileProduct != productId) {
2518 this.currentMobileProduct = productId;
2519 this.showMobileActionBar = true;
2520 this.showMobileActionControls = true;
2521
2522 if(this.pickedVariants.find(x => x.id == productId)) {
2523 this.currentActiveMobileButton = 'update';
2524 this.currentMobileQty = this.pickedVariants.find(x => x.id == productId).qty;
2525 } else if(this.pickedAcc.find(x => x.id == productId)) {
2526 this.currentActiveMobileButton = 'update';
2527 this.currentMobileQty = this.pickedAcc.find(x => x.id == productId).qty;
2528 } else {
2529 this.currentActiveMobileButton = 'add';
2530 this.currentMobileQty = 0;
2531 }
2532 } else {
2533 this.currentMobileProduct = '';
2534 this.showMobileActionControls = false;
2535
2536 if(this.pickedVariants.length == 0) {
2537 this.showMobileActionBar = false;
2538 }
2539
2540 if(this.showAccessories || this.accessoriesList.length == 0) {
2541 this.currentActiveMobileButton = 'order';
2542 } else {
2543 this.currentActiveMobileButton = 'next';
2544 }
2545 }
2546 }
2547 },
2548 addToTempCart(amount, id) {
2549 this.loadingPrice = true;
2550 clearTimeout(this.timeOut);
2551
2552 if(this.pickedVariants.filter(x => x.id == id).length > 0) {
2553 if(amount > 0) {
2554 this.pickedVariants.find(x => x.id == id).qty = amount;
2555 } else {
2556 const index = this.pickedVariants.findIndex(x => x.id == id);
2557 this.pickedVariants.splice(index, 1);
2558 }
2559 } else {
2560 if(amount > 0) {
2561 const data = this.sortedVariants.find(x => x.id == id);
2562
2563 this.pickedVariants.push({
2564 bundle: false,
2565 id: id,
2566 qty: parseInt(amount),
2567 length: data.size.length,
2568 width: data.size.width,
2569 thickness: data.size.thickness,
2570 variantId: data.id
2571 });
2572 }
2573 }
2574
2575 if(this.pickedVariants.length > 0) {
2576 this.timeOut = setTimeout(() => {
2577 this.priceLookUp();
2578 }, 1000);
2579 } else {
2580 this.priceObject.totalEx = 0;
2581 this.priceObject.totalInc = 0;
2582 this.priceObject.vat = 0;
2583 this.priceObject.unitPrice = 0;
2584
2585 this.loadingPrice = false;
2586 }
2587 },
2588 editMobileQty($event) {
2589 this.currentMobileQty = $event.target.value
2590 },
2591 updateMobileBasket() {
2592 let productToUpdate = this.sortedVariants.find(x => x.id == this.currentMobileProduct);
2593
2594 if(!productToUpdate) {
2595 productToUpdate = this.sortedBundles.find(x => x.bundleNo == this.currentMobileProduct);
2596 }
2597
2598 if(productToUpdate) {
2599 if(productToUpdate.bundleNo) {
2600 this.addBundleToTempCart(1, this.currentMobileProduct);
2601 } else {
2602 this.addToTempCart(this.currentMobileQty, this.currentMobileProduct);
2603 }
2604
2605 this.showMobileActionControls = false;
2606 this.currentMobileProduct = '';
2607
2608 if(this.accessoriesList.length == 0) {
2609 this.currentActiveMobileButton = 'order';
2610 } else {
2611 this.currentActiveMobileButton = 'next';
2612 }
2613 } else {
2614 productToUpdate = this.accessoriesList.find(x => x.id == this.currentMobileProduct);
2615
2616 this.addAcc(this.currentMobileQty, this.currentMobileProduct);
2617
2618 this.showMobileActionControls = false;
2619 this.currentMobileProduct = '';
2620 this.currentActiveMobileButton = 'order';
2621 }
2622 },
2623 addBundleToTempCart(amount, bundleNo) {
2624 this.loadingPrice = true;
2625 clearTimeout(this.timeOut);
2626
2627 if(amount > 0) {
2628 this.pickedVariants.push({
2629 bundle: true,
2630 bundleNo: bundleNo,
2631 productsInBundle: this.sortedBundles.filter(x => x.bundleNo == bundleNo)[0].productsInBundle
2632 })
2633 } else {
2634 const index = this.pickedVariants.findIndex(x => x.bundleNo == bundleNo);
2635 this.pickedVariants.splice(index, 1);
2636 }
2637
2638 if(this.pickedVariants.length > 0) {
2639 this.timeOut = setTimeout(() => {
2640 this.priceLookUp();
2641 }, 1000);
2642 } else {
2643 this.priceObject.totalEx = 0;
2644 this.priceObject.totalInc = 0;
2645 this.priceObject.vat = 0;
2646 this.priceObject.unitPrice = 0;
2647
2648 this.loadingPrice = false;
2649 }
2650 },
2651 updateAccButton(amount, productNumber) {
2652 if((amount > 0 && (!this.pickedAcc.find(x => x.id == productNumber) || amount != this.pickedAcc.find(x => x.id == productNumber).qty)) || (this.pickedAcc.find(x => x.id == productNumber) && amount != this.pickedAcc.find(x => x.id == productNumber).qty)) {
2653 this.$refs['confirmBtn' + productNumber][0].classList.remove('disabled')
2654 } else {
2655 this.$refs['confirmBtn' + productNumber][0].classList.add('disabled')
2656 }
2657 },
2658 addAcc(event, productNumber) {
2659 let product = this.pickedAcc.find(x => x.id == productNumber);
2660 let qty = typeof event == 'number' ? event : this.$refs['accCounter' + productNumber][0].value;
2661
2662 let queryString = `&ICC_userId=${this.customerNumber}&ICC_itemId=${productNumber}&ICC_quantity1=`;
2663
2664 if(product) {
2665 if(qty > 0) {
2666 product.qty = qty;
2667 queryString += product.qty;
2668 } else {
2669 this.pickedAcc.splice(this.pickedAcc.findIndex(x => x.id == product.id), 1);
2670 }
2671 } else {
2672 this.pickedAcc.push({
2673 id: productNumber,
2674 name: this.accessoriesList.find(x => x.Number == productNumber).Name,
2675 name2: this.accessoriesList.find(x => x.Number == productNumber).ProductFields.Name2.Value,
2676 qty: qty,
2677 price: {
2678 exVat: 0,
2679 vat: 0,
2680 withVat: 0,
2681 unitPrice: 0
2682 }
2683 })
2684
2685 queryString += qty;
2686 }
2687
2688 if(qty > 0) {
2689 fetch(`/Default.aspx?ID=1115${queryString}`)
2690 .then(response => response.json())
2691 .then(response => {
2692 if(product) {
2693 product.price.exVat = response.totalPriceWithoutVat;
2694 product.price.vat = response.vat;
2695 product.price.withVat = response.totalPriceWithVat;
2696 product.price.unitPrice = response.unitPrice;
2697 } else {
2698 const newProduct = this.pickedAcc.at(-1);
2699
2700 newProduct.price.exVat = response.totalPriceWithoutVat;
2701 newProduct.price.vat = response.vat;
2702 newProduct.price.withVat = response.totalPriceWithVat;
2703 newProduct.price.unitPrice = response.unitPrice;
2704 }
2705
2706 this.tempPriceUpdate();
2707 })
2708 } else {
2709 this.tempPriceUpdate();
2710 }
2711
2712 this.$refs['confirmBtn' + productNumber][0].classList.add('disabled');
2713 },
2714 prettyNumber(number, minDigits) {
2715 return parseFloat(number).toLocaleString(this.lang, { minimumFractionDigits: minDigits ? minDigits : 0 })
2716 },
2717 prettyPrice(price) {
2718 let rawPrice = price;
2719
2720 if(typeof price == "string" && (price.split(".").length - 1 > 1 || (price.indexOf(".") == 1 && price.length > 4) || (price.indexOf(".") == 2 && price.length >= 6) || (price.indexOf(".") == 3 && price.length > 6))) {
2721 // Price is over 1000 in danish format
2722
2723 rawPrice = rawPrice.replaceAll(".", "");
2724 rawPrice = rawPrice.replaceAll(",", ".");
2725 } else if(typeof price == "string" && (price.split(",").length - 1 > 1 || (price.indexOf(",") == 1 && price.length > 4) || (price.indexOf(",") == 2 && price.length >= 6) || (price.indexOf(",") == 3 && price.length > 6))) {
2726 // Price is over 1000 in english format
2727
2728 rawPrice = rawPrice.replaceAll(",", "");
2729 }
2730
2731 rawPrice = parseFloat(rawPrice);
2732 return rawPrice.toLocaleString(this.lang, { minimumFractionDigits: 2, maximumFractionDigits: 2 } )
2733 },
2734 calculateStockLevel(stock) {
2735 if(this.isLoggedIn && stock >= 0) {
2736 return stock > 500 ? '+500' : stock;
2737 } else {
2738 return stock > 100 ? '+100' : stock;
2739 }
2740
2741 return 0;
2742 },
2743 toggleState($event) {
2744 $event.target.closest('.side-basket__product').classList.toggle('closed');
2745 },
2746 openForm(e) {
2747 document.querySelector('.product-modal').classList.remove('js-slide-in');
2748
2749 const toggleTrigger = e.currentTarget;
2750 const target = document.querySelector(toggleTrigger.getAttribute('data-target'));
2751
2752 if (target) {
2753 disableScrollLock()
2754 history.back();
2755
2756 if (!target.classList.contains('js-open')) {
2757 toggleTrigger.classList.add('js-open');
2758 target.classList.add('js-open');
2759 target.style.height = `${target.scrollHeight}px`;
2760
2761 if (toggleTrigger.getAttribute('data-action-scroll') != 'no-scroll') {
2762 setTimeout(function() {
2763 target.scrollIntoView({behavior: 'smooth'});
2764 },300);
2765 }
2766
2767 if (target.classList.contains('dialog')) {
2768 document.querySelector('body').style.overflow = 'hidden';
2769 }
2770 } else {
2771 toggleTrigger.classList.remove('js-open');
2772 target.classList.remove('js-open');
2773 target.style.height = null;
2774
2775 if (target.classList.contains('dialog')) {
2776 document.querySelector('body').style.overflow = null;
2777 }
2778 }
2779 }
2780 },
2781 calculateMeters() {
2782 let meters = 0;
2783
2784 this.pickedVariants.forEach(variant => {
2785 let length = variant['length'];
2786
2787 if(this.mainProduct.sizeUnits.length.indexOf('FUß') > -1) {
2788 length = length * 304.8;
2789 }
2790
2791 let variantMeters = parseFloat(length) * variant.qty / 1000;
2792 meters += variantMeters;
2793 })
2794
2795 return parseFloat(meters).toFixed(3);
2796 },
2797 calculatePieces() {
2798 let pieces = 0;
2799
2800 this.pickedVariants.forEach(variant => {
2801 if(variant.bundle) {
2802 variant.productsInBundle.forEach(product => {
2803 pieces += parseInt(product.stock.units);
2804 })
2805 } else {
2806 pieces += parseInt(variant.qty);
2807 }
2808 });
2809
2810 return pieces;
2811 },
2812 calculateSquareMeters() {
2813 return parseFloat(this.calculateMeters() * (this.mainProduct.width / 1000)).toFixed(3);
2814 },
2815 calculateCubicMeters() {
2816 let cubicMeters = 0;
2817
2818 this.pickedVariants.forEach(variant => {
2819 let variantMeters = 0;
2820
2821 let lengthMultiplier = 1;
2822 let widthMultiplier = 1;
2823 let thicknessMultiplier = 1;
2824
2825 if(this.mainProduct.sizeUnits.length.indexOf('FUß') > -1) {
2826 lengthMultiplier = 304.79999025;
2827 }
2828
2829 if(this.mainProduct.sizeUnits.width.indexOf('ZOLL') > -1) {
2830 widthMultiplier = 25.39998628;
2831 }
2832
2833 if(this.mainProduct.sizeUnits.thickness.indexOf('ZOLL') > -1) {
2834 thicknessMultiplier = 25.39998628
2835 }
2836
2837 if(variant.bundle) {
2838 variant.productsInBundle.forEach(product => {
2839 variantMeters += (parseFloat(product.length.replace(",", "") * lengthMultiplier / 1000) * parseFloat(product.thickness * thicknessMultiplier / 1000) * parseFloat(product.width * widthMultiplier) / 1000) * parseInt(product.stock.units);
2840 })
2841 } else {
2842 variantMeters += (parseFloat(variant['length'] / 1000) * parseFloat(variant['thickness'] / 1000) * parseFloat(variant['width']) / 1000) * variant.qty;
2843 }
2844
2845 cubicMeters += variantMeters;
2846 })
2847
2848 return cubicMeters;
2849 },
2850 calculateCubicFeet() {
2851 let cubicFeet = 0;
2852
2853 this.pickedVariants.forEach(variant => {
2854 let variantMeters = 0;
2855
2856 let lengthMultiplier = 1;
2857 let widthMultiplier = 1;
2858 let thicknessMultiplier = 1;
2859
2860 if(this.mainProduct.sizeUnits.length.indexOf('FUß') > -1) {
2861 lengthMultiplier = 304.79999025;
2862 }
2863
2864 if(this.mainProduct.sizeUnits.width.indexOf('ZOLL') > -1) {
2865 widthMultiplier = 25.39998628;
2866 }
2867
2868 if(this.mainProduct.sizeUnits.thickness.indexOf('ZOLL') > -1) {
2869 thicknessMultiplier = 25.39998628
2870 }
2871
2872 if(variant.bundle) {
2873 variant.productsInBundle.forEach(product => {
2874 let lengthMM = product.length.replace(",", "") * lengthMultiplier;
2875 let lengthM = lengthMM / 1000;
2876 let widthMM = product.width * widthMultiplier;
2877 let widthM = widthMM / 1000;
2878 let thicknessMM = product.thickness * thicknessMultiplier;
2879 let thicknessM = thicknessMM / 1000;
2880
2881 variantMeters += Number(parseFloat(lengthM * widthM * thicknessM * 35.32 * product.stock.units))
2882 })
2883 } else {
2884 variantMeters += ((parseFloat(variant['length'] * lengthMultiplier / 1000) * parseFloat(variant['thickness'] * thicknessMultiplier / 1000) * parseFloat(variant['width'] * widthMultiplier / 1000)) * variant.qty);
2885 }
2886
2887 cubicFeet += Number(variantMeters);
2888 })
2889
2890 return Number(cubicFeet).toFixed(2);
2891 },
2892 calculateTotalQTY() {
2893 let qty = 0;
2894
2895 this.pickedVariants.forEach(variant => {
2896 qty += variant.qty;
2897 });
2898
2899 return qty;
2900 },
2901 resetBasket() {
2902 this.showAccessories = false;
2903 this.pickedVariants = [];
2904 this.showStep1 = true;
2905 this.pickedAcc = [];
2906 this.priceObject.unitPrice = 0;
2907 this.priceObject.totalEx = 0;
2908 this.priceObject.vat = 0;
2909 this.priceObject.totalInc = 0;
2910 this.priceObject.corePrice = 0;
2911
2912 Array.from(this.$refs.counter).forEach(counter => {
2913 counter.value = 0;
2914 });
2915 },
2916 async addToBasket() {
2917 this.loading = true;
2918 var params = new FormData();
2919
2920 params.append('CartCmd', "addMulti")
2921
2922 this.pickedVariants.forEach((variant, index) => {
2923 var productLoopCounter = index + 1;
2924
2925 if(variant.bundle) {
2926 params.append('ProductLoopCounter' + productLoopCounter, productLoopCounter);
2927 params.append('ProductID' + productLoopCounter, this.mainProduct.id);
2928 params.append('Quantity' + productLoopCounter, 1);
2929 params.append('EcomOrderLineFieldInput_BundleNo' + productLoopCounter, variant.bundleNo);
2930 } else {
2931 params.append('ProductLoopCounter' + productLoopCounter, productLoopCounter);
2932 params.append('ProductID' + productLoopCounter, this.mainProduct.id);
2933 params.append('VariantID' + productLoopCounter, variant.variantId);
2934 params.append('Quantity' + productLoopCounter, parseInt(variant.qty));
2935 }
2936 })
2937 const config = {
2938 method: 'POST',
2939 body: params
2940 }
2941
2942 this.productsAdded = this.pickedVariants.length;
2943
2944 const response = await fetch('@formAction' + '&redirect=false', config)
2945
2946 if (response.ok) {
2947 dataLayer.push({ ecommerce: null }); // Clear the previous ecommerce object.
2948 dataLayer.push({
2949 event: "add_to_cart",
2950 ecommerce: {
2951 currency: "@GetString("Ecom:Product.Currency.Code")",
2952 value: this.priceObject.totalEx,
2953 items: this.ga4Products
2954 }
2955 });
2956
2957 if(this.accessoriesList.length > 0) {
2958 this.showAccessories = true;
2959 this.loading = false;
2960 this.currentActiveMobileButton = 'order';
2961 } else {
2962 window.location.href = "@formAction";
2963 }
2964
2965 showStep1 = false;
2966 } else {
2967 console.log(response)
2968 }
2969 },
2970 async addAccToBasket() {
2971 this.loading = true;
2972 var params = new FormData();
2973
2974 params.append('CartCmd', "addMulti")
2975
2976 this.pickedAcc.forEach((variant, index) => {
2977 var productLoopCounter = index + 1;
2978
2979 params.append('ProductLoopCounter' + productLoopCounter, productLoopCounter);
2980 params.append('ProductID' + productLoopCounter, variant.id);
2981 params.append('Quantity' + productLoopCounter, variant.qty);
2982 })
2983 const config = {
2984 method: 'POST',
2985 body: params
2986 }
2987
2988 const response = await fetch('@formAction' + '&redirect=false', config)
2989
2990 if (response.ok) {
2991 window.location.href = "@formAction";
2992 } else {
2993 console.log(response)
2994 }
2995 }
2996 },
2997 watch: {
2998 orderLoader(newValue, oldValue) {
2999 if(!newValue && !this.enquireProduct && this.isLoggedIn) {
3000 clearTimeout(this.orderButtonSpinner);
3001 document.querySelector('#product-order-button .product-order-button').style.display = "block";
3002 document.querySelector('#product-order-button .loader').style.display = "none";
3003 }
3004 }
3005 }
3006 });
3007 </script>
3008 @SnippetEnd("JavaScripts")
3009 }
3010
3011 @functions {
3012 private string GetFileIcon(string fileUrl)
3013 {
3014 string extension = Path.GetExtension(fileUrl)?.ToLower();
3015
3016 if (string.IsNullOrEmpty(extension))
3017 return System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/file.svg"));
3018
3019 switch (extension)
3020 {
3021 case ".pdf":
3022 return System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/file.svg"));
3023 case ".jpg":
3024 case ".jpeg":
3025 case ".png":
3026 case ".gif":
3027 case ".webp":
3028 return @System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/image.svg"));
3029 default:
3030 return System.IO.File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath("/files/templates/designs/keflico/assets/svg/product/file.svg"));
3031 }
3032 }
3033
3034 public List<string> GetFilters(string GroupId)
3035 {
3036 List<string> filters = new List<string>();
3037
3038 switch (GroupId)
3039 {
3040 case "group1":
3041 filters.Add("10");
3042 filters.Add("11");
3043 break;
3044 case "group32":
3045 filters.Add("17");
3046 break;
3047 case "group52":
3048 filters.Add("12");
3049 filters.Add("13");
3050 filters.Add("14");
3051 filters.Add("16");
3052 break;
3053 case "group53":
3054 filters.Add("14");
3055 break;
3056 case "group56":
3057 filters.Add("16");
3058 break;
3059 case "group61":
3060 case "group67":
3061 filters.Add("12");
3062 break;
3063 case "group63":
3064 filters.Add("13");
3065 break;
3066 case "group73":
3067 filters.Add("18");
3068 break;
3069 case "group129":
3070 filters.Add("6");
3071 break;
3072 default:
3073 filters.Add("");
3074 break;
3075 }
3076
3077 return filters;
3078 }
3079
3080 public string BuildFilterString(string group) {
3081 string filter = "";
3082 List<string> ids = GetFilters(group);
3083
3084 if(group == "group126") {
3085
3086 } else if(group == "group129") {
3087 foreach(var id in ids) {
3088 filter += filter == "" ? "Types contains \""+id+"\"" : " or Types contains \""+id+"\"";
3089 }
3090 } else {
3091 foreach(var id in ids) {
3092 filter += filter == "" ? "WoodTypes contains \""+id+"\"" : " or WoodTypes contains \""+id+"\"";
3093 }
3094 }
3095
3096 return filter;
3097 }
3098 }
3099