387 lines
21 KiB
Plaintext
387 lines
21 KiB
Plaintext
@model ShoppingCartModel
|
|
|
|
@using Nop.Core
|
|
@using Nop.Core.Domain.Catalog
|
|
@using Nop.Core.Domain.Media
|
|
@using Nop.Core.Domain.Orders
|
|
@using Nop.Core.Domain.Tax
|
|
|
|
@inject IWebHelper webHelper
|
|
@inject IWorkContext workContext
|
|
@inject MediaSettings mediaSettings
|
|
@inject OrderSettings orderSettings
|
|
|
|
<div class="order-summary-content">
|
|
@await Component.InvokeAsync(typeof(WidgetViewComponent), new { widgetZone = PublicWidgetZones.OrderSummaryContentBefore, additionalData = Model })
|
|
@await Html.PartialAsync("_OrderReviewData", Model.OrderReviewData)
|
|
@if (Model.Items.Count > 0)
|
|
{
|
|
if (Model.Warnings.Count > 0)
|
|
{
|
|
<div class="message-error">
|
|
<ul>
|
|
@foreach (var warning in Model.Warnings)
|
|
{
|
|
<li>@warning</li>
|
|
}
|
|
</ul>
|
|
</div>
|
|
}
|
|
@*we add enctype = "multipart/form-data" because "File upload" attribute control type requires it*@
|
|
<form asp-route="ShoppingCart" method="post" enctype="multipart/form-data" id="shopping-cart-form">
|
|
<div class="table-wrapper">
|
|
<table class="cart">
|
|
<colgroup>
|
|
@if (Model.ShowSku)
|
|
{
|
|
<col width="1" />
|
|
}
|
|
@if (Model.ShowProductImages)
|
|
{
|
|
<col width="1" />
|
|
}
|
|
<col />
|
|
@if (Model.ShowVendorName)
|
|
{
|
|
<col width="1" />
|
|
}
|
|
<col width="1" />
|
|
<col width="1" />
|
|
<col width="1" />
|
|
@if (Model.IsEditable)
|
|
{
|
|
<col width="1" />
|
|
}
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
@if (Model.ShowSku)
|
|
{
|
|
<th class="sku">
|
|
@T("ShoppingCart.SKU")
|
|
</th>
|
|
}
|
|
@if (Model.ShowProductImages)
|
|
{
|
|
<th class="product-picture">
|
|
@T("ShoppingCart.Image")
|
|
</th>
|
|
}
|
|
<th class="product">
|
|
@T("ShoppingCart.Product(s)")
|
|
</th>
|
|
@if (Model.ShowVendorName)
|
|
{
|
|
<th class="vendor">
|
|
@T("ShoppingCart.VendorName")
|
|
</th>
|
|
}
|
|
<th class="unit-price">
|
|
@T("ShoppingCart.UnitPrice")
|
|
</th>
|
|
<th class="quantity">
|
|
@T("ShoppingCart.Quantity")
|
|
</th>
|
|
<th class="subtotal">
|
|
@T("ShoppingCart.ItemTotal")
|
|
</th>
|
|
@if (Model.IsEditable)
|
|
{
|
|
<th class="remove-from-cart">
|
|
@T("ShoppingCart.Remove")
|
|
</th>
|
|
}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in Model.Items)
|
|
{
|
|
<tr>
|
|
@if (Model.ShowSku)
|
|
{
|
|
<td class="sku">
|
|
<label class="td-title">@T("ShoppingCart.SKU"):</label>
|
|
<span class="sku-number">@item.Sku</span>
|
|
</td>
|
|
}
|
|
@if (Model.ShowProductImages)
|
|
{
|
|
<td class="product-picture">
|
|
<a href="@(Url.RouteUrl<Product>(new { SeName = item.ProductSeName }))">
|
|
<img alt="@item.Picture.AlternateText" src="@item.Picture.ImageUrl" title="@item.Picture.Title" width="@mediaSettings.DefaultImageQuality" />
|
|
</a>
|
|
</td>
|
|
}
|
|
<td class="product">
|
|
<a href="@(Url.RouteUrl<Product>(new { SeName = item.ProductSeName }))" class="product-name">@item.ProductName</a>
|
|
@if (!string.IsNullOrEmpty(item.AttributeInfo))
|
|
{
|
|
<div class="attributes">
|
|
@Html.Raw(item.AttributeInfo)
|
|
</div>
|
|
}
|
|
@if (!string.IsNullOrEmpty(item.RecurringInfo))
|
|
{
|
|
<div class="recurring-info">
|
|
@Html.Raw(item.RecurringInfo)
|
|
</div>
|
|
}
|
|
@if (!string.IsNullOrEmpty(item.RentalInfo))
|
|
{
|
|
<div class="rental-info">
|
|
@Html.Raw(item.RentalInfo)
|
|
</div>
|
|
}
|
|
@if (Model.IsEditable && item.AllowItemEditing)
|
|
{
|
|
var editCartItemUrl = Url.RouteUrl<Product>(new { SeName = item.ProductSeName }, webHelper.GetCurrentRequestProtocol());
|
|
editCartItemUrl = webHelper.ModifyQueryString(editCartItemUrl, "updatecartitemid", item.Id.ToString());
|
|
<div class="edit-item">
|
|
<a href="@editCartItemUrl">@T("Common.Edit")</a>
|
|
</div>
|
|
}
|
|
@if (item.Warnings.Count > 0)
|
|
{
|
|
<div class="message-error">
|
|
<ul>
|
|
@foreach (var warning in item.Warnings)
|
|
{
|
|
<li>@Html.Raw(warning)</li>
|
|
}
|
|
</ul>
|
|
</div>
|
|
}
|
|
</td>
|
|
@if (Model.ShowVendorName)
|
|
{
|
|
<td class="vendor">
|
|
<label class="td-title">@T("ShoppingCart.VendorName"):</label>
|
|
<span class="vendor-name">@item.VendorName</span>
|
|
</td>
|
|
}
|
|
<td class="unit-price">
|
|
<label class="td-title">@T("ShoppingCart.UnitPrice"):</label>
|
|
<span class="product-unit-price">@item.UnitPrice</span>
|
|
</td>
|
|
<td class="quantity">
|
|
<label class="td-title" for="itemquantity@(item.Id)">@T("ShoppingCart.Quantity"):</label>
|
|
@if (Model.IsEditable)
|
|
{
|
|
if (item.AllowedQuantities.Count > 0)
|
|
{
|
|
<select name="itemquantity@(item.Id)" id="itemquantity@(item.Id)" class="qty-dropdown">
|
|
@foreach (var qty in item.AllowedQuantities)
|
|
{
|
|
<option selected="@qty.Selected" value="@qty.Value">@qty.Value</option>
|
|
}
|
|
</select>
|
|
}
|
|
else
|
|
{
|
|
<div class="product-quantity">
|
|
<div class="quantity up" id="quantity-up-@(item.Id)"></div>
|
|
<input name="itemquantity@(item.Id)" id="itemquantity@(item.Id)" type="text" value="@(item.Quantity)" class="qty-input" aria-label="@T("ShoppingCart.Quantity")" onchange="$('#updatecart').trigger('click');" />
|
|
<div class="quantity down" id="quantity-down-@(item.Id)"></div>
|
|
</div>
|
|
<script asp-location="Footer">
|
|
$(function() {
|
|
$('#quantity-up-@(item.Id)').on('click',
|
|
function (e) {
|
|
var input = $(document).find('#itemquantity@(item.Id)');
|
|
var oldValue = parseInt(input.val());
|
|
var newVal = oldValue + 1;
|
|
input.val(newVal.toString());
|
|
input.trigger("change");
|
|
});
|
|
|
|
$('#quantity-down-@(item.Id)').on('click',
|
|
function (e) {
|
|
var input = $(document).find('#itemquantity@(item.Id)');
|
|
var oldValue = parseInt(input.val());
|
|
var newVal = oldValue - 1;
|
|
input.val(newVal.toString());
|
|
input.trigger("change");
|
|
});
|
|
});
|
|
</script>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<span class="product-quantity">@item.Quantity</span>
|
|
}
|
|
</td>
|
|
<td class="subtotal">
|
|
<label class="td-title">@T("ShoppingCart.ItemTotal"):</label>
|
|
<span class="product-subtotal">@item.SubTotal</span>
|
|
@if (!string.IsNullOrEmpty(item.Discount))
|
|
{
|
|
<div class="discount">
|
|
@T("ShoppingCart.ItemYouSave", item.Discount)
|
|
</div>
|
|
if (item.MaximumDiscountedQty.HasValue)
|
|
{
|
|
<div class="discount-additional-info">
|
|
@T("ShoppingCart.MaximumDiscountedQty", item.MaximumDiscountedQty.Value)
|
|
</div>
|
|
}
|
|
}
|
|
</td>
|
|
@if (Model.IsEditable)
|
|
{
|
|
<td class="remove-from-cart">
|
|
@if (item.DisableRemoval)
|
|
{
|
|
<text> </text>
|
|
}
|
|
else
|
|
{
|
|
<input type="checkbox" name="removefromcart" id="removefromcart@(item.Id)" value="@(item.Id)" aria-label="@T("ShoppingCart.Remove")" />
|
|
<button type="button" name="updatecart" class="remove-btn" onclick="$('#removefromcart@(item.Id)').attr('checked', true); $('#updatecart').trigger('click');"></button>
|
|
}
|
|
</td>
|
|
}
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@if (Model.IsEditable && Model.Items.Count > 0 && Model.DisplayTaxShippingInfo)
|
|
{
|
|
var inclTax = await workContext.GetTaxDisplayTypeAsync() == TaxDisplayType.IncludingTax;
|
|
//tax info is already included in the price (incl/excl tax). that's why we display only shipping info here
|
|
//of course, you can modify appropriate locales to include VAT info there
|
|
<div class="tax-shipping-info">
|
|
@T(inclTax ? "ShoppingCart.TaxShipping.InclTax" : "ShoppingCart.TaxShipping.ExclTax", Url.RouteTopicUrl("shippinginfo"))
|
|
</div>
|
|
}
|
|
<div class="cart-options">
|
|
@if (Model.IsEditable)
|
|
{
|
|
<div class="common-buttons">
|
|
<button type="submit" name="updatecart" id="updatecart" class="button-2 update-cart-button" style="display: none;">@T("ShoppingCart.UpdateCart")</button>
|
|
|
|
<button type="submit" name="continueshopping" class="button-2 continue-shopping-button">@T("ShoppingCart.ContinueShopping")</button>
|
|
@await Component.InvokeAsync(typeof(ShoppingCartEstimateShippingViewComponent))
|
|
</div>
|
|
}
|
|
@if (Model.IsEditable)
|
|
{
|
|
@await Html.PartialAsync("_CheckoutAttributes", Model)
|
|
}
|
|
@await Component.InvokeAsync(typeof(SelectedCheckoutAttributesViewComponent))
|
|
</div>
|
|
<div class="cart-footer">
|
|
@await Component.InvokeAsync(typeof(WidgetViewComponent), new { widgetZone = PublicWidgetZones.OrderSummaryCartFooter, additionalData = Model })
|
|
@if (Model.IsEditable)
|
|
{
|
|
<div class="cart-collaterals">
|
|
<div class="deals">
|
|
@await Html.PartialAsync("_DiscountBox", Model.DiscountBox)
|
|
@await Html.PartialAsync("_GiftCardBox", Model.GiftCardBox)
|
|
@await Component.InvokeAsync(typeof(WidgetViewComponent), new { widgetZone = PublicWidgetZones.OrderSummaryContentDeals, additionalData = Model })
|
|
</div>
|
|
</div>
|
|
}
|
|
<div class="totals">
|
|
@await Component.InvokeAsync(typeof(WidgetViewComponent), new { widgetZone = PublicWidgetZones.OrderSummaryTotals, additionalData = Model })
|
|
@await Component.InvokeAsync(typeof(OrderTotalsViewComponent), new { isEditable = Model.IsEditable })
|
|
@if (Model.IsEditable)
|
|
{
|
|
if (!string.IsNullOrEmpty(Model.MinOrderSubtotalWarning))
|
|
{
|
|
<div class="min-amount-warning">
|
|
@Model.MinOrderSubtotalWarning
|
|
</div>
|
|
}
|
|
}
|
|
@if (Model.IsEditable)
|
|
{
|
|
if (Model.TermsOfServiceOnShoppingCartPage)
|
|
{
|
|
<div id="terms-of-service-warning-box" title="@T("Checkout.TermsOfService")" style="display: none;">
|
|
<p>@T("Checkout.TermsOfService.PleaseAccept")</p>
|
|
</div>
|
|
<div class="terms-of-service">
|
|
<input id="termsofservice" type="checkbox" name="termsofservice" />
|
|
<label for="termsofservice">@T("Checkout.TermsOfService.IAccept")</label>
|
|
@if (Model.TermsOfServicePopup)
|
|
{
|
|
<a class="read" id="read-terms">@T("Checkout.TermsOfService.Read")</a>
|
|
<script asp-location="Footer">
|
|
$(function() {
|
|
$('#read-terms').on('click',
|
|
function(e) {
|
|
e.preventDefault();
|
|
displayPopupContentFromUrl(
|
|
'@Url.RouteUrl("TopicPopup", new {SystemName = "conditionsofuse"})',
|
|
'@T("Checkout.TermsOfService")');
|
|
});
|
|
});
|
|
</script>
|
|
}
|
|
else
|
|
{
|
|
<a class="read" id="read-terms" href="@Url.RouteTopicUrl("conditionsofuse")">@T("Checkout.TermsOfService.Read")</a>
|
|
}
|
|
</div>
|
|
}
|
|
<div class="checkout-buttons">
|
|
@if (string.IsNullOrEmpty(Model.MinOrderSubtotalWarning) && !Model.HideCheckoutButton)
|
|
{
|
|
<script asp-location="Footer">
|
|
$(function() {
|
|
$('#checkout').on('click', function () {
|
|
//terms of service
|
|
var termOfServiceOk = true;
|
|
if ($('#termsofservice').length > 0) {
|
|
//terms of service element exists
|
|
if (!$('#termsofservice').is(':checked')) {
|
|
$("#terms-of-service-warning-box").dialog();
|
|
termOfServiceOk = false;
|
|
} else {
|
|
termOfServiceOk = true;
|
|
}
|
|
}
|
|
return termOfServiceOk;
|
|
});
|
|
});
|
|
</script>
|
|
if (orderSettings.CheckoutDisabled)
|
|
{
|
|
<div class="checkout-disabled">
|
|
@T("Checkout.Disabled")
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<button type="submit" id="checkout" name="checkout" value="checkout" class="button-1 checkout-button">
|
|
@T("Checkout.Button")
|
|
</button>
|
|
}
|
|
}
|
|
</div>
|
|
<div class="addon-buttons">
|
|
@*Payment method buttons (e.g. GoogleCheckoutButton, Paypal Express)*@
|
|
@foreach (var pm in Model.ButtonPaymentMethodViewComponents)
|
|
{
|
|
@await Component.InvokeAsync(pm)
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
@if (Model.IsEditable)
|
|
{
|
|
@await Component.InvokeAsync(typeof(CrossSellProductsViewComponent))
|
|
}
|
|
</form>
|
|
}
|
|
else
|
|
{
|
|
<div class="no-data">
|
|
@T("ShoppingCart.CartIsEmpty")
|
|
</div>
|
|
}
|
|
@await Component.InvokeAsync(typeof(WidgetViewComponent), new { widgetZone = PublicWidgetZones.OrderSummaryContentAfter, additionalData = Model })
|
|
</div> |