Error executing template "Designs/Tefcold/eCom/ProductCatalog/basic_Pim.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at Tefcold.Web.CustomCode.Razor.ProductViewModelExtensions.GetSpecifications(ProductViewModel product)
   at Tefcold.Web.CustomCode.Extensions.ProductExtensions.GetAsseccoriesList(ProductViewModel viewModel, String shopId)
   at CompiledRazorTemplates.Dynamic.RazorEngine_ea47ccc8302b43968066c1b9bef4c4a9.Execute() in E:\Solutions\Staging\Tefcold.Web\Files\Templates\Designs\Tefcold\eCom\ProductCatalog\basic_Pim.cshtml:line 35
   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.b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @using System.Globalization 2 @using NLWI.Platforms.Dynamicweb9.Specs 3 @using NLWI.Core.Factory 4 @using System.Linq; 5 @using System.Text.RegularExpressions 6 @using Dynamicweb.Ecommerce.International 7 @using Dynamicweb.Ecommerce.ProductCatalog 8 @using Dynamicweb.Ecommerce.Products 9 @using Dynamicweb.Ecommerce.Stocks 10 @using Dynamicweb.Security.UserManagement 11 @using NORRIQ.Common8.Ecom 12 @using Newtonsoft.Json 13 @using Newtonsoft.Json.Serialization 14 @using NORRIQ.SalesPersonLogin.Services 15 @using NORRIQ.Seo.Canonical 16 @using Tefcold.Web.CustomCode.AsyncProductList.Models 17 @using Tefcold.Web.CustomCode.Extensions 18 @using Tefcold.Web.CustomCode.Items 19 @using Tefcold.Web.CustomCode.Items.Properties 20 @using Tefcold.Web.CustomCode.Items.Settings 21 @*@using Tefcold.Web.CustomCode.ProductHelper*@ 22 @using Tefcold.Web.CustomCode.Razor 23 @using Tefcold.Web.CustomCode.Stocks 24 @using Tefcold.Web.CustomCode.Stocks.Helpers 25 @inherits Tefcold.Web.CustomCode.Razor.TefcoldViewModelTemplate<Dynamicweb.Ecommerce.ProductCatalog.ProductViewModel> 26 @{ 27 var websiteSettings = Pageview.Area.Item.ToCodeFirstItem<Websites>();// Dynamicweb.Services.Items.GetItem(Pageview.Area.ItemType, Pageview.Area.ItemId).ToCodeFirstItem<Websites>(); 28 29 var stockInformation = StockLocationHelper.GetShopStockInformation(Pageview.ID); 30 31 //Dynamicweb.Ecommerce.Services.StockService.GetStockUnits("34024-at-SHOP2", ""); 32 //var stockInformation = StockLocationHelper.GetShopStockInformation(Pageview.ID); 33 var variantId = System.Web.HttpContext.Current.Request.QueryString["VariantID"]; 34 var selectedModel = (!string.IsNullOrEmpty(variantId) ? Model.Variants?.FirstOrDefault(a => string.Equals(a.VariantId, variantId)) : null) ?? Model; 35 var accessories = selectedModel.GetAsseccoriesList(Pageview.Area.EcomShopId); 36 var relatedProducts = Model.GetProductRelationGroup("Related Products");// Configuration 37 var perfionImageNames = new string[] { "PrimaryImage", "DetailImage1", "DetailImage2", "BrandedImage", "PackedImage", "OtherImages", "WithContentImage", "OpenImage", "ImageRange", "ImageOnLocation","StorageImages" }; 38 //var specsToList = new HashSet<string>() { "Fitting", "Features", "USP", "Gender", "Season", "Year" }; @*Leave empty for all *@ 39 40 var remoteStock = StockUnitHelper.GetRemoteStock(selectedModel, Pageview, websiteSettings.ExternalShopIds); 41 42 var inspirationGroupIds = websiteSettings.InspirationGroupIds ?? new List<string>(); 43 selectedModel.StockUnits = selectedModel.StockUnits.GetShopStocks(Pageview.Area.EcomShopId).ToList(); 44 45 FieldValueViewModel youtubeIDfield; 46 selectedModel.ProductFields.TryGetValue("YoutubeId", out youtubeIDfield); 47 string youtubeID = youtubeIDfield?.Value?.ToString(); 48 var hasVideo = !string.IsNullOrEmpty(youtubeID); 49 50 youtubeID = selectedModel.GetSpecifications().GetByKey("YouTubeURL").Value; 51 52 var convertedSelectedModel = new AsyncProductWithSpecification(new SimpleProduct(selectedModel, null, stockInformation, inspirationGroupIds, websiteSettings.ExternalShopIds, true)); 53 convertedSelectedModel.Product.DefaultPrice.CurrencyCode = Pageview.Area.EcomCurrencyId; 54 var convertedMasterModel = new AsyncProductWithSpecification(new SimpleProduct(Model, null, stockInformation, inspirationGroupIds, websiteSettings.ExternalShopIds, true)); 55 56 var selectedJsonModel = JsonConvert.SerializeObject(convertedSelectedModel, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); 57 var selectedMasterProductModel = JsonConvert.SerializeObject(convertedMasterModel, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); 58 selectedMasterProductModel = selectedMasterProductModel.Replace("'", "&#39;"); 59 selectedJsonModel = selectedJsonModel.Replace("'", "&#39;"); 60 61 string asyncPrefix = "Async "; 62 var userInTefcoldUserGroup = ImpersonationService.IsCurrentlyImpersonating(); 63 FieldValueViewModel isSpareField; 64 selectedModel.ProductFields.TryGetValue("IsSparePart", out isSpareField); 65 var isSparePart = (bool)isSpareField.Value; 66 67 var product = Dynamicweb.Ecommerce.Services.Products.GetProductById(Model.Id, Model.VariantId, Model.LanguageId); 68 69 var productIsBlocked = product != null && !product.Active; 70 71 //Used to determine whether or not to show phdCode 72 73 if (isSparePart) 74 { 75 76 Pageview.Meta.AddTag("robots", "noindex,nofollow"); 77 } 78 79 // Specs 80 var specs = ProductViewModelExtensions.GetSpecifications(selectedModel); 81 var images = perfionImageNames.SelectMany(a => specs.GetAllByKey(a)).ToList(); 82 var imageAlt = specs.GetByKey("ProductName"); 83 84 var ecoIcon = specs.GetByKey("EcoIcon"); 85 86 var trueString = true.ToString().ToLower(); 87 var czBrandName = specs.GetByKey("BrandNameCZ"); 88 string basicPimPrefix = "PDP "; 89 var languageId = Model.LanguageId; 90 91 var productService = ObjectFactory.GetInstance<ProductService>(); 92 LanguageService languageService = new LanguageService(); 93 //ProductFields 94 95 DateTime result; 96 string earliestHarborArrival = selectedModel.ProductFields.FirstOrDefault(f => f.Value.SystemName == "EarliestArrivalFromHarbor").Value?.Value?.ToString() ?? string.Empty; 97 98 if (DateTime.TryParseExact(earliestHarborArrival, "yyyy-mm-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out result)) 99 { 100 var earliestArrivalTranslateString = Translate(basicPimPrefix + "stock arriving soon. Due", "Stock arriving soon. Due"); 101 earliestHarborArrival = result.ToString("dd/mm/yyyy"); 102 earliestHarborArrival = earliestArrivalTranslateString + " " + earliestHarborArrival; 103 } 104 105 //websiteSettings = Pageview.GetWebsiteSettings(); 106 string shortSellingText = specs.GetByKey("SellingTextShort")?.Value; 107 string energyArrow = specs.GetByKey("EnergyArrow")?.Value; 108 string energyLabel = specs.GetByKey("EnergyLabel")?.Value; 109 var marketingMessage = specs.GetByKey("MarketingMessage")?.Value; 110 111 var stickerImage = Model.GetStickerImage(); 112 string netVolumeEnergyRating = specs.GetByKey("NetVolumeEnergyRating")?.Value; 113 string totalDisplayArea = specs.GetByKey("TotalDisplayArea")?.Value; 114 var standardCustomer = Pageview.AreaSettings.GetString("StandardCustomer"); 115 standardCustomer = string.IsNullOrEmpty(standardCustomer) ? "" : standardCustomer; 116 string detailImage1Text = specs.GetByKey("DetailImage1Text")?.Value; 117 string detailImage2Text = specs.GetByKey("DetailImage2Text")?.Value; 118 } 119 <product-details-simple-pim :product='@selectedJsonModel' 120 :images='@Newtonsoft.Json.JsonConvert.SerializeObject(images.Select(a => a.Value))' 121 inline-template 122 language-id="@Model.LanguageId"> 123 <div class="basic_pim" v-bind:class="{'initialized': initialized }"> 124 <section class="basic_pim-pdp" itemscope="" itemtype="https://schema.org/Product"> 125 <div class="basic_pim-media"> 126 <div class="@(images.Count() > 1 ? "basic_pim-pictos thumbs" : "basic_pim-pictos")"> 127 <div class="stickers"> 128 @if (!string.IsNullOrEmpty(stickerImage)) 129 { 130 <img src="/Admin/Public/GetImage.ashx?Height=@TefcoldParagraphSettings.StickHeightDetails&amp;Compression=85&amp;Image=@stickerImage" alt="@Translate(basicPimPrefix + "Sticker", "Sticker")" class="img-fluid"/> 131 } 132 @if (websiteSettings.DiscountFormat != null) 133 { 134 <span v-if="ShowDiscount" class="sticker discount"> 135 -{{discount}}% 136 </span> 137 } 138 139 </div> 140 @if (!string.IsNullOrEmpty(ecoIcon?.Value)) 141 { 142 <img src="@(ecoIcon?.Value)" alt="@Translate(basicPimPrefix + "eco product", "Eco product")" class="img-fluid" style="margin-left:auto;" /> 143 } 144 145 </div> 146 <gallery :items="images" 147 :index="index" 148 @@close="index = null"> 149 </gallery> 150 <template v-if="images.length > 1"> 151 <slick ref="slick" 152 class="basic_pim-thumbs" 153 id="pdp-thumbs" 154 :options="slickPimOptionsThumbs"> 155 <figure v-for="thumb in images" class="basic_pim-thumb"> 156 <img :src="'/Admin/Public/GetImage.ashx?Width=50&amp;Height=50&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;fillcanvas=True&amp;Image=' + thumb" 157 alt="@selectedModel.Name" 158 class="img-fluid" /> 159 </figure> 160 @if (!string.IsNullOrEmpty(youtubeID)) 161 { 162 <figure class="basic_pim-thumb"> 163 <svg x="0px" y="0px" 164 width="48" height="48" 165 viewBox="0 0 48 48"> 166 <path fill="#FF3D00" d="M43.2,33.9c-0.4,2.1-2.1,3.7-4.2,4c-3.3,0.5-8.8,1.1-15,1.1c-6.1,0-11.6-0.6-15-1.1c-2.1-0.3-3.8-1.9-4.2-4C4.4,31.6,4,28.2,4,24c0-4.2,0.4-7.6,0.8-9.9c0.4-2.1,2.1-3.7,4.2-4C12.3,9.6,17.8,9,24,9c6.2,0,11.6,0.6,15,1.1c2.1,0.3,3.8,1.9,4.2,4c0.4,2.3,0.9,5.7,0.9,9.9C44,28.2,43.6,31.6,43.2,33.9z"></path> 167 <path fill="#FFF" d="M20 31L20 17 32 24z"></path> 168 </svg> 169 </figure> 170 } 171 172 </slick> 173 <slick ref="slick" 174 class="basic_pim-images" 175 id="pdp-images" 176 :options="slickPimOptionsImages"> 177 <figure class="basic_pim-image" 178 v-for="(image, imageIndex) in images" 179 :key="imageIndex" 180 @@click="setIndex(imageIndex)" 181 title="@Translate(basicPimPrefix + "show image", "Show image")"> 182 <picture> 183 <source media="(max-width:767.98px)" :srcset="'/Admin/Public/GetImage.ashx?Width=400&amp;Height=400&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;fillcanvas=True&amp;Image=' + image"> 184 <source media="(max-width:991.98px)" :srcset="'/Admin/Public/GetImage.ashx?Width=530&amp;Height=530&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;fillcanvas=True&amp;Image=' + image"> 185 <img :src="'/Admin/Public/GetImage.ashx?Width=530&amp;Height=530&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;fillcanvas=True&amp;Image=' + image" 186 alt="@selectedModel.Name" 187 class="img-fluid" 188 itemprop="image" /> 189 </picture> 190 @if (!string.IsNullOrEmpty(detailImage1Text) || !string.IsNullOrEmpty(detailImage2Text)) 191 { 192 <figcaption class="alert bg-white" v-if="imageIndex < 3"> 193 @if (!string.IsNullOrEmpty(detailImage1Text)) 194 { 195 <template v-if="imageIndex == 1"> 196 @detailImage1Text 197 </template> 198 } 199 @if (!string.IsNullOrEmpty(detailImage2Text)) 200 { 201 <template v-if="imageIndex == 2"> 202 @detailImage2Text 203 </template> 204 } 205 </figcaption> 206 } 207 </figure> 208 @if (!string.IsNullOrEmpty(youtubeID)) 209 { 210 <figure :key="images.Count" 211 @@click="setIndex(images.Count)" 212 title="@Translate(basicPimPrefix + "show image", "Show image")"> 213 <div> 214 <youtube-embed-lite vid="@youtubeID" thumb-quality="hq" class="embed-responsive-item" /> 215 </div> 216 </figure> 217 } 218 219 220 </slick> 221 </template> 222 <template v-if="images.length == 1"> 223 <div class="basic_pim-images"> 224 <figure class="basic_pim-image" 225 v-for="(image, imageIndex) in images" 226 :key="imageIndex" 227 @@click="setIndex(imageIndex)" 228 title="@Translate(basicPimPrefix + "show image", "Show image")"> 229 <picture> 230 <source media="(max-width:767.98px)" :srcset="'/Admin/Public/GetImage.ashx?Width=300&amp;Height=250&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;fillcanvas=True&amp;Image=' + image"> 231 <source media="(max-width:991.98px)" :srcset="'/Admin/Public/GetImage.ashx?Width=400&amp;Height=350&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;fillcanvas=True&amp;Image=' + image"> 232 <img :src="'/Admin/Public/GetImage.ashx?Width=427&amp;Height=427&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;fillcanvas=True&amp;Image=' + image" 233 alt="@selectedModel.Name" 234 class="img-fluid" 235 itemprop="image"> 236 </picture> 237 @if (!string.IsNullOrEmpty(detailImage1Text) || !string.IsNullOrEmpty(detailImage2Text)) 238 { 239 <figcaption class="alert bg-white"> 240 @if (!string.IsNullOrEmpty(detailImage1Text)) 241 { 242 <template v-if="imageIndex == 1"> 243 @detailImage1Text 244 </template> 245 } 246 @if (!string.IsNullOrEmpty(detailImage2Text)) 247 { 248 <template v-if="imageIndex == 2"> 249 @detailImage2Text 250 </template> 251 } 252 </figcaption> 253 } 254 </figure> 255 </div> 256 </template> 257 <template v-if="images.length == 0"> 258 @{ 259 var pdpImage = "/Files/Images/default.jpg"; 260 } 261 <div class="basic_pim-image"> 262 <picture class="basic_pim-image"> 263 <source media="(max-width:1199.98px)" srcset="/Admin/Public/GetImage.ashx?Width=630&amp;Height=630&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;Image=@(pdpImage)"> 264 <source media="(max-width:991.98px)" srcset="/Admin/Public/GetImage.ashx?Width=530&amp;Height=530&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;Image=@(pdpImage)"> 265 <source media="(max-width:767.98px)" srcset="/Admin/Public/GetImage.ashx?Width=400&amp;Height=400&amp;Compression=85&amp;Crop=5&amp;Format=webp&amp;Quality=85&amp;Image=@(pdpImage)"> 266 <img src="@(pdpImage)" 267 alt="@Translate(basicPimPrefix + "No product picture", "No product picture")" 268 class="img-fluid" 269 itemprop="image"> 270 </picture> 271 </div> 272 </template> 273 </div> 274 <div class="basic_pim-content"> 275 <header> 276 <h1 itemprop="name"> 277 @selectedModel.Name 278 </h1> 279 <p itemprop="category">@(selectedModel?.ShortDescription ?? "")</p> 280 </header> 281 @if (specs.GetAllByKey("BulletPoints").Any()) 282 { 283 <ul class="basic_pim-specs"> 284 @foreach (var bp in specs.GetAllByKey("BulletPoints")) 285 { 286 <li> 287 @bp.Value 288 </li> 289 } 290 </ul> 291 } 292 293 @* 294 <template name="item-stock-state" v-if="stockLocationState!=0"> 295 <p :class="'stock out-of-stock'" v-if="stockLocationState==5"> 296 <link itemprop="availability" href="http://schema.org/SoldOut" /> 297 @Translate(asyncPrefix + "Out Of Stock", "Out Of Stock") 298 </p> 299 <p :class="'stock few-in-stock'" v-if="stockLocationState==7"> 300 <link itemprop="availability" href="http://schema.org/LimitedAvailability" /> 301 @Translate(asyncPrefix + "Few In Stock", "Few In Stock") 302 </p> 303 <p :class="'stock in-stock'" v-if="stockLocationState==8"> 304 <link itemprop="availability" href="http://schema.org/InStock" /> 305 @Translate(asyncPrefix + "In Stock", "In Stock") 306 </p> 307 </template> 308 *@ 309 310 @if (!string.IsNullOrEmpty(marketingMessage) && Pageview.IsAllowedToShop()) 311 { 312 <span class="basic_pim-marketing-message">@marketingMessage</span> 313 } 314 315 @if (Pageview.IsAllowedToShop() && !productIsBlocked) 316 { 317 <stock-location-component inline-template :remote-stock-shop-ids='@JsonConvert.SerializeObject(websiteSettings.ExternalShopIds)' not-in-stock-text="@Translate(basicPimPrefix + "not in stock text", "N/A")" :default-stock-units='product.product.stockUnits' :default-remote-stock-units='@Newtonsoft.Json.JsonConvert.SerializeObject(remoteStock)' :product='product' earliest-harbor-arrival-date="@earliestHarborArrival"> 318 <div class="basic_pim-stocks"> 319 <template v-if="stockUnits.length > 0 && !loading"> 320 <div v-for="unit in stockUnits" class="custom-control custom-radio"> 321 <span style="font-size: 1px">{{unit.quantity}}</span> 322 <input type="radio" v-model="selectedVal" name="stocks" :id="unit.stockLocation.name" :value="unit.stockLocation.name" class="custom-control-input" :disabled="unit.quantity <=0 || getStockLocation!=''" :checked="getStockLocation == unit.stockLocation.name"> 323 <label v-if="!@userInTefcoldUserGroup.ToString().ToLower()" :for="unit.stockLocation.name" class="custom-control-label"> 324 {{ unit.stockLocation.description }} {{ GetStockAmountString(unit.quantity) }} @Translate("PDP In Stock", "In Stock") 325 <template v-if="stocksHasNoQuantity"> 326 <br/><span style="font-size: small;">{{earliestHarborArrivalDate}}</span> 327 </template> 328 </label> 329 <label v-else :for="unit.stockLocation.name" class="custom-control-label"> 330 {{ unit.stockLocation.description }} {{ unit.quantity }} @Translate("PDP In Stock", "In Stock") 331 <template v-if="stocksHasNoQuantity"> 332 <br/><span style="font-size: small;">{{earliestHarborArrivalDate}}</span> 333 </template> 334 </label> 335 </div> 336 <br/> 337 </template> 338 <template v-else-if="loading"> 339 <span class="spinner-sm-default"></span> 340 </template> 341 <template v-if="remoteStockUnits.length > 0 && !loading"> 342 <div v-for="unit in remoteStockUnits" class="custom-control"> 343 <span style="font-size: 1px">{{unit.Quantity}}</span> 344 @*<input type="radio" v-model="selectedVal" name="stocks" :id="unit.StockLocation.Description" :value="unit.StockLocation.Description" class="custom-control-input" :disabled="true">*@ 345 @*<label v-if="!@userInTefcoldUserGroup.ToString().ToLower()" :for="unit.StockLocation.Description" class="custom-control-label">{{ unit.StockLocation.Description }} {{ GetStockAmountString(unit.Quantity) }} @Translate("PDP In Stock", "In Stock")</label>*@ 346 <label v-if="!@userInTefcoldUserGroup.ToString().ToLower()" :for="unit.StockLocation.Description" class=""> 347 {{ unit.StockLocation.Description }} {{ GetStockAmountString(unit.Quantity) }} @Translate("PDP In Stock", "In Stock") 348 <br /><span v-if="unit.Quantity > 0" class="remotestock">@Translate("Back In Stock Again Text", "Stock due on")</span> 349 </label> 350 <label v-else :for="unit.StockLocation.Description" class="custom-control"> 351 {{ unit.StockLocation.Description }} {{ unit.Quantity }} @Translate("PDP In Stock", "In Stock") 352 <br/><span v-if="unit.Quantity > 0" class="remotestock">@Translate("Back In Stock Again Text", "Stock due on")</span> 353 </label> 354 355 </div> 356 </template> 357 </div> 358 </stock-location-component> 359 } 360 @if (!Pageview.IsAllowedToShop() || productIsBlocked) 361 { 362 <buying-component inline-template :initial-product='@selectedMasterProductModel' :selected-product='@selectedMasterProductModel'> 363 <div class="basic_pim-buying"> 364 365 @if (!string.IsNullOrEmpty(energyArrow)) 366 { 367 string name = Regex.Replace(selectedModel.Name.Trim(), "[^A-Za-z0-9_. ]+", ""); 368 var lang = languageService.GetLanguage(selectedModel.LanguageId)?.Code2; 369 //var lang = languageService.GetLanguage(selectedModel.LanguageId)?.Code2; 370 371 //string filePattern = $"[[type]]-{selectedModel.Number}-{name}-{lang}"; 372 <div class="pdp-energy"> 373 <div class="pdp-energy-data"> 374 <a href="@energyLabel" target="_blank" class="pdp-energy-label"> 375 <img src="/Admin/Public/GetImage.ashx?Height=40&amp;Crop=5&amp;Image=@energyArrow" /> 376 </a> 377 378 379 @{ string filePattern = $"[[type]]-{selectedModel.Number}-{name}-{lang}"; } 380 381 @if (!string.IsNullOrEmpty(@specs.GetByKey("prodsheets").Value)) 382 { 383 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("prodsheets").Value','@filePattern.Replace("[[type]]", "ProductSheet")','ProductSheet')" target="_blank"> 384 @Translate(basicPimPrefix + "product sheet", "Product Sheet") 385 386 </a> 387 } 388 </div> 389 </div> 390 } 391 392 <ul class="basic_pim-variants" v-if="initialProduct.product.simpleVariants && initialProduct.product.simpleVariants.length > 0"> 393 <li> 394 @{ 395 FieldValueViewModel productImg; 396 FieldValueViewModel productColor; 397 Model.ProductFields.TryGetValue("productVariantColorImage", out productImg); 398 Model.ProductFields.TryGetValue("productVariantValue", out productColor); 399 } 400 <a href="Default.aspx?ID=@Pageview.ID&ProductId=@Model.Id" class="@(Model.Number == selectedModel.Number ? "active" : "")" :style="getImageOrColor('@(productImg?.Value)','@(productColor?.Value)')"></a> 401 </li> 402 403 @if (Model.Variants != null) 404 { 405 foreach (var variant in Model.Variants) 406 { 407 FieldValueViewModel variantImg; 408 FieldValueViewModel variantColor; 409 variant.ProductFields.TryGetValue("productVariantColorImage", out variantImg); 410 variant.ProductFields.TryGetValue("productVariantValue", out variantColor); 411 412 <li> 413 <a href="/Default.aspx?ID=@Pageview.ID&ProductId=@variant.Id&VariantId=@variant.VariantId" class="@(variant.Number == selectedModel.Number ? "active" : "")" :style="getImageOrColor('@(variantImg?.Value)','@(variantColor?.Value)')"></a> 414 </li> 415 416 } 417 } 418 </ul> 419 </div> 420 </buying-component> 421 <p itemprop="sku"> 422 @Translate(basicPimPrefix + "Product number", "Product number"): @selectedModel.Number @(string.IsNullOrEmpty(selectedModel.GetNavItemNumber()) ? "" : "("+Translate("Substition for","Substitution for ")+ $"{selectedModel.GetNavItemNumber()})") 423 </p> 424 <a href="@NORRIQ.Common8.Razor.Navigation.GetUrlByNavigationTag("contact")" class="btn btn-outline-secondary btn-sm mt-3"> 425 @Translate("create account", "Create account") 426 </a> 427 } 428 else 429 { 430 <buying-component inline-template @@discount="onDiscount($event)" :initial-product='@selectedMasterProductModel' :selected-product='@selectedMasterProductModel' :chosen-warranty-code="chosenWarrantyCode" :warranty-info="warrantyInfo"> 431 <div class="basic_pim-buying" itemprop="offers" itemscope="" itemtype="https://schema.org/Offer"> 432 <div class="pdp-energy"> 433 <async-price class-type="asyncprice-pdp" 434 :product='@selectedJsonModel' 435 :default-price="@selectedModel.Price.PriceWithoutVat.ToString(CultureInfo.InvariantCulture)" 436 :only-standard-price="@(Pageview.IsCurrentlyB2C().ToString().ToLower())" 437 list-price="true" 438 :should-emit-warranties="true" 439 language-id="@languageId" 440 standard-customer="@standardCustomer" 441 @@discount="onDiscount($event)"> 442 </async-price> 443 @if (!string.IsNullOrEmpty(energyArrow)) 444 { 445 446 447 string name = Regex.Replace(selectedModel.Name.Trim(), "[^A-Za-z0-9_. ]+", ""); 448 var lang = languageService.GetLanguage(selectedModel.LanguageId)?.Code2; 449 string filePattern = $"[[type]]-{selectedModel.Number}-{name}-{lang}"; 450 451 452 <div class="pdp-energy-data"> 453 <a href="@energyLabel" target="_blank" class="pdp-energy-label"> 454 <img src="/Admin/Public/GetImage.ashx?Height=40&amp;Crop=5&amp;Image=@energyArrow" /> 455 </a> 456 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("prodsheets").Value','@filePattern.Replace("[[type]]", "ProductSheet")','ProductSheet')" target="_blank" class="pdp-energy-link"> 457 458 @Translate(basicPimPrefix + "product sheet", "Product Sheet") 459 460 </a> 461 </div> 462 } 463 </div> 464 <ul class="basic_pim-variants" v-if="initialProduct.product.simpleVariants && initialProduct.product.simpleVariants.length > 0"> 465 <li> 466 @{ 467 FieldValueViewModel productImg; 468 FieldValueViewModel productColor; 469 Model.ProductFields.TryGetValue("productVariantColorImage", out productImg); 470 Model.ProductFields.TryGetValue("productVariantValue", out productColor); 471 } 472 <a href="Default.aspx?ID=@Pageview.ID&ProductId=@Model.Id" class="@(Model.Number == selectedModel.Number ? "active" : "")" :style="getImageOrColor('@(productImg?.Value)','@(productColor?.Value)')"></a> 473 </li> 474 475 @if (Model.Variants != null) 476 { 477 foreach (var variant in Model.Variants) 478 { 479 FieldValueViewModel variantImg; 480 FieldValueViewModel variantColor; 481 variant.ProductFields.TryGetValue("productVariantColorImage", out variantImg); 482 variant.ProductFields.TryGetValue("productVariantValue", out variantColor); 483 484 <li> 485 <a href="/Default.aspx?ID=@Pageview.ID&ProductId=@variant.Id&VariantId=@variant.VariantId" class="@(variant.Number == selectedModel.Number ? "active" : "")" :style="getImageOrColor('@(variantImg?.Value)','@(variantColor?.Value)')"></a> 486 </li> 487 488 } 489 } 490 </ul> 491 <div class="pdp-btn-group"> 492 <add-to-basket-simple class="addtobasketsimple-pdp" 493 :product='@selectedJsonModel' 494 :price-without-vat="currentItemPriceWithoutVat" 495 button-class="btn btn-primary" 496 :group-warranty-code="chosenWarrantyCode" 497 :warranty-info="warrantyInfo" 498 :unit-of-measure="'PCS'" 499 language-id="@languageId" 500 :only-spare-parts="@((Pageview.User.OnlySpareParts() && !isSparePart).ToString().ToLower())" 501 :is-marketing-user="@(Pageview.User.OnlyView().ToString().ToLower())" 502 :ishvasuser="@(Pageview.User.IsHVACUser().ToString().ToLower())" 503 standard-customer="@standardCustomer"> 504 </add-to-basket-simple> 505 @if (Pageview.IsCurrentlyB2B()) 506 { 507 <favorite-lists ui-error-message-translation="@Translate(basicPimPrefix + " Error while retrieving favorite list", "Error while retrieving favorite list")" :is-favorite-mode="@NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("favorites") == @Pageview.ID" :product='@selectedJsonModel'></favorite-lists> 508 } 509 <add-to-compare :product-number="selectedProduct.product.number"></add-to-compare> 510 </div> 511 </div> 512 </buying-component> 513 <p itemprop="sku"> 514 @Translate(basicPimPrefix + "Product number", "Product number"): @selectedModel.Number @(string.IsNullOrEmpty(selectedModel.GetNavItemNumber()) ? "" : "(" + Translate("Substition for", "Substitution for ") + $"{selectedModel.GetNavItemNumber()})") 515 516 </p> 517 518 if (Pageview.IsCZShop() && czBrandName != null && !string.IsNullOrWhiteSpace(czBrandName.Value)) 519 { 520 <p class="phdCode"> 521 @Translate(basicPimPrefix + "Brand name", "Brand"): @czBrandName.Value 522 </p> 523 } 524 525 if (Pageview.IsCZShop() && !string.IsNullOrEmpty(specs.GetByKey("PhdCode")?.Value)) 526 { 527 <p class="phdCode">@Translate(basicPimPrefix + "PhdCode", "PhdCode") @(specs.GetByKey("PhdCode")?.Value)</p> 528 } 529 if (!isSparePart && (Pageview.IsCurrentlyB2B() && Pageview.User.AllowWarranty() || Pageview.IsCurrentlyB2C())) 530 { 531 <div class="basic_pim-warranty" v-if="@((!isSparePart).ToString().ToLower()) && warranties?.length>0"> 532 <div v-for="(warranty,index) in warranties" class="custom-control custom-radio"> 533 <input type="radio" name="warranty" :id="'warranty' + index" v-model="chosenWarranty" :value="warranty" class="custom-control-input" /> 534 <label :for="'warranty' + index" class="custom-control-label"> 535 {{getDescription(warranty.itemNo) +' - ' + product.product.defaultPrice.currencyCode + ' ' + warranty.price.priceWithoutVat + ',-'}} 536 </label> 537 </div> 538 @*<template v-if="warrantyLoading"> 539 <div class="basic_listview-loader text-center">http://localhost:55277/http://localhost:55277/ 540 <span class="spinner-lg-default"></span> 541 </div> 542 </template>*@ 543 </div> 544 } 545 } 546 @if (isSparePart && specs.GetByGroup("NIQSpecifications").Any()) 547 { 548 <ul class="list-unstyled spare-specs mt-3"> 549 @foreach (var group in specs.GetByGroup("NIQSpecifications").Where(x => x.Key != "EcoIcon").OrderBy(x => x.Group2Order).ThenBy(x => x.ValueSortOrder).GroupBy(x => x.Group2)) 550 { 551 552 553 foreach (var spec in group) 554 { 555 556 <li> 557 558 <span>@spec.Caption</span> 559 <span> 560 @spec.Value 561 @spec.Unit 562 </span> 563 </li> 564 } 565 566 } 567 </ul> 568 } 569 </div> 570 </section> 571 @if (!isSparePart) 572 { 573 <section class="basic_pim-collapse"> 574 @if (!string.IsNullOrEmpty(selectedModel.LongDescription) || !string.IsNullOrEmpty(shortSellingText) || specs.GetByGroup("NIQSpecifications").Any()) 575 { 576 <div class="basic_pim-col" visible id="specs1"> 577 @if (!string.IsNullOrEmpty(selectedModel.LongDescription) || !string.IsNullOrEmpty(shortSellingText)) 578 { 579 <button class="btn-collapse" id="description" v-b-toggle.long-description> 580 @Translate(basicPimPrefix + "product description", "Product description") 581 </button> 582 <b-collapse id="long-description" appear accordion="specs1"> 583 <template> 584 <div class="body-collapse"> 585 @if (!string.IsNullOrEmpty(shortSellingText)) 586 { 587 <p>@shortSellingText</p> 588 } 589 @if (!string.IsNullOrEmpty(selectedModel.LongDescription)) 590 { 591 <p>@selectedModel.LongDescription</p> 592 } 593 </div> 594 </template> 595 </b-collapse> 596 } 597 @if (specs.GetByGroup("NIQSpecifications").Any()) 598 { 599 <button class="btn-collapse" id="specs" v-b-toggle.specs-list> 600 @Translate(basicPimPrefix + "Product Specs", "Product Specifications") 601 </button> 602 <b-collapse id="specs-list" accordion="specs1"> 603 <template> 604 <div class="body-collapse full"> 605 <table class="table table-specs"> 606 607 <tbody> 608 609 @foreach (var group in specs.GetByGroup("NIQSpecifications").Where(x => x.Key != "EcoIcon").OrderBy(x => x.Group2Order).ThenBy(x => x.ValueSortOrder).GroupBy(x => x.Group2)) 610 { 611 var test = specs; 612 613 <tr> 614 <th>@group.Key</th> 615 <th></th> 616 </tr> 617 foreach (var spec in group) 618 { 619 if (spec.Key == "EnergyArrow") 620 { 621 continue; 622 } 623 if (spec.Key == "EnergyArrowText" && !string.IsNullOrEmpty(energyArrow)) 624 { 625 <tr> 626 <td> 627 @spec.Caption 628 </td> 629 <td valign="middle" style="vertical-align:middle;"> 630 <a href="@energyLabel" target="_blank" style="display:flex;"> 631 <img src="/Admin/Public/GetImage.ashx?Height=18&amp;Crop=5&amp;Image=@energyArrow" /> 632 </a> 633 </td> 634 </tr> 635 } 636 else 637 { 638 <tr> 639 <td> 640 @spec.Caption 641 </td> 642 <td valign="middle" style="vertical-align:middle;"> 643 @spec.Value 644 @spec.Unit 645 </td> 646 </tr> 647 } 648 } 649 } 650 <tr> 651 <th></th> 652 <th></th> 653 </tr> 654 </tbody> 655 </table> 656 657 </div> 658 </template> 659 </b-collapse> 660 } 661 </div> 662 } 663 <div class="basic_pim-col" id="specs2"> 664 665 <button class="btn-collapse" id="download" v-b-toggle.download-documents> 666 @Translate(basicPimPrefix + "downloads", "Downloads") 667 </button> 668 <b-collapse id="download-documents" accordion="specs2"> 669 <template> 670 <div class="body-collapse"> 671 <ul class="basic_pim-downloads"> 672 @{ 673 674 string name = Regex.Replace(selectedModel.Name.Trim(), "[^A-Za-z0-9_. ]+", ""); 675 var lang = languageService.GetLanguage(selectedModel.LanguageId)?.Code2; 676 string filePattern = $"[[type]]-{selectedModel.Number}-{name}-{lang}"; } 677 678 @if (!string.IsNullOrEmpty(@specs.GetByKey("prodsheets").Value)) 679 { 680 <li> 681 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("prodsheets").Value','@filePattern.Replace("[[type]]", "ProductSheet")','ProductSheet')" target="_blank"> 682 <svg> 683 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 684 </svg> 685 @Translate(basicPimPrefix + "product sheet", "Product Sheet") 686 </a> 687 </li> 688 } 689 @if (!string.IsNullOrEmpty(@specs.GetByKey("Usermanual").Value)) 690 { 691 <li> 692 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("Usermanual").Value','@filePattern.Replace("[[type]]", "Usermanual")','Usermanual')" target="_blank"> 693 <svg> 694 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 695 </svg> 696 @Translate(basicPimPrefix + "User manual", "User manual") 697 </a> 698 </li> 699 } 700 @if (!string.IsNullOrEmpty(@specs.GetByKey("SparePartsBC").Value)) 701 { 702 <li> 703 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("SparePartsBC").Value','@filePattern.Replace("[[type]]","SparePartsBC")','SparePartsBC')" target="_blank"> 704 <svg> 705 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 706 </svg> 707 @Translate(basicPimPrefix + basicPimPrefix + "spare part list", "Spare part list") 708 </a> 709 </li> 710 } 711 @if (!string.IsNullOrEmpty(energyLabel)) 712 { 713 <li> 714 <a href="#" v-on:click="downloadProductFile($event,'@name','@energyLabel','@filePattern.Replace("[[type]]","EnergyClassification")','EnergyClassification')" target="_blank"> 715 <svg> 716 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 717 </svg> 718 @Translate(basicPimPrefix + "Energy Classification", "Energy Classification") 719 </a> 720 </li> 721 } 722 @if (!string.IsNullOrEmpty(@specs.GetByKey("HVACSpecs").Value)) 723 { 724 <li> 725 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("HVACSpecs").Value','@filePattern.Replace("[[type]]","HVACSpecs")','Drawings')" target="_blank"> 726 <svg> 727 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 728 </svg> 729 @Translate(basicPimPrefix + "HVACSpecs", "HVAC Specs") 730 </a> 731 </li> 732 } 733 @if (Pageview.User != null && Pageview.User.AllowDownloadDocuments()) 734 { 735 if (!string.IsNullOrEmpty(specs.GetByKey("WiringDiagrams").Value)) 736 { 737 <li> 738 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("WiringDiagrams").Value','@filePattern.Replace("[[type]]","WiringDiagrams")','WiringDiagrams')" target="_blank"> 739 <svg> 740 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 741 </svg> 742 @Translate(basicPimPrefix + "Wiring diagram", "Wiring diagram") 743 </a> 744 </li> 745 } 746 if (!string.IsNullOrEmpty(specs.GetByKey("Drawings").Value)) 747 { 748 <li> 749 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("Drawings").Value','@filePattern.Replace("[[type]]","Drawings")','Drawings')" target="_blank"> 750 <svg> 751 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 752 </svg> 753 @Translate(basicPimPrefix + "Drawings", "Drawings") 754 </a> 755 </li> 756 } 757 if (!string.IsNullOrEmpty(specs.GetByKey("BrandingFile").Value)) 758 { 759 <li> 760 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("BrandingFile").Value','@filePattern.Replace("[[type]]","Branding")','BrandingFile')" target="_blank"> 761 <svg> 762 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 763 </svg> 764 @Translate(basicPimPrefix + "Branding File", "Branding drawing") 765 </a> 766 </li> 767 } 768 if (!string.IsNullOrEmpty(specs.GetByKey("BrandingTemplate").Value)) 769 { 770 <li> 771 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("BrandingTemplate").Value','@filePattern.Replace("[[type]]", "BrandingTemplate")','BrandingTemplate')" target="_blank"> 772 <svg> 773 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 774 </svg> 775 @Translate(basicPimPrefix + "Branding Template", "Branding Template") 776 </a> 777 </li> 778 } 779 if (!string.IsNullOrEmpty(specs.GetByKey("QuickGuide").Value)) 780 { 781 <li> 782 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("QuickGuide").Value','@filePattern.Replace("[[type]]","QuickGuide")','QuickGuide')" target="_blank"> 783 <svg> 784 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 785 </svg> 786 @Translate(basicPimPrefix + "QuickGuide", "Quick Guide") 787 </a> 788 </li> 789 } 790 if (!string.IsNullOrEmpty(specs.GetByKey("AssemblyGuide").Value)) 791 { 792 <li> 793 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("AssemblyGuide").Value','@filePattern.Replace("[[type]]","AssemblyGuide")','AssemblyGuide')" target="_blank"> 794 <svg> 795 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 796 </svg> 797 @Translate(basicPimPrefix + "AssemblyGuide", "Assembly Guide") 798 </a> 799 </li> 800 } 801 if (!string.IsNullOrEmpty(specs.GetByKey("EUDeclaration").Value)) 802 { 803 <li> 804 <a href="#" v-on:click="downloadProductFile($event,'@name','@specs.GetByKey("EUDeclaration").Value','@filePattern.Replace("[[type]]","EUDeclaration")','EUDeclaration')" target="_blank"> 805 <svg> 806 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/files/dist/icons/icons.svg#download"></use> 807 </svg> 808 @Translate(basicPimPrefix + "EUDeclaration", "EU Declaration of Conformity") 809 </a> 810 </li> 811 } 812 } 813 814 </ul> 815 </div> 816 </template> 817 </b-collapse> 818 819 @if (!isSparePart) 820 { 821 <product-spare-parts-view :page-view-id="@Pageview.ID" 822 :language-id="'@selectedModel.LanguageId'" 823 :product-number="@selectedModel.Number" 824 :exploded-drawing="'@(specs.GetByKey("ExplodedDrawing")?.Value)'" 825 :spare-part-report="'@(specs.GetByKey("SparePartsBC").Value)'" 826 product-name="@name" 827 language-code="@lang" 828 :sparepart-location="product.product.defaultStockLocationName"> 829 </product-spare-parts-view> 830 } 831 832 </div> 833 </section> 834 } 835 @if (accessories != null && accessories.Any()) 836 { 837 838 <section class="basic_related"> 839 <template> 840 <header class="basic_related-header" id="accessories-header"> 841 <h2 class="text-center"> 842 @Translate(basicPimPrefix + "Accessories", "Accessories") 843 </h2> 844 </header> 845 <slick ref="slick" 846 class="basic_related-grid" 847 :options="slickAccessoriesOptions"> 848 @foreach (var accessory in accessories) 849 { 850 var converted = new AsyncProductWithSpecification(new SimpleProduct(accessory.ToViewModel(), null, stockInformation, inspirationGroupIds, websiteSettings.ExternalShopIds, true)); 851 var accessoryJson = JsonConvert.SerializeObject(converted, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); 852 accessoryJson = accessoryJson.Replace("'", "&#39;"); 853 <article class="basic_related-product"> 854 <a href="/Default.aspx?ID=@NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("plp")&amp;ProductID=@accessory.Id" class="basic_related-url"> 855 <figure> 856 @{ 857 var image = string.IsNullOrEmpty(accessory.ImageLarge) ? "/Files/Images/default.jpg" : "/Files/" + accessory.ImageLarge; 858 } 859 <img src="/Admin/Public/GetImage.ashx?Width=427&amp;Height=427&amp;Compression=85&amp;Crop=5&amp;Image=@image" 860 alt="@accessory.Name" 861 class="img-fluid" /> 862 </figure> 863 <header> 864 <h1>@accessory.Name</h1> 865 <p class="basic_related-category">@accessory.ShortDescription</p> 866 <p class="basic_related-sku">@Translate(basicPimPrefix + "Product Number", "Product Number") @accessory.Number</p> 867 </header> 868 </a> 869 @if (Pageview.IsCurrentlyB2B()) 870 { 871 <buying-component inline-template :initial-product='@accessoryJson'> 872 <footer> 873 <async-price class-type="asyncprice-plp" 874 :default-price="@accessory.Price.PriceWithoutVAT.ToString(CultureInfo.InvariantCulture)" 875 :product='@accessoryJson' 876 only-price="true" 877 standard-customer="@standardCustomer"> 878 </async-price> 879 <add-to-basket-simple :product='@accessoryJson' 880 button-class="btn btn-primary" 881 class="addtobasketsimple-plp ml-auto" 882 language-id="@languageId" 883 :price-without-vat="@accessory.Price.PriceWithoutVAT.ToString(CultureInfo.InvariantCulture)" 884 :only-spare-parts="@((Pageview.User.OnlySpareParts() && !isSparePart).ToString().ToLower())" 885 :is-marketing-user="@(Pageview.User.OnlyView().ToString().ToLower())" 886 :ishvasuser="@(Pageview.User.IsHVACUser().ToString().ToLower())" 887 standard-customer="@standardCustomer"> 888 </add-to-basket-simple> 889 </footer> 890 </buying-component> 891 892 } 893 else 894 { 895 <footer> 896 <async-price class-type="asyncprice-plp" 897 :default-price="@accessory.Price.PriceWithoutVAT.ToString(CultureInfo.InvariantCulture)" 898 :product='@accessoryJson' 899 only-price="true" 900 :only-standard-price="@(Pageview.IsCurrentlyB2C().ToString().ToLower())" 901 standard-customer="@standardCustomer"> 902 </async-price> 903 @if (Pageview.IsCurrentlyB2C()) 904 { 905 <add-to-basket-simple :product='@accessoryJson' 906 button-class="btn btn-primary" 907 class="addtobasketsimple-plp ml-auto" 908 language-id="@languageId" 909 :price-without-vat="@accessory.Price.PriceWithoutVAT.ToString(CultureInfo.InvariantCulture)" 910 :only-spare-parts="@((Pageview.User.OnlySpareParts() && !isSparePart).ToString().ToLower())" 911 :is-marketing-user="@(Pageview.User.OnlyView().ToString().ToLower())" 912 :ishvasuser="@(Pageview.User.IsHVACUser().ToString().ToLower())" 913 standard-customer="@standardCustomer"> 914 </add-to-basket-simple> 915 } 916 </footer> 917 } 918 </article> 919 } 920 </slick> 921 </template> 922 </section> 923 } 924 @if (relatedProducts != null && relatedProducts.RelatedProducts.Any()) 925 { 926 <section class="basic_related"> 927 <template> 928 <header class="basic_related-header" id="related-header"> 929 <h2 class="text-center"> 930 @Translate(basicPimPrefix + "Related Products", "Related Products") 931 </h2> 932 </header> 933 <slick ref="slick" 934 class="basic_related-grid" 935 :options="slickRelatedOptions"> 936 @foreach (var relProduct in relatedProducts.RelatedProducts) 937 { 938 939 //var relProduct = productService.GetProductById(rel.Id, rel.VariantId, rel.LanguageId); 940 var converted = new AsyncProductWithSpecification(new SimpleProduct(relProduct.ToViewModel(), null, stockInformation, inspirationGroupIds, websiteSettings.ExternalShopIds, true)); 941 var relProductJson = JsonConvert.SerializeObject(converted, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); 942 relProductJson = relProductJson.Replace("'", "&#39;"); 943 <article class="basic_related-product"> 944 <a href="/Default.aspx?ID=@NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("plp")&amp;ProductID=@relProduct.Id" class="basic_related-url"> 945 <figure style="min-height: 1px;"> 946 @{ 947 var image = string.IsNullOrEmpty(relProduct.ImageLarge) ? "/Files/Images/default.jpg" : "/Files/" + relProduct.ImageLarge; 948 } 949 <img src="/Admin/Public/GetImage.ashx?Width=427&amp;Height=427&amp;Compression=85&amp;Crop=5&amp;fillcanvas=true&amp;Image=@image" 950 alt="@relProduct.Name" 951 class="img-fluid" /> 952 </figure> 953 <header> 954 <h1>@relProduct.Name</h1> 955 <p class="basic_related-category">@relProduct.ShortDescription</p> 956 <p class="basic_related-sku">@Translate(basicPimPrefix + "Product Number", "Product Number") @relProduct.Number</p> 957 </header> 958 </a> 959 960 @if (Pageview.IsCurrentlyB2B()) 961 { 962 963 <buying-component @@discount="onDiscount($event)" inline-template :initial-product='@relProductJson' :selected-product='@relProductJson'> 964 <footer> 965 <async-price class-type="asyncprice-plp" 966 :default-price="@relProduct.Price.PriceWithoutVAT.ToString(CultureInfo.InvariantCulture)" 967 :product='@relProductJson' 968 unit-of-measure="PCS" 969 only-price="true" 970 should-emit-warranties="true" 971 :only-standard-price="@(Pageview.IsCurrentlyB2C().ToString().ToLower())" 972 standard-customer="@standardCustomer" 973 @@discount="onDiscount($event)"> 974 </async-price> 975 <add-to-basket-simple :product='@relProductJson' 976 button-class="btn btn-primary" 977 :unit-of-measure="'PCS'" 978 class="addtobasketsimple-plp ml-auto" 979 :price-without-vat="currentItemPriceWithoutVat" 980 language-id="@languageId" 981 :only-spare-parts="@((Pageview.User.OnlySpareParts() && !isSparePart).ToString().ToLower())" 982 :is-marketing-user="@(Pageview.User.OnlyView().ToString().ToLower())" 983 :ishvasuser="@(Pageview.User.IsHVACUser().ToString().ToLower())" 984 standard-customer="@standardCustomer" 985 @@discount="onDiscount($event)"> 986 </add-to-basket-simple> 987 </footer> 988 </buying-component> 989 990 } 991 else 992 { 993 <footer> 994 <async-price class-type="asyncprice-plp" 995 :default-price="@relProduct.Price.PriceWithoutVAT.ToString(CultureInfo.InvariantCulture)" 996 :product='@relProductJson' 997 only-price="true" 998 :only-standard-price="@(Pageview.IsCurrentlyB2C().ToString().ToLower())" 999 standard-customer="@standardCustomer"> 1000 </async-price> 1001 @if (Pageview.IsCurrentlyB2C()) 1002 { 1003 1004 <add-to-basket-simple :product='@relProductJson' 1005 :unit-of-measure="'PCS'" 1006 button-class="btn btn-primary" 1007 class="addtobasketsimple-plp ml-auto" 1008 language-id="@languageId" 1009 :price-without-vat="@relProduct.Price.PriceWithoutVAT.ToString(CultureInfo.InvariantCulture)" 1010 :only-spare-parts="@((Pageview.User.OnlySpareParts() && !isSparePart).ToString().ToLower())" 1011 :is-marketing-user="@(Pageview.User.OnlyView().ToString().ToLower())" 1012 :ishvasuser="@(Pageview.User.IsHVACUser().ToString().ToLower())" 1013 standard-customer="@standardCustomer"> 1014 </add-to-basket-simple> 1015 } 1016 </footer> 1017 } 1018 </article> 1019 } 1020 </slick> 1021 </template> 1022 </section> 1023 } 1024 1025 </div> 1026 </product-details-simple-pim> 1027