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("'", "'");
59 selectedJsonModel = selectedJsonModel.Replace("'", "'");
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&Compression=85&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&Height=50&Compression=85&Crop=5&Format=webp&Quality=85&fillcanvas=True&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&Height=400&Compression=85&Crop=5&Format=webp&Quality=85&fillcanvas=True&Image=' + image">
184 <source media="(max-width:991.98px)" :srcset="'/Admin/Public/GetImage.ashx?Width=530&Height=530&Compression=85&Crop=5&Format=webp&Quality=85&fillcanvas=True&Image=' + image">
185 <img :src="'/Admin/Public/GetImage.ashx?Width=530&Height=530&Compression=85&Crop=5&Format=webp&Quality=85&fillcanvas=True&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&Height=250&Compression=85&Crop=5&Format=webp&Quality=85&fillcanvas=True&Image=' + image">
231 <source media="(max-width:991.98px)" :srcset="'/Admin/Public/GetImage.ashx?Width=400&Height=350&Compression=85&Crop=5&Format=webp&Quality=85&fillcanvas=True&Image=' + image">
232 <img :src="'/Admin/Public/GetImage.ashx?Width=427&Height=427&Compression=85&Crop=5&Format=webp&Quality=85&fillcanvas=True&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&Height=630&Compression=85&Crop=5&Format=webp&Quality=85&Image=@(pdpImage)">
264 <source media="(max-width:991.98px)" srcset="/Admin/Public/GetImage.ashx?Width=530&Height=530&Compression=85&Crop=5&Format=webp&Quality=85&Image=@(pdpImage)">
265 <source media="(max-width:767.98px)" srcset="/Admin/Public/GetImage.ashx?Width=400&Height=400&Compression=85&Crop=5&Format=webp&Quality=85&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&Crop=5&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&Crop=5&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&Crop=5&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("'", "'");
853 <article class="basic_related-product">
854 <a href="/Default.aspx?ID=@NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("plp")&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&Height=427&Compression=85&Crop=5&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("'", "'");
943 <article class="basic_related-product">
944 <a href="/Default.aspx?ID=@NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("plp")&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&Height=427&Compression=85&Crop=5&fillcanvas=true&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