Trustpilot

COMMANDEZ AVANT 13.00 - PUIS NOUS EXPÉDIONS AUJOURD'HUI (EN SEMAINE)

LIVRAISON DE 3-5 JOURS

COMMANDEZ AVANT 13.00 - PUIS NOUS EXPÉDIONS AUJOURD'HUI (EN SEMAINE)

POLITIQUE DE RETOUR DE 14 JOURS

Exception in template (Designs\OutletCamping\eCom/Productlist/ProductListFacets.cshtml): System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.dbdcbeffb.Execute()
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context) in c:\Users\abbottm\Documents\GitHub\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateBase.cs:line 126
   at RazorEngine.Templating.TemplateService.Run(ITemplate template, DynamicViewBag viewBag) in c:\Users\abbottm\Documents\GitHub\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateService.cs:line 608
   at RazorEngine.Templating.TemplateService.Parse(String razorTemplate, Object model, DynamicViewBag viewBag, String cacheName) in c:\Users\abbottm\Documents\GitHub\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateService.cs:line 439
   at RazorEngine.Razor.Parse[T](String razorTemplate, T model, DynamicViewBag viewBag, String cacheName) in c:\Users\abbottm\Documents\GitHub\RazorEngine\src\Core\RazorEngine.Core\Razor.cs:line 290
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
@using System @using System.Collections.Generic @using System.Globalization @using System.Linq @using System.Web @using Dynamicweb.Data; @using Dynamicweb.Extensibility @using Dynamicweb.Frontend @using Dynamicweb.Ecommerce.Products @using Dynamicweb.Indexing.Querying @using OaseOutdoors.Components.Shared.Modules.Ecom.ModelBuilders @using OaseOutdoors.Components.Shared.Modules.Ecom.Models @using OaseOutdoors.Services.EcomUrlService.Initialization @using OaseOutdoors.Services.UrlParserService.Initialization @using OaseOutdoors.Services.FacetService.Models @using OaseOutdoors.Services.GroupService.Initialization @using OaseOutdoors.Services.ImageService.Enums @using OaseOutdoors.Services.ImageService.Initialization @using OaseOutdoors.Services.ProductResourceService.Enums @using OaseOutdoors.Services.ProductResourceService.Initialization @using OaseOutdoors.Services.ProductService.Initialization @using OaseOutdoors.Services.StaticResourceService.Initialization @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ var staticResourceService = ServiceLocator.Current.GetStaticResourceService(); var area = PageView.Current().Area; var areas = Dynamicweb.Services.Areas.GetAreas().Where(x => x.Active && x.Item["ShopPublished"] != null && (bool)x.Item["ShopPublished"] && x.Name.ToLower().Contains(area.Name.Split(':')[0].Trim().ToLower())).ToList(); string groupId = GetString("Ecom:Group.ID"); var group = Group.GetGroupById(groupId); var productViewModelService = new ProductViewModelBuilder(); var groupViewModelService = new GroupViewModelBuilder(); if (group.ShopId != Pageview.Area.EcomShopId) { var groupContext = HttpContext.Current; groupContext.Response.RedirectPermanent(new Uri(groupContext.Request.Url.Scheme + "://" + groupContext.Request.Url.Host + groupContext.Request.RawUrl).GetLeftPart(UriPartial.Path) + "-404", true); } var groupService = ServiceLocator.Current.GetGroupService(); var groupViewModel = groupViewModelService.GetViewModel(group); var beginSection = "<div class=\"container\"><section class=\"product-container\">"; var endSection = "</section></div>"; var urlService = ServiceLocator.Current.GetEcomUrlService(); var urlParserService = ServiceLocator.Current.GetUrlParserService(); var valutaSelector = HttpContext.Current.Request.Cookies["currencySelector"]; GroupCollection subGroups = null; if (group != null && group.HasChildGroups && group.Subgroups.Count >= 1) { subGroups = group.Subgroups; } else if (group != null && group.ParentGroups.Count > 0) { subGroups = group.ParentGroups.FirstOrDefault().Subgroups; } int breadCrumbTotal = groupViewModel.Breadcrumb.Count; int breadCrumbIndex = 1; var queryService = ServiceLocator.Current.GetInstance<IQueryService>(); var query = queryService.LoadQuery("Products", "ProductsSortAndFilter" + ".query"); var productService = ServiceLocator.Current.GetProductService(); var parameters = new Dictionary<string, object> { { "groupId", groupId } }; ////Price var heighestPriceProduct = productService.GetHighestOrLowest(query, parameters, Dynamicweb.Indexing.Querying.Sorting.SortDirection.Descending, "Price"); double heighestPrice = 0.0; var currencySymbol = ""; if (heighestPriceProduct != null) { heighestPrice = Math.Ceiling(heighestPriceProduct.Price.PriceWithVAT); currencySymbol = heighestPriceProduct.Price.Currency.Symbol; } var lowestPriceProduct = productService.GetHighestOrLowest(query, parameters, Dynamicweb.Indexing.Querying.Sorting.SortDirection.Ascending, "Price"); double lowestPrice = 0.0; if (lowestPriceProduct != null) { lowestPrice = Math.Floor(lowestPriceProduct.Price.PriceWithVAT); } var currentPriceQueryString = (!string.IsNullOrWhiteSpace(HttpContext.Current.Request.QueryString.Get("pricevat"))) ? HttpContext.Current.Request.QueryString.Get("pricevat") : HttpContext.Current.Request.QueryString.Get("pricevateur"); string[] currentPriceArray = { }; if (!string.IsNullOrWhiteSpace(currentPriceQueryString)) { currentPriceArray = currentPriceQueryString.Split(','); } var currentPriceLowValue = lowestPrice; var currentPriceHighValue = heighestPrice; if (currentPriceArray.Length == 2) { var currentPriceLowQuery = currentPriceArray.FirstOrDefault(); if (!string.IsNullOrWhiteSpace(currentPriceLowQuery)) { currentPriceLowValue = Convert.ToInt32(currentPriceLowQuery); } var currentPriceHighQuery = currentPriceArray.LastOrDefault(); if (!string.IsNullOrWhiteSpace(currentPriceHighQuery)) { currentPriceHighValue = Convert.ToInt32(currentPriceHighQuery); } } ////end price //Weight var heighestWeightProduct = productService.GetHighestOrLowest(query, parameters, Dynamicweb.Indexing.Querying.Sorting.SortDirection.Descending, "WeightNotAnalyzed"); double heighestWeight = 0.0; if (heighestWeightProduct != null) { heighestWeight = Math.Ceiling(heighestWeightProduct.Weight); } var lowestWeightProduct = productService.GetHighestOrLowest(query, parameters, Dynamicweb.Indexing.Querying.Sorting.SortDirection.Ascending, "WeightNotAnalyzed"); double lowestWeight = 0.0; if (lowestWeightProduct != null) { lowestWeight = Math.Floor(lowestWeightProduct.Weight); } var currentWeightQueryString = HttpContext.Current.Request.QueryString.Get("weight"); string[] currentWeightArray = { }; if (!string.IsNullOrWhiteSpace(currentWeightQueryString)) { currentWeightArray = currentWeightQueryString.Split(','); } var currentWeightLowValue = lowestWeight; var currentWeightHighValue = heighestWeight; if (currentWeightArray.Length == 2) { var currentWeightLowQuery = currentWeightArray.FirstOrDefault(); if (!string.IsNullOrWhiteSpace(currentWeightLowQuery)) { currentWeightLowValue = Convert.ToInt32(currentWeightLowQuery); } var currentWeightHighQuery = currentWeightArray.LastOrDefault(); if (!string.IsNullOrWhiteSpace(currentWeightHighQuery)) { currentWeightHighValue = Convert.ToInt32(currentWeightHighQuery); } } } @SnippetStart("canonical") <link rel="canonical" href="@groupViewModel.Canonical" /> @foreach (var hrefLang in groupViewModel.HrefLangs) { <link rel="alternate" hreflang="@hrefLang.HrefLang" href="@hrefLang.Href" /> } @SnippetEnd("canonical") @SnippetStart("languageSelector") <ul> @foreach (var languageArea in areas) { var hrefLang = groupViewModel.HrefLangs.FirstOrDefault(x => x.HrefAreaId == languageArea.ID); if (hrefLang == null || hrefLang.Href.ToLower().Contains("page-not-found")) { hrefLang = new HrefLangViewModel(); hrefLang.HrefName = languageArea.Item["ShopLanguageName"].ToString() ?? string.Empty; hrefLang.HrefLang = languageArea.CultureInfo.Name; hrefLang.Href = "/Default.aspx?areaid=" + languageArea.ID; hrefLang.HrefAreaId = languageArea.ID; } if (hrefLang != null && hrefLang.HrefLang != "x-default") { <li class="country-picker__item @(hrefLang.HrefAreaId == Pageview.AreaID ? "country-picker__item--current" : string.Empty)"> <a href="@hrefLang.Href"> <svg aria-hidden="true"> <use xlink:href="@staticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> <span>@hrefLang.HrefName</span> </a> </li> } } </ul> @SnippetEnd("languageSelector") @if (groupViewModel.Hero != null) { @RenderParagraphContent(groupViewModel.Hero.ID) } @helper SortingMarkup(GroupViewModel groupViewModel, String triggerId, Boolean initModule = true) { var rawUrl = Dynamicweb.Context.Current.Request.Url; var uri = new Uri(rawUrl.ToString()); // this gets all the query string key value pairs as a collection var newQueryString = HttpUtility.ParseQueryString(uri.Query); // this removes the key if exists newQueryString.Remove("sortby"); newQueryString.Remove("sortorder"); var baseUrl = uri.GetLeftPart(UriPartial.Path); baseUrl = newQueryString.Count > 0 ? String.Format("{0}?{1}", baseUrl, newQueryString) : baseUrl; baseUrl = baseUrl.Contains("?") ? baseUrl + "&" : baseUrl + "?"; <div class="sorting" @(initModule ? "data-module=\"sorting\"" : string.Empty)> <input id="product-list-sorting-@triggerId" type="checkbox" class="trigger"> <label for="product-list-sorting-@triggerId" class="sorting__button btn"> <span class="btn__icon"> <svg role="img"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#sorting"></use></svg> </span> <span class="btn__text"> @Translate("Sorting", "Sorting"): @if (HttpContext.Current.Request.QueryString.Get("sortby") == "Price") { @Translate("Price", "Price") } else if (HttpContext.Current.Request.QueryString.Get("sortby") == "ProductTitle") { @Translate("Alphabetical", "Alphabetical") } else { @Translate("Standard", "Standard") } </span> </label> <div class="sorting__options"> <ul> <li> <a href="@(baseUrl)">@Translate("Standard", "Standard")</a> </li> <li> <a href="@(baseUrl)sortby=Price&sortorder=asc">@Translate("Price", "Price")</a> </li> <li> <a href="@(baseUrl)sortby=ProductTitle&sortorder=asc">@Translate("Alphabetical", "Alphabetical")</a> </li> </ul> </div> </div> } <section class="content content--breadcrumb container-ribbon"> <div class="container"> <ol class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"> @foreach (var item in groupViewModel.Breadcrumb) { if (item == groupViewModel.Breadcrumb.LastOrDefault()) { <li class="breadcrumb__item @(item == groupViewModel.Breadcrumb.LastOrDefault() ? "breadcrumb__item--current" : "")" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> <meta itemprop="item" href="@item.Link"> <a> <span itemprop="name"> @if (breadCrumbIndex == breadCrumbTotal - 1) { @* The second to last breadcrumb item is the only one visible on mobile devices and thus the only one with this SVG *@ <svg aria-hidden="true"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#arrow-left"></use></svg> } @item.LinkTitle </span> </a> <meta itemprop="position" content="@breadCrumbIndex"> </li> } else { <li class="breadcrumb__item @(item == groupViewModel.Breadcrumb.LastOrDefault() ? "breadcrumb__item--current" : "")" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> <a itemprop="item" href="@item.Link"> <span itemprop="name"> @if (breadCrumbIndex == breadCrumbTotal - 1) { @* The second to last breadcrumb item is the only one visible on mobile devices and thus the only one with this SVG *@ <svg aria-hidden="true"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#arrow-left"></use></svg> } @item.LinkTitle </span> </a> <meta itemprop="position" content="@breadCrumbIndex"> </li> } breadCrumbIndex++; } </ol> </div> </section> @if (subGroups != null) { <section class="content content--subnavigation container-ribbon"> <div class="container"> <nav class="subnavigation"> <ul> @foreach (var subGroup in subGroups) { var productsCount = groupService.GetProductsCount(subGroup); <li class="subnavigation__item @(subGroup.Id == groupId ? "subnavigation__item--active" : "")"> <a href="@urlService.GetUrl(subGroup.IdUrlEncoded)"> @subGroup.Name @(productsCount == 0 ? "" : "(" + productsCount + ")") </a> </li> } </ul> </nav> </div> </section> } @if (group != null && group.HasProducts()) { int count = 0; int ribbonIndex = 0; <section class="content content--product-list-title container-ribbon"> <div class="container"> <button type="button" class="filters-toggle"> <div> <svg role="img"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#filters"></use></svg> </div> <div class="header__expand-menu-title" style="margin-left:0px;">FILTER</div> </button> @SortingMarkup(groupViewModel, "1") <div> @if (groupViewModel.Hero != null) { <span class="h-1">@group.Name</span> } else { <h1><span class="h-1">@group.Name</span></h1> } </div> </div> </section> foreach (var facetGroup in GetLoop("FacetGroups")) { if (subGroups != null) { <section class="content content--product-list-subgroups"> <section class="filter__groups"> <div class="container"> <nav> <ul style="background-color: #deeeed;margin: 5px;"> @foreach (var subGroup in subGroups) { var productsCount = groupService.GetProductsCount(subGroup); <li class="filter__groups-item @(subGroup.Id == groupId ? "subnavigation__item--active" : "")"> <a href="@urlService.GetUrl(subGroup.IdUrlEncoded)"> @subGroup.Name @(productsCount == 0 ? "" : "(" + productsCount + ")") </a> </li> } </ul> </nav> </div> </section> </section> } <section class="filter filter--hidden-on-mobile content content--product-list-filters container-ribbon" data-see-more="@Translate("SeeMore", "See more")" data-total-page-count="@GetString("Ecom:ProductList.TotalPages")" data-total-number="@GetString("Ecom:ProductList.PageProdCnt")" data-group-id="@group.Id" data-module="filter"> <form> <div class="container"> <div class="filter__container"> <div class="filter__icon-container"> <span class="filter__icon"> <svg role="img"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#filters"></use></svg> </span> </div> <div class="filter__facets"> @*Weight*@ @if (lowestWeight < heighestWeight) { <div class="filter__facets-container filter__facets-container--large" data-facet-name="@Translate("weight", "Weight")" data-facet-queryname="weight"> <div class="filter__facet"> <div class="filter__facet-head"> <span class="btn"> <span class="btn__icon"> <svg role="img"> <use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> </span> <span class="btn__text">@Translate("weight", "Weight")</span> </span> </div> <div class="filter__facet-body filter__facet-body--slider"> <div class="filter__range" id="range-filter-weight" data-range-current-min="@currentWeightLowValue" data-range-current-max="@currentWeightHighValue" data-range-min="@lowestWeight" data-range-max="@heighestWeight" data-range-unit="kg" data-range-name="weight"></div> <div class="range-filter__container"> <div class="range-filter-weight-min"></div> <div class="range-filter-weight-max"></div> </div> <input id="weight-min" hidden name="weight" type="text" value="@currentWeightLowValue" /> <input id="weight-max" hidden name="weight" type="text" value="@currentWeightHighValue" /> </div> </div> </div> } @*Price*@ @if (lowestPrice < heighestPrice && (valutaSelector == null || Pageview.AreaID != 1)) { <div class="filter__facets-container filter__facets-container--large" data-facet-name="@Translate("price", "Price")" data-facet-queryname="pricevat"> <div class="filter__facet"> <div class="filter__facet-head"> <span class="btn"> <span class="btn__icon"> <svg role="img"> <use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> </span> <span class="btn__text">@Translate("price", "Price")</span> </span> </div> <div class="filter__facet-body filter__facet-body--slider"> <div class="filter__range" id="range-filter-pricevat" data-range-current-min="@currentPriceLowValue" data-range-current-max="@currentPriceHighValue" data-range-min="@lowestPrice" data-range-max="@heighestPrice" data-range-unit="@currencySymbol" data-range-name="pricevat"></div> <div class="range-filter__container"> <div class="range-filter-pricevat-min"></div> <div class="range-filter-pricevat-max"></div> </div> <input id="pricevat-min" hidden name="pricevat" type="text" value="@currentPriceLowValue" /> <input id="pricevat-max" hidden name="pricevat" type="text" value="@currentPriceHighValue" /> </div> </div> </div> } @if (lowestPrice < heighestPrice && (valutaSelector != null && Pageview.AreaID == 1)) { <div class="filter__facets-container filter__facets-container--large" data-facet-name="@Translate("price", "Price")" data-facet-queryname="pricevateur"> <div class="filter__facet"> <div class="filter__facet-head"> <span class="btn"> <span class="btn__icon"> <svg role="img"> <use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> </span> <span class="btn__text">@Translate("price", "Price")</span> </span> </div> <div class="filter__facet-body filter__facet-body--slider"> <div class="filter__range" id="range-filter-pricevateur" data-range-current-min="@currentPriceLowValue" data-range-current-max="@currentPriceHighValue" data-range-min="@lowestPrice" data-range-max="@heighestPrice" data-range-unit="@currencySymbol" data-range-name="pricevateur"></div> <div class="range-filter__container"> <div class="range-filter-pricevateur-min"></div> <div class="range-filter-pricevateur-max"></div> </div> <input id="pricevateur-min" hidden name="pricevateur" type="text" value="@currentPriceLowValue" /> <input id="pricevateur-max" hidden name="pricevateur" type="text" value="@currentPriceHighValue" /> </div> </div> </div> } @*end price*@ @foreach (var facet in facetGroup.GetLoop("Facets")) { var renderType = facet.GetString("Facet.RenderType"); var optionsCount = facet.GetInteger("Facet.OptionWithResultCount"); if (optionsCount < 1 || renderType == "Range" && optionsCount < 2) { continue; } var facetMinValue = 0; var facetMaxValue = 0; List<int> facetValues = new List<int>(); var facetOptions = facet.GetLoop("FacetOptions"); if (renderType == "Range") { foreach (var facetOption in facetOptions) { var facetValue = facetOption.GetString("FacetOption.Value").Trim(); if (isStringInt(facetValue) && int.Parse(facetValue) > 0) { facetValues.Add(int.Parse(facetValue)); } } facetMinValue = facetValues.Min(); facetMaxValue = facetValues.Max(); } string facetClass = "filter__facets-container"; if (facet.GetString("Facet.QueryParameter") == "color") { facetClass = "filter__facets-container filter__facets-container--large"; } var id = 0; var faceType = (renderType == "Range") ? "filter__facet-body--slider" : string.Empty; var queryParam = facet.GetString("Facet.QueryParameter"); if(renderType == "Range" && facetMinValue < facetMaxValue || renderType != "Range") { <div class="@facetClass" data-facet-name="@facet.GetString("Facet.Name")" data-facet-queryname="@facet.GetString("Facet.QueryParameter")"> <div class="filter__facet"> <div class="filter__facet-head"> <span class="btn"> <span class="btn__icon"> <svg role="img"> <use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> </span> <span class="btn__text">@Translate(facet.GetString("Facet.Name"), facet.GetString("Facet.Name"))</span> </span> </div> <div class="filter__facet-body @faceType"> @switch (renderType) { case "Checkboxes": foreach (var facetOption in facetOptions) { <div class="filter__facet-seperator"> <input type="checkbox" @(facetOption.GetBoolean("FacetOption.Selected") ? "checked" : "") name="@facet.GetString("Facet.QueryParameter")" value="@facetOption.GetString("FacetOption.Value")" id="@facet.GetString("Facet.QueryParameter")@id" /> <label for="@facet.GetString("Facet.QueryParameter")@id"> @facetOption.GetString("FacetOption.Label").Replace("xxx", " ") @if (facet.GetString("Facet.QueryParameter") == "width" || facet.GetString("Facet.QueryParameter") == "height") { <text>cm</text> } </label> </div> id++; } break; case "Range": if (facetValues.Count > 0) { string[] facetSelectedValues = { facetMinValue.ToString(), facetMaxValue.ToString() }; if (HttpContext.Current.Request.QueryString.Get(queryParam) != null) { facetSelectedValues = HttpContext.Current.Request.QueryString.Get(queryParam).Split(','); } var facetCurrentMinValue = facetSelectedValues[0]; var facetCurrentMaxValue = facetSelectedValues[1]; <div class="filter__range" id="range-filter-@queryParam" data-range-current-min="@facetCurrentMinValue" data-range-current-max="@facetCurrentMaxValue" data-range-min="@facetMinValue" data-range-max="@facetMaxValue" data-range-unit="@Translate(queryParam + "-unit", queryParam + "-unit")" data-range-name="@queryParam"> </div> <div class="range-filter__container"> <div class="range-filter-@queryParam-min"></div> <div class="range-filter-@queryParam-max"></div> </div> <input id="@queryParam-min" hidden name="@queryParam" type="text" value="@facetCurrentMinValue" /> <input id="@queryParam-max" hidden name="@queryParam" type="text" value="@facetCurrentMaxValue" /> } break; } </div> </div> </div> } } </div> <div class="filter__filter-container"> <button type="button" class="filter__list-item filter__filter-reset filter__filter-reset--hidden"> <span>@Translate("FilterResetAll", "Reset all")</span> </button> <button class="btn btn--filled"> <span class="btn__text">@Translate("Filter", "Filter")</span> </button> </div> @SortingMarkup(groupViewModel, "2", false) </div> <div class="filter__list-container hidden"> <div class="filter__list"></div> <button type="button" class="filter__list-item filter__filter-reset"> <span> <svg role="img"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/static/dist/svg/_bundle.svg#close"></use> </svg> </span> <span>@Translate("FilterResetAll", "Reset all")</span> </button> </div> </div> @if (!String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("sortby"))) { <input name="sortby" type="hidden" value="@HttpContext.Current.Request.QueryString.Get("sortby")"> } @if (!String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("sortorder"))) { <input name="sortorder" type="hidden" value="@HttpContext.Current.Request.QueryString.Get("sortorder")"> } </form> </section> } <section class="content content--body"> <div class="product-item-wrapper container-ribbon"> <div class="container"> <section class="product-container"> @foreach (var p in GetLoop("Products")) { if (groupViewModel.HeroProduct != null && p.GetString("Ecom:Product.ID") == groupViewModel.HeroProduct.Id) { // Skip if this is the chosen hero product continue; } if (groupViewModel.IsFiltered == false && count % 6 == 0 && count > 0) { if (count == 6 && groupViewModel.HeroProduct != null) { //Show hero @RenderHeroProduct(groupViewModel.HeroProduct, groupViewModel, true) } else if (count == 6 && groupViewModel.FeaturedRibbonIds.Count > ribbonIndex && ribbonIndex != groupViewModel.FeaturedRibbonIds.Count - 1) { @endSection //Show embedded content @RenderParagraphContent(groupViewModel.FeaturedRibbonIds[ribbonIndex]) ribbonIndex++; @beginSection } else if (count > 0 && groupViewModel.FeaturedRibbonIds.Count > ribbonIndex && ribbonIndex != groupViewModel.FeaturedRibbonIds.Count - 1) { @endSection //Show embedded content @RenderParagraphContent(groupViewModel.FeaturedRibbonIds[ribbonIndex]) ribbonIndex++; @beginSection } } count++; @RenderProduct(p, groupViewModel, false) } @if (groupViewModel.IsFiltered == false && groupViewModel.FeaturedRibbonIds != null && groupViewModel.FeaturedRibbonIds.Count > ribbonIndex) { @endSection //Render any remaining ribbons on product page for (int i = ribbonIndex; i < groupViewModel.FeaturedRibbonIds.Count; i++) { if (i != groupViewModel.FeaturedRibbonIds.Count - 1) { @RenderParagraphContent(groupViewModel.FeaturedRibbonIds[i]) } } @beginSection } @if (groupViewModel.FeaturedRibbonIds.Count > 0) { @RenderParagraphContent(groupViewModel.FeaturedRibbonIds[groupViewModel.FeaturedRibbonIds.Count - 1]) } </section> <div class="search-results__button"> <span class="btn"> <span class="btn__text">@Translate("LoadMore", "Load More")</span> </span> </div> </div> </div> @if (groupViewModel.SEO != null) { @RenderParagraphContent(groupViewModel.SEO.ID) } </section> } @helper RenderProduct(LoopItem product, GroupViewModel groupViewModel, bool isHero) { var productClass = isHero ? "product-item--hero" : "product-item--flex"; <article itemscope itemtype="http://schema.org/Product" class="product-item @productClass"> <link itemprop="brand" content="@product.GetString("Ecom:Product:Field.BrandName")" /> <link itemprop="description" content="@product.GetString("Ecom:Product.LongDescription")" /> <link itemprop="sku" content="@product.GetString("Ecom:Product.Number")" /> <a itemprop="url" href="@groupViewModel.UrlService.GetUrl(groupViewModel.Id, product.GetString("Ecom:Product.ID"))"> <div class="product-item__header"> @{ var imageService = ServiceLocator.Current.GetImageService(); var productResourceService = ServiceLocator.Current.GetProductResourceService(); var imagePath = productResourceService.Get(product.GetString("Ecom:Product:Field.Image001"), FileFormat.Jpeg); var img = imageService.Begin(imagePath); var imgSrc = img.SetWidth(800).SetHeight(800).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop(); var imgClass = ""; if (Pageview.Device == 0 && product.GetString("Ecom:Product:Field.Image062") != "") { var imageHoverPath = productResourceService.Get(product.GetString("Ecom:Product:Field.Image062"), FileFormat.Jpeg); var imgHover = imageService.Begin(imageHoverPath); var imgHoverSrc = imgHover.SetWidth(800).SetHeight(800).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop(); imgClass = "orig"; <figure class="lazy hover" data-src-sm="@imgHoverSrc" data-alt="@product.GetString("Ecom:Product.Name")"> <noscript><img src="@imgHoverSrc" itemprop="image" content="@imgHoverSrc" alt="Outwell @product.GetString("Ecom:Product.Name")"></noscript> </figure> } } <figure class="lazy" data-src-sm="@imgSrc" data-alt="@product.GetString("Ecom:Product.Name")"> <noscript><img src="@imgSrc" itemprop="image" content="@imgSrc" alt="@product.GetString("Ecom:Product.Name")"></noscript> </figure> @if (!string.IsNullOrEmpty(product.GetString("Ecom:Product:Field.OutletcampingSplash")) && !string.IsNullOrEmpty(product.GetString("Ecom:Product:Field.OutletcampingSplashColor"))) { var splashTexts = product.GetString("Ecom:Product:Field.OutletcampingSplash").Split(' '); <div class="product-item__splash" style="z-index:100;background: @product.GetString("Ecom:Product:Field.OutletcampingSplashColor");"> <div class="product-item__splash-text"> <p> @for (var i = 0; i <= splashTexts.Length - 1; i++) { if (i == 1) { <span class="product-item__splash-text--bold"> @splashTexts[i]</span> } else { @splashTexts[i] } } </p> </div> </div> } </div> <div class="product-item__body"> @{ var periodEndDateSql = Database.ExecuteScalar(CommandBuilder.Create("SELECT p.PeriodEndDate FROM EcomProducts AS ep INNER JOIN EcomPeriods AS p ON ep.ProductPeriodId = p.PeriodId WHERE ep.ProductId = {0} AND ep.ProductLanguageId = {1}", product.GetString("Ecom:Product.ID"), product.GetString("Ecom:Product.LanguageID"))); var periodEndDate = (periodEndDateSql != null) ? (DateTime)periodEndDateSql : DateTime.MinValue; if (periodEndDate >= DateTime.Now && periodEndDate <= DateTime.Now.AddDays(14)) { <div data-module="countdown"> <div class="product-item__countdown" data-date="@periodEndDate.ToString("MM/dd/yyyy HH:mm:ss")"> <div class="product-item__countdown-title">@Translate("Offer ends in")</div> <div class="product-item__countdown-counter"></div> <div class="product-item__countdown-text"> <span>@Translate("Hours", "Hours")</span> <span>@Translate("Min", "Min")</span> <span>@Translate("Sec", "Sec")</span> </div> </div> </div> } } <div class="product-item__headline"> <h2 itemprop="name">@product.GetString("Ecom:Product.Name")</h2> </div> @if (!string.IsNullOrEmpty(@product.GetString("Ecom:Product.Price.Price"))) { <div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="product-item__price"> <link itemprop="availability" href="http://schema.org/InStock"> <link itemprop="url" href="@groupViewModel.UrlService.GetUrl(groupViewModel.Id, product.GetString("Ecom:Product.ID"))" /> @if (!string.IsNullOrEmpty(product.GetString("Ecom:Product:Field.Savepct.Value"))) { <div class="save"> <span>@Translate("Save", "Save") @product.GetString("Ecom:Product:Field.Savepct.Value")%</span> </div> } <div class="price"><span itemprop="priceCurrency" content="@product.GetString("Ecom:Product.Price.Currency.Symbol")">@product.GetString("Ecom:Product.Price.Currency.Symbol")</span> <span itemprop="price" content="@product.GetDouble("Ecom:Product.Price.PriceWithVAT.Value").ToString("F", new CultureInfo("en-GB"))">@product.GetString("Ecom:Product.Price.Price")</span></div> <div class="if-discount"> @if (!string.IsNullOrEmpty(product.GetString("Ecom:Product:Field.PriceBefore.Value"))) { if (product.GetDouble("Ecom:Product:Field.PriceBefore.Value") > 0) { <span>@Translate("Before", "Used to be") @product.GetString("Ecom:Product.Price.Currency.Symbol") @product.GetString("Ecom:Product:Field.PriceBefore.Value")</span> } } </div> </div> } <div class="product-item__button"> <span class="btn"> @if (Pageview.AreaID != 2) { <span class="btn__icon"> <img src="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/media/cart-white-outletcamping.png")"> </span> } <span class="btn__text">@Translate("SeeMore", "See more")</span> </span> </div> </div> </a> @if (isHero && groupViewModel.HeroImage != null) { <figure> <img src="@groupViewModel.HeroImage.SetWidth(800).SetHeight(400).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop()" /> </figure> } </article> } @helper RenderHeroProduct(ProductViewModel productViewModel, GroupViewModel groupViewModel, bool isHero) { var productClass = isHero ? "product-item--hero" : "product-item--flex"; <article itemscope itemtype="http://schema.org/Product" class="product-item @productClass"> <a itemprop="url" href="@groupViewModel.UrlService.GetUrl(groupViewModel.Id, productViewModel.Id)"> <div class="product-item__header"> <figure> <img src="@productViewModel.MainImage.SetWidth(800).SetHeight(800).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop()" itemprop="image" content="@productViewModel.MainImage.SetWidth(800).SetHeight(800).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop()" alt=""> </figure> @if (!string.IsNullOrEmpty(productViewModel.OutletcampingSplash) && !string.IsNullOrEmpty(productViewModel.OutletcampingSplashColor)) { var splashTexts = productViewModel.OutletcampingSplash.Split(' '); <div class="product-item__splash product-item__splash" style="background: @productViewModel.OutletcampingSplashColor;"> <div class="product-item__splash-text"> <p> @for (var i = 0; i <= splashTexts.Length - 1; i++) { if (i == 1) { <span class="product-item__splash-text--bold"> @splashTexts[i]</span> } else { @splashTexts[i] } } </p> </div> </div> } </div> <div class="product-item__body"> @{ if (productViewModel.PeriodEndDate >= DateTime.Now && productViewModel.PeriodEndDate <= DateTime.Now.AddDays(14)) { <div data-module="countdown"> <div class="product-item__countdown" data-date="@productViewModel.PeriodEndDate.ToString("MM/dd/yyyy HH:mm:ss")"> <div class="product-item__countdown-title">@Translate("Offer ends in")</div> <div class="product-item__countdown-counter"></div> <div class="product-item__countdown-text"> <span>@Translate("Hours", "Hours")</span> <span>@Translate("Min", "Min")</span> <span>@Translate("Sec", "Sec")</span> </div> </div> </div> } } <div class="product-item__headline"> <h1 itemprop="name">@productViewModel.Name</h1> </div> @if (!string.IsNullOrEmpty(@productViewModel.Price)) { <div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="product-item__price"> <div class="price"><span itemprop="priceCurrency" content="@productViewModel.Currency">@productViewModel.CurrencySymbol</span> <span itemprop="price" content="@productViewModel.UnformatedPrice">@productViewModel.Price</span></div> <div class="if-discount"> @if (!string.IsNullOrEmpty(productViewModel.BeforePrice)) { <span>@Translate("Before", "Used to be") @productViewModel.CurrencySymbol @productViewModel.BeforePrice</span> } </div> </div> } <div class="product-item__button"> <span class="btn"> @if (Pageview.AreaID != 2) { <span class="btn__icon"> <img src="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/media/cart-white-outletcamping.png")"> </span> } <span class="btn__text">@Translate("SeeMore", "See more")</span> </span> </div> </div> </a> @if (isHero && groupViewModel.HeroImage != null) { <figure> <img src="@groupViewModel.HeroImage.SetWidth(800).SetHeight(400).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop()" /> </figure> } </article> } @SnippetStart("jarvis") @{ var raptorArea = PageView.Current().Area; var settingsRaptorApiKey = PageView.Current().Area.Item["SettingsRaptorApiKey"]; } @if (settingsRaptorApiKey != null) { if (PageView.Current().Device == Dynamicweb.Frontend.Devices.DeviceType.Desktop && !string.IsNullOrEmpty(settingsRaptorApiKey.ToString())) { var jarvis = (HttpContext.Current.Request.Cookies["jarvis"] != null) ? HttpContext.Current.Request.Cookies["jarvis"].Value : "1"; var jarvisBoxStatus = (jarvis == "1") ? "jarvis--open" : string.Empty; var jarvisBtnStatus = (jarvis == "1") ? "" : "jarvis-btn--open"; var raptorAreaId = raptorArea.ID; var raptorBrandId = (raptorArea.Item["SettingsRaptorUserId"] != null) ? raptorArea.Item["SettingsRaptorUserId"].ToString() : string.Empty; var raptorCookieId = (HttpContext.Current.Request.Cookies[raptorBrandId + "rsa"] != null) ? HttpContext.Current.Request.Cookies[raptorBrandId + "rsa"].Value : ""; var raptorContent1 = groupViewModel.JarvisHistory; var raptorContent2 = groupViewModel.JarvisTopCategory; var settingsShopId = raptorArea.Item["SettingsShopId"].ToString(); var ecomPageId = urlParserService.GetPageId(settingsShopId); if (!string.IsNullOrEmpty(raptorCookieId)) { <div data-module="jarvis"> <div class="jarvis @jarvisBoxStatus"> <div class="jarvis__header"> <span class="your">@Translate("Your", "Your")</span> <span class="guide">@Translate("Guide", "Guide")</span> <span class="logo"></span> </div> <div class="jarvis__guide"> <button class="jarvis__close"><span class="round"><svg viewBox="0 0 100 100"><path d="M 10,50 L 60,100 L 70,90 L 30,50 L 70,10 L 60,0 Z" class="arrow"></path></svg></span> @Translate("Hide the wizard", "Hide the wizard")</button> <div class="jarvis__text"> <p> @Translate("The guide follows you around and finds new recommendations based on what you're looking at.", "The guide follows you around and finds new recommendations based on what you're looking at.") </p> </div> </div> <div class="jarvis__alternatives"> <section class="featured-products container-ribbon ribbon"> <h3>@Translate("Most seen in this category", "Most seen in this category")</h3> <div class="featured-products__container" data-url="/webservices/jarvis.ashx?areaId=@raptorAreaId&raptorFunction=GetTopViewedInCategory&raptorCategoryId=@groupId"> @foreach (var raptorProduct in raptorContent2) { var raptorProductView = productViewModelService.GetViewModel(raptorProduct); if (raptorProductView.MainImage != null) { raptorProductView.RaptorImage = raptorProductView.MainImage.SetWidth(500).SetHeight(300).SetCrop(CropType.KeepAspectRatio).SetCompression(50).GetCrop(); } raptorProductView.RaptorUrl = urlService.GetUrl(raptorProductView.GroupId, raptorProductView.Id, ecomPageId.GetValueOrDefault()); <article itemscope itemtype="http://schema.org/Product\" class="product-item"> <a itemprop="url" href="@raptorProductView.RaptorUrl"> <div class="product-item__header"> <figure> <img src="@raptorProductView.RaptorImage" itemprop="image" content="OaseOutdoors.Services.ImageService.ImageService" alt="@raptorProductView.Name"> </figure> </div> <div class="product-item__body"> <div class="product-item__headline"> <h3 itemprop="name" class="h-1">@raptorProductView.Name</h3> </div> <div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="product-item__price"> <div class="price"><span itemprop=\"priceCurrency\" content="@raptorProductView.Currency">@raptorProductView.CurrencySymbol</span> <span itemprop="price" content="@raptorProductView.UnformatedPrice">@raptorProductView.Price</span></div> </div> </div> </a> </article> } </div> </section> </div> <div class="jarvis__suggest"> <section class="featured-products container-ribbon ribbon"> <h3>@Translate("You have previously looked at", "You have previously looked at")</h3> <div class="featured-products__container" data-url="/webservices/jarvis.ashx?areaId=@raptorAreaId&raptorFunction=GetCookieHistory"> @foreach (var raptorProduct in raptorContent1) { var raptorProductView = productViewModelService.GetViewModel(raptorProduct); if (raptorProductView.MainImage != null) { raptorProductView.RaptorImage = raptorProductView.MainImage.SetWidth(500).SetHeight(300).SetCrop(CropType.KeepAspectRatio).SetCompression(50).GetCrop(); } raptorProductView.RaptorUrl = urlService.GetUrl(raptorProductView.GroupId, raptorProductView.Id, ecomPageId.GetValueOrDefault()); <article itemscope itemtype="http://schema.org/Product\" class="product-item"> <a itemprop="url" href="@raptorProductView.RaptorUrl"> <div class="product-item__header"> <figure> <img src="@raptorProductView.RaptorImage" itemprop="image" content="OaseOutdoors.Services.ImageService.ImageService" alt="@raptorProductView.Name"> </figure> </div> <div class="product-item__body"> <div class="product-item__headline"> <h3 itemprop="name" class="h-1">@raptorProductView.Name</h3> </div> <div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="product-item__price"> <div class="price"><span itemprop=\"priceCurrency\" content="@raptorProductView.Currency">@raptorProductView.CurrencySymbol</span> <span itemprop="price" content="@raptorProductView.UnformatedPrice">@raptorProductView.Price</span></div> </div> </div> </a> </article> } </div> </section> </div> </div> <div class="jarvis-btn @jarvisBtnStatus"> <img src="/static/dist/img/jarvis/jarvis-small.png"> </div> </div> } } } @SnippetEnd("jarvis") @functions { public bool isStringInt(String s) { try { int.Parse(s); return true; } catch (FormatException ex) { return false; } } }