Error executing template "Designs/Swift/_parsed/GBG_VariantMatrix.parsed.cshtml"
System.ArgumentNullException: Value cannot be null.
Parameter name: input
at System.Text.RegularExpressions.Regex.Replace(String input, String replacement)
at System.Text.RegularExpressions.Regex.Replace(String input, String pattern, String replacement)
at CompiledRazorTemplates.Dynamic.RazorEngine_b4eefafaf5064d26a61e0155d429162c.Execute() in D:\dynamicweb.net\Solutions\Degree\granberg.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\_parsed\GBG_VariantMatrix.parsed.cshtml:line 133
at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
2 @using System.Text.RegularExpressions
3 @using Dynamicweb.Ecommerce.ProductCatalog
4 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites
5 @using Dynamicweb.Ecommerce.Products.FieldDisplayGroups
6 @using Dynamicweb.Frontend
7 @using System.Web
8 @using Dynamicweb.Ecommerce.Products
9 @using Dynamicweb.Ecommerce.Stocks
10
11 @functions{
12 public class MultiplierButton
13 {
14 public int multiplier { get; set; }
15 public string label { get; set; }
16 public int sort { get; set; }
17 }
18
19 public CartOrderlineViewModel GetProductOrderline(string productId, string variantId)
20 {
21 CartOrderlineViewModel response = new CartOrderlineViewModel();
22 var orderLines = Model.Cart?.CartOrderlines;
23 if(orderLines != null)
24 {
25 CartOrderlineViewModel productOrderLine = orderLines.Where(x => x.ProductID == productId && x.ProductVariantID == variantId).FirstOrDefault();
26 response = productOrderLine != null ? productOrderLine : response;
27 }
28 return response;
29 }
30
31 }
32
33 @{
34 ProductViewModel product = new ProductViewModel();
35 bool hasExpectedDelivery = false;
36 string expectedDeliveryDate = "";
37 bool IsNeverOutOfStock = false;
38 string[] variantId = new string[] {};
39 string disableAddToCart = "";
40
41
42 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
43 {
44 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
45 }
46
47 ProductViewModelSettings productSetting = new ProductViewModelSettings
48 {
49 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID,
50 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code,
51 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2,
52 ShopId = Pageview.Area.EcomShopId
53 };
54
55 if (Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") != null)
56 {
57 string productId = Dynamicweb.Context.Current.Request.QueryString.Get("ProductID");
58
59 product = ViewModelFactory.CreateView(productSetting, productId);
60 } else {
61 product = ViewModelFactory.CreateView(productSetting, "Product122");
62 }
63
64 int multiplier = 1;
65 if (Dynamicweb.Context.Current.Request.QueryString.Get("multiplier") != null)
66 {
67 multiplier = Dynamicweb.Core.Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("multiplier"));
68 }
69 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", "");
70 bool anonymousUser = Pageview.User == null;
71 bool hideAddToCart = anonymousUsersLimitations.Contains("cart") && anonymousUser;
72 //hideAddToCart = product.VariantInfo.VariantInfo != null && Model.Item.GetBoolean("HideVariantSelector") ? true : hideAddToCart;
73 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser;
74 bool hideFavoritesSelector = false;//!string.IsNullOrEmpty(Model.Item.GetString("HideFavoritesSelector")) ? Model.Item.GetBoolean("HideFavoritesSelector") : false;
75
76 if(product.Id != "")
77 {
78 IsNeverOutOfStock = product.NeverOutOfstock;
79 variantId = product.VariantId?.Split('.');
80 disableAddToCart = (product.StockLevel <= 0) ? "disabled" : "";
81 if (IsNeverOutOfStock)
82 {
83 disableAddToCart = "";
84 }
85
86 // Does product has a expected delivery data
87 hasExpectedDelivery = product.ExpectedDelivery != null && product.ExpectedDelivery > DateTime.Now;
88 expectedDeliveryDate = product.ExpectedDelivery?.ToShortDateString() ?? "";
89
90 }
91
92
93 string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService"));
94 if (!url.Contains("LayoutTemplate"))
95 {
96 url += url.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml";
97 }
98
99
100
101 string theme = "";//!string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
102
103 string titleFontSize = "display-6";//Model.Item.GetRawValueString("TitleFontSize", "display-6");
104
105 string contentPadding = "";//Model.Item.GetRawValueString("ContentPadding", "");
106 contentPadding = contentPadding == "small" ? "p-2 p-md-3" : contentPadding;
107 contentPadding = contentPadding == "large" ? "p-4 p-md-5" : contentPadding;
108
109 string quantityPricesLayout = "list";//Model.Item.GetRawValueString("QuantityPricesLayout", "list");
110 string minQty = "min=\"0\"";
111 // string minQty = product.PurchaseMinimumQuantity != 1 ? "min=\"" + product.PurchaseMinimumQuantity.ToString() + "\"" : "min=\"1\"";
112 string stepQty = product.PurchaseQuantityStep > 1 ? product.PurchaseQuantityStep.ToString() : "1";
113 string valueQty = product.PurchaseMinimumQuantity > product.PurchaseQuantityStep ? product.PurchaseMinimumQuantity.ToString() : stepQty;
114 string qtyValidCheck = stepQty != "1" ? "onkeyup=\"swift.Cart.QuantityValidate(event)\"" : "";
115
116 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower();
117 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat);
118
119 string priceMin = "";
120 string priceMax = "";
121
122 string iconPath = "/Files/icons/";
123
124 var favoriteParameters = new Dictionary<string, object>();
125
126 List<UnitOfMeasure> productUnits = new List<UnitOfMeasure>();
127
128 string tabParameter = Dynamicweb.Context.Current.Request.QueryString.Get("tab");
129 string outerCaseChecked = tabParameter == "outer-case" || tabParameter == "" ? "checked" : "";
130 string bundleChecked = tabParameter == "bundle" ? "checked" : "";
131 string pairsChecked = tabParameter == "pairs" ? "checked" : "";
132 // string step = tabParameter == "outer-case" || tabParameter == "" ? "72" : tabParameter == "bundle" ? "12" : "1";
133 string step = Regex.Replace(tabParameter, @"[^\d]", "");
134 }
135 <div class="h-100 @(contentPadding) @(theme)">
136 <div class="d-flex flex-column gap-4 js-product">
137 @if (!anonymousUser)
138 {
139 if(product.Id != "")
140 {
141
142 // Dynamicweb.Ecommerce.Services.UnitOfMeasureService unitService = new Dynamicweb.Ecommerce.Services.UnitOfMeasureService();
143 Dynamicweb.Ecommerce.Stocks.UnitOfMeasureService unitService = new Dynamicweb.Ecommerce.Stocks.UnitOfMeasureService();
144 productUnits = unitService.GetUnitOfMeasures(product.Id).ToList();
145 @* @productUnits.Count *@
146 <div class="d-flex gap-0" role="group" aria-label="Basic radio toggle button order-units" data-ref="table-header">
147 @foreach (var unit in productUnits)
148 {
149
150 @* <p>@unit.QuantityPerUnit</p> *@
151 var quantity = unit.QuantityPerUnit;
152 var id = unit.UnitId;
153 if (quantity == 1)
154 {
155 if (tabParameter=="" || tabParameter == "quantity-input-1")
156 {
157 <input type="radio" class="btn-check quantity-input" name="options" id="quantity-input-@quantity" data-step-input="@quantity" autocomplete="off" checked>
158 <label class="btn btn-primary flex-fill rounded-0 shadow-none multiplier-btn py-3" data-step="@quantity" checked>@quantity @Translate("pair bundle").ToUpper()</label>
159 }
160 else
161 {
162 <input type="radio" class="btn-check quantity-input" name="options" id="quantity-input-@quantity" data-step-input="@quantity" autocomplete="off">
163 <label class="btn btn-primary flex-fill rounded-0 shadow-none multiplier-btn py-3" data-step="@quantity">@quantity @Translate("pair bundle").ToUpper()</label>
164 }
165
166 }
167 else if(id != "Unit_PALL")
168 {
169 if (tabParameter == "quantity-input-" + quantity)
170 {
171 <input type="radio" class="btn-check quantity-input" name="options" id="quantity-input-@quantity" checked data-step-input="@quantity" autocomplete="off">
172 <label class="btn btn-primary flex-fill rounded-0 shadow-none multiplier-btn py-3" data-step="@quantity" checked>@quantity @Translate("pairs bundle").ToUpper()</label>
173 }
174 else
175 {
176 <input type="radio" class="btn-check quantity-input" name="options" id="quantity-input-@quantity" data-step-input="@quantity" autocomplete="off">
177 <label class="btn btn-primary flex-fill rounded-0 shadow-none multiplier-btn py-3" data-step="@quantity">@quantity @Translate("pairs bundle").ToUpper()</label>
178 }
179 }
180 }
181 </div>
182
183
184 // var units = GetUnitOfMeasures(product.Id);
185
186
187 int groupNumber = 1;
188 @* <div class=" grid gap-0" role="group" aria-label="Basic radio toggle button order-units" data-ref="table-header"> *@
189
190 @* <input type="radio" class="btn-check" name="options" id="outer-case" autocomplete="off" @outerCaseChecked> *@
191 @* <label class="btn btn-primary rounded-0 shadow-none multiplier-btn py-3 g-col-4" data-step="72" for="outer-case">@Translate("Outer Case").ToUpper()</label> *@
192 @* *@
193 @* <input type="radio" class="btn-check" name="options" id="bundle" autocomplete="off" @bundleChecked> *@
194 @* <label class="btn btn-primary rounded-0 shadow-none multiplier-btn py-3 g-col-4" data-step="12" for="bundle">@Translate("Bundle").ToUpper()</label> *@
195 @* *@
196 @* <input type="radio" class="btn-check" name="options" id="pairs" autocomplete="off" @pairsChecked> *@
197 @* <label class="btn btn-primary rounded-0 shadow-none multiplier-btn py-3 g-col-4" data-step="1" for="pairs">@Translate("Pairs").ToUpper()</label> *@
198
199 // </div>
200
201 <input type="hidden" name="variantid"/>
202
203 foreach (var variantGroup in product.VariantGroups())
204 {
205 VariantGroupViewModel group = variantGroup;
206 int i = 0;
207
208 <div class="js-variant-group" data-group-id="@groupNumber">
209 @if (group.Name == "Size")
210 {
211
212
213 <table class="table text-center">
214 <thead>
215 <tr>
216 @* <th>@Translate("Stock")</th> *@
217 <th>@Translate("Sizes")</th>
218 <th>@Translate("Quantity (pairs)")</th>
219 </tr>
220 </thead>
221 <tbody>
222 @foreach (var option in group.Options)
223 {
224 string orderLineID = "";
225 double orderLineQuantity = 0;
226 int quantityMultiplier = Dynamicweb.Core.Converter.ToInt32(multiplier);
227
228 ProductViewModel variant = ViewModelFactory.CreateView(productSetting, product.Id, option.Id);
229 double? variantStock = variant.StockLevel;
230 string variantMinQty = variant.PurchaseMinimumQuantity != 1 ? "min=\"" + variant.PurchaseMinimumQuantity.ToString() + "\"" : "min=\"1\"";
231 string variantStepQty = variant.PurchaseQuantityStep > 1 ? variant.PurchaseQuantityStep.ToString() : "1";
232 string variantValueQty = variant.PurchaseMinimumQuantity > variant.PurchaseQuantityStep ? variant.PurchaseMinimumQuantity.ToString() : variantStepQty;
233 string variantQtyValidCheck = stepQty != "1" ? "onkeyup=\"swift.Cart.QuantityValidate(event)\"" : "";
234 string uniqueID = variant.Id + "_" + variant.VariantId;
235 string quantityInputName = "Quantity";
236 string inputClass = "d-none";
237
238 <tr>
239 @* <td> *@
240 @* @variantStock *@
241 @* </td> *@
242 <td>
243 <p class="d-inline-block variant-option js-variant-option mb-0 pt-2" data-variant-id="@option.Id">
244 @option.Name
245 </p>
246 </td>
247 <td class="w-50">
248
249 @* @if (variantStock > 0) *@
250 @* { *@
251 @{var productOrderLine = GetProductOrderline(variant.Id, variant.VariantId);}
252 <form id="@uniqueID" action="@url">
253
254 @if (variant.IsProductInCart() && productOrderLine.Quantity > 0)
255 {
256
257 inputClass = "d-flex";
258 orderLineID = productOrderLine.ID;
259 orderLineQuantity = productOrderLine.Quantity;
260 quantityInputName = "QuantityOrderLine" + orderLineID;
261 <input type="hidden" name="cartcmd" value="UpdateorderLines">
262 <input type="hidden" name="redirect" value="false">
263 //do some logic to handle increase orderline
264 }
265 else
266 {
267 // do logic to handle add to cart
268 <input type="hidden" name="redirect" value="false">
269 <input type="hidden" name="ProductId" value="@variant.Id">
270 <input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code">
271 <input type="hidden" name="VariantId" value="@variant.VariantId">
272 <input type="hidden" name="cartcmd" value="add">
273
274 <button type="button" class="btn btn-primary flex-fill js-add-to-cart-button" title="@Translate("Add to cart")">@Translate("Add to cart")
275 </button>
276 }
277 <div class="js-input-group @inputClass flex-wrap justify-content-center">
278 <button type="button" class="btn btn-link" data-role="step-down">
279 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
280 <rect x="0.5" y="0.5" width="23" height="23" rx="2.5" stroke="black"/>
281 <path d="M17 10V14H7V10H17Z" fill="black"/>
282 </svg>
283 </button>
284
285 <label for="QuantityOrderLine@(option.Id)" class="visually-hidden" >@Translate("Quantity"):</label>
286 <input step="@step" type="number" data-ref="quantity-input" id="QuantityOrderLine@(option.Id)" @minQty class="form-control text-center quantity-input" value="@orderLineQuantity" name="@quantityInputName" @qtyValidCheck style="max-width: 4.5rem;" data-bs-container="body" data-bs-toggle="popover" data-bs-trigger="manual" data-bs-placement="top" data-stock="@variantStock" data-error-invalid-multiplier="The current value is invalid! Step is: " data-error-no-stock="Not enough stock!" data-bs-content="asd" data-bs-custom-class="alert-danger">
287
288 <button type="button" class="btn btn-link" data-role="step-up" data-bs-container="body" data-bs-toggle="popover" data-bs-trigger="manual" data-bs-placement="top" data-bs-content="Not enough stock!" data-bs-custom-class="alert-danger">
289 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
290 <rect x="0.5" y="0.5" width="23" height="23" rx="2.5" stroke="black"/>
291 <path d="M9.9774 20V4H14.0226V20H9.9774ZM4 14.0226V9.9774H20V14.0226H4Z" fill="black"/>
292 </svg>
293 </button>
294 </div>
295
296 @* <div class="px-3 mt-3 w-50 bg-danger m-auto rounded-pill d-none" data-role="alert-stock-exceeded"> *@
297 @* <p class="align-self-center text-center m-0">@Translate("Stock exceeded!")</p> *@
298 @* </div> *@
299 @* <button type="submit" onclick="document.querySelector('#@uniqueID').submit()">submit</button> *@
300 @* <button type="button" onclick="swift.Cart.UpdateCustom(event)" class="btn btn-primary" style="white-space: nowrap" title="@Translate("Add to cart")" id="AddToCartButton@(uniqueID)"> *@
301 @* </button> *@
302 </form>
303
304 @* } *@
305 @* else *@
306 @* { *@
307 @* <button type="button" class="btn btn-primary flex-fill js-add-to-cart-button" disabled title="@Translate("Add to cart")">@Translate("Add to cart") *@
308 @* </button> *@
309 @* } *@
310 </td>
311 </tr>
312
313 i++;
314
315 }
316 </tbody>
317 </table>
318
319
320 }
321 </div>
322
323 groupNumber++;
324 }
325
326 if (!IsNeverOutOfStock)
327 {
328 <div class="mt-3 js-stock-state">
329
330 @* @if (product.StockLevel > 0) *@
331 @* { *@
332 @* if (!Model.Item.GetBoolean("HideInventory")) *@
333 @* { *@
334 @* <p class="small text-success m-0">@product.StockLevel @Translate("Products available in stock")</p> *@
335 @* } *@
336 @* else *@
337 @* { *@
338 @* <p class="small text-success m-0">@Translate("Available in stock")</p> *@
339 @* } *@
340 @* } *@
341 @* *@
342 @* else *@
343 @* { *@
344 @* <p class="small text-danger m-0">@Translate("Out of Stock")</p> *@
345 @* } *@
346
347 @if (hasExpectedDelivery)
348 {
349 <p>
350 <span>@Translate("Expected back in stock:")</span>
351 <span>@expectedDeliveryDate</span>
352 </p>
353 }
354
355 </div>
356 }
357 } else {
358 <p>@Translate("Invalid product")</p>
359 }
360
361 }
362 else
363 {
364 <p>test</p>
365 @* <button class="btn btn-primary"> *@
366 <a href="/sign-in" class="btn btn-secondary col-lg-3 col-6 my-3 ms-lg-4 mx-auto log-in-button-pdp" style="text-transform: none">
367 @Translate("Webshop Login")
368 </a>
369 @* </button> *@
370 }
371 </div>
372 </div>
373