feat: shopping cart page

This commit is contained in:
prssanna 2021-01-20 17:52:54 +05:30
parent 706eae7cac
commit b00eb1b0cc
14 changed files with 573 additions and 201 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -5,6 +5,19 @@ body.product-page {
background: var(--gray-50); background: var(--gray-50);
} }
.item-breadcrumbs {
.breadcrumb-container {
ol.breadcrumb {
background-color: var(--gray-50) !important;
}
a {
color: var(--gray-900);
}
}
}
.carousel-control { .carousel-control {
height: 42px; height: 42px;
width: 42px; width: 42px;
@ -77,6 +90,18 @@ body.product-page {
margin-top: 1.25rem; margin-top: 1.25rem;
} }
.no-image {
@include flex(flex, center, center, null);
height: 200px;
margin: 0 auto;
margin-top: var(--margin-xl);
background: var(--gray-100);
width: 80%;
border-radius: var(--border-radius);
font-size: 2rem;
color: var(--gray-500);
}
.product-title { .product-title {
font-size: 14px; font-size: 14px;
color: var(--gray-800); color: var(--gray-800);
@ -98,7 +123,7 @@ body.product-page {
.product-category { .product-category {
font-size: 13px; font-size: 13px;
color: var(--gray-600); color: var(--text-muted);
margin: var(--margin-sm) 0; margin: var(--margin-sm) 0;
} }
@ -159,6 +184,15 @@ body.product-page {
@include card($padding: var(--padding-md)); @include card($padding: var(--padding-md));
min-height: 70vh; min-height: 70vh;
.product-details {
max-width: 40%;
margin-left: -30px;
.btn-add-to-cart {
font-size: var(--text-base);
}
}
.product-title { .product-title {
font-size: 24px; font-size: 24px;
font-weight: 600; font-weight: 600;
@ -166,7 +200,7 @@ body.product-page {
} }
.product-code { .product-code {
color: var(--gray-600); color: var(--text-muted);
font-size: 13px; font-size: 13px;
} }
@ -180,13 +214,13 @@ body.product-page {
padding: 15px; padding: 15px;
@include media-breakpoint-between(xs, md) { @include media-breakpoint-between(xs, md) {
height: 320px; height: 300px;
width: 320px; width: 300px;
} }
@include media-breakpoint-up(lg) { @include media-breakpoint-up(lg) {
height: 430px; height: 350px;
width: 420px; width: 350px;
} }
img { img {
@ -208,7 +242,7 @@ body.product-page {
.item-slideshow-image { .item-slideshow-image {
height: 4rem; height: 4rem;
width: 4rem; width: 6rem;
object-fit: contain; object-fit: contain;
padding: 0.5rem; padding: 0.5rem;
border: 1px solid var(--table-border-color); border: 1px solid var(--table-border-color);
@ -227,24 +261,56 @@ body.product-page {
font-weight: 600; font-weight: 600;
.formatted-price { .formatted-price {
color: var(--gray-600); color: var(--text-muted);
font-size: 14px; font-size: var(--text-base);
} }
} }
.no-stock { .no-stock {
font-size: 14px; font-size: var(--text-base);
}
} }
} }
.item-breadcrumbs { .item-configurator-dialog {
.breadcrumb-container { .modal-header {
margin: 0px; padding: var(--padding-md) var(--padding-xl);
padding: 0px;
a {
color: $text-muted;
} }
.modal-body {
padding: 0 var(--padding-xl);
padding-bottom: var(--padding-xl);
.status-area {
.alert {
padding: var(--padding-xs) var(--padding-sm);
font-size: var(--text-sm);
}
}
.form-layout {
max-height: 50vh;
overflow-y: auto;
}
.section-body {
.form-column {
.form-group {
.control-label {
font-size: var(--text-md);
color: var(--gray-700);
}
.help-box {
margin-top: 2px;
font-size: var(--text-sm);
}
}
}
}
svg {
display: none;
} }
} }
} }
@ -258,3 +324,167 @@ body.product-page {
border-radius: $card-border-radius; border-radius: $card-border-radius;
} }
} }
.cart-icon {
.cart-badge {
position: relative;
top: -10px;
left: -12px;
background: var(--red-600);
width: 16px;
align-items: center;
height: 16px;
font-size: 10px;
border-radius: 50%;
}
}
#page-cart {
.shopping-cart-header {
font-weight: bold;
}
.cart-container {
color: var(--text-color);
.frappe-card {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.cart-items-header {
font-weight: 600;
}
.cart-table {
th, tr, td {
border-color: var(--border-color);
border-width: 1px;
}
th {
font-weight: normal;
font-size: 13px;
color: var(--text-muted);
padding: var(--padding-sm) 0;
}
td {
padding: var(--padding-sm) 0;
color: var(--text-color);
}
.cart-items {
.item-title {
font-size: var(--text-base);
font-weight: 500;
color: var(--text-color);
}
.item-subtitle {
color: var(--text-muted);
font-size: var(--text-md);
}
.item-subtotal {
font-size: var(--text-base);
font-weight: 500;
}
.item-rate {
font-size: var(--text-md);
color: var(--text-muted);
}
textarea {
width: 40%;
}
}
.cart-tax-items {
.item-grand-total {
font-size: 16px;
font-weight: 600;
color: var(--text-color);
}
}
}
.cart-addresses {
hr {
border-color: var(--border-color);
}
}
.number-spinner {
width: 75%;
.cart-btn {
border: none;
background: var(--gray-100);
box-shadow: none;
height: 28px;
align-items: center;
display: flex;
}
.cart-qty {
height: 28px;
font-size: var(--text-md);
}
}
.place-order-container {
.btn-place-order {
width: 62%;
}
}
}
}
.cart-empty.frappe-card {
min-height: 76vh;
@include flex(flex, center, center, column);
.cart-empty-message {
font-size: 18px;
color: var(--text-color);
font-weight: bold;
}
}
.address-card {
.card-title {
font-size: var(--text-base);
font-weight: 500;
}
.card-text {
font-size: var(--text-md);
color: var(--gray-700);
}
.card-link {
font-size: var(--text-md);
svg use {
stroke: var(--blue-500);
}
}
.btn-change-address {
color: var(--blue-500);
box-shadow: none;
border: 1px solid var(--blue-500);
}
}
.modal .address-card {
.card-body {
padding: var(--padding-sm);
border-radius: var(--border-radius);
border: 1px solid var(--dark-border-color);
}
}

View File

@ -42,14 +42,30 @@ def get_cart_quotation(doc=None):
return { return {
"doc": decorate_quotation_doc(doc), "doc": decorate_quotation_doc(doc),
"shipping_addresses": [{"name": address.name, "title": address.address_title, "display": address.display} "shipping_addresses": get_shipping_addresses(party),
for address in addresses if address.address_type == "Shipping"], "billing_addresses": get_billing_addresses(party),
"billing_addresses": [{"name": address.name, "title": address.address_title, "display": address.display}
for address in addresses if address.address_type == "Billing"],
"shipping_rules": get_applicable_shipping_rules(party), "shipping_rules": get_applicable_shipping_rules(party),
"cart_settings": frappe.get_cached_doc("Shopping Cart Settings") "cart_settings": frappe.get_cached_doc("Shopping Cart Settings")
} }
@frappe.whitelist()
def get_shipping_addresses(party=None):
if not party:
party = get_party()
addresses = get_address_docs(party=party)
return [{"name": address.name, "title": address.address_title, "display": address.display}
for address in addresses if address.address_type == "Shipping"
]
@frappe.whitelist()
def get_billing_addresses(party=None):
if not party:
party = get_party()
addresses = get_address_docs(party=party)
return [{"name": address.name, "title": address.address_title, "display": address.display}
for address in addresses if address.address_type == "Billing"
]
@frappe.whitelist() @frappe.whitelist()
def place_order(): def place_order():
quotation = _get_cart_quotation() quotation = _get_cart_quotation()
@ -203,26 +219,32 @@ def get_terms_and_conditions(terms_name):
@frappe.whitelist() @frappe.whitelist()
def update_cart_address(address_type, address_name): def update_cart_address(address_type, address_name):
quotation = _get_cart_quotation() quotation = _get_cart_quotation()
address_display = get_address_display(frappe.get_doc("Address", address_name).as_dict()) address_doc = frappe.get_doc("Address", address_name).as_dict()
address_display = get_address_display(address_doc)
if address_type.lower() == "billing": if address_type.lower() == "billing":
quotation.customer_address = address_name quotation.customer_address = address_name
quotation.address_display = address_display quotation.address_display = address_display
quotation.shipping_address_name == quotation.shipping_address_name or address_name quotation.shipping_address_name == quotation.shipping_address_name or address_name
address_doc = next((doc for doc in get_billing_addresses() if doc["name"] == address_name), None)
elif address_type.lower() == "shipping": elif address_type.lower() == "shipping":
quotation.shipping_address_name = address_name quotation.shipping_address_name = address_name
quotation.shipping_address = address_display quotation.shipping_address = address_display
quotation.customer_address == quotation.customer_address or address_name quotation.customer_address == quotation.customer_address or address_name
address_doc = next((doc for doc in get_shipping_addresses() if doc["name"] == address_name), None)
apply_cart_settings(quotation=quotation) apply_cart_settings(quotation=quotation)
quotation.flags.ignore_permissions = True quotation.flags.ignore_permissions = True
quotation.save() quotation.save()
context = get_cart_quotation(quotation) context = get_cart_quotation(quotation)
context['address'] = address_doc
return { return {
"taxes": frappe.render_template("templates/includes/order/order_taxes.html", "taxes": frappe.render_template("templates/includes/order/order_taxes.html",
context), context),
"address": frappe.render_template("templates/includes/cart/address_card.html",
context)
} }
def guess_territory(): def guess_territory():

View File

@ -14,7 +14,7 @@ $.extend(shopping_cart, {
}, },
bind_events: function() { bind_events: function() {
shopping_cart.bind_address_select(); shopping_cart.bind_address_picker_dialog();
shopping_cart.bind_place_order(); shopping_cart.bind_place_order();
shopping_cart.bind_request_quotation(); shopping_cart.bind_request_quotation();
shopping_cart.bind_change_qty(); shopping_cart.bind_change_qty();
@ -23,12 +23,30 @@ $.extend(shopping_cart, {
shopping_cart.bind_coupon_code(); shopping_cart.bind_coupon_code();
}, },
bind_address_select: function() { bind_address_picker_dialog: function() {
$(".cart-addresses").on('click', '.address-card', function(e) { const d = this.get_update_address_dialog();
const $card = $(e.currentTarget); this.parent.find('.btn-change-address').on('click', (e) => {
const type = $(e.currentTarget).parents('.address-container').attr('data-address-type');
$(d.get_field('address_picker').wrapper).html(
this.get_address_template(type)
);
d.show();
});
},
get_update_address_dialog() {
return new frappe.ui.Dialog({
title: "Select Address",
fields: [{
'fieldtype': 'HTML',
'fieldname': 'address_picker',
}],
primary_action_label: __('Set Address'),
primary_action: () => {
const $card = d.$wrapper.find('.address-card.active');
const address_type = $card.closest('[data-address-type]').attr('data-address-type'); const address_type = $card.closest('[data-address-type]').attr('data-address-type');
const address_name = $card.closest('[data-address-name]').attr('data-address-name'); const address_name = $card.closest('[data-address-name]').attr('data-address-name');
return frappe.call({ frappe.call({
type: "POST", type: "POST",
method: "erpnext.shopping_cart.cart.update_cart_address", method: "erpnext.shopping_cart.cart.update_cart_address",
freeze: true, freeze: true,
@ -37,14 +55,44 @@ $.extend(shopping_cart, {
address_name address_name
}, },
callback: function(r) { callback: function(r) {
d.hide();
if(!r.exc) { if(!r.exc) {
$(".cart-tax-items").html(r.message.taxes); $(".cart-tax-items").html(r.message.taxes);
shopping_cart.parent.find(
`.address-container[data-address-type="${address_type}"]`
).html(r.message.address);
} }
} }
}); });
}
}); });
}, },
get_address_template(type) {
return {
shipping: `<div class="mb-3" data-section="shipping-address">
<div class="row no-gutters" data-fieldname="shipping_address_name">
{% for address in shipping_addresses %}
<div class="mr-3 mb-3 w-100" data-address-name="{{address.name}}" data-address-type="shipping"
{% if doc.shipping_address_name == address.name %} data-active {% endif %}>
{% include "templates/includes/cart/address_picker_card.html" %}
</div>
{% endfor %}
</div>
</div>`,
billing: `<div class="mb-3" data-section="billing-address">
<div class="row no-gutters" data-fieldname="customer_address">
{% for address in billing_addresses %}
<div class="mr-3 mb-3 w-100" data-address-name="{{address.name}}" data-address-type="billing"
{% if doc.shipping_address_name == address.name %} data-active {% endif %}>
{% include "templates/includes/cart/address_picker_card.html" %}
</div>
{% endfor %}
</div>
</div>`,
}[type];
},
bind_place_order: function() { bind_place_order: function() {
$(".btn-place-order").on("click", function() { $(".btn-place-order").on("click", function() {
shopping_cart.place_order(this); shopping_cart.place_order(this);
@ -221,6 +269,7 @@ $.extend(shopping_cart, {
frappe.ready(function() { frappe.ready(function() {
$(".cart-icon").hide(); $(".cart-icon").hide();
shopping_cart.parent = $(".cart-container");
shopping_cart.bind_events(); shopping_cart.bind_events();
}); });

View File

@ -1,12 +1,17 @@
<div class="card address-card h-100"> <div class="card address-card h-100">
<div class="check" style="position: absolute; right: 15px; top: 15px;"> <div class="btn btn-sm btn-default btn-change-address" style="position: absolute; right: 0; top: 0;">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check"><polyline points="20 6 9 17 4 12"></polyline></svg> {{ _('Change') }}
</div> </div>
<div class="card-body"> <div class="card-body p-0">
<h5 class="card-title">{{ address.title }}</h5> <div class="card-title">{{ address.title }}</div>
<p class="card-text text-muted"> <div class="card-text mb-2">
{{ address.display }} {{ address.display }}
</p> </div>
<a href="/addresses?name={{address.name}}" class="card-link">{{ _('Edit') }}</a> <a href="/addresses?name={{address.name}}" class="card-link">
<svg class="icon icon-sm">
<use href="#icon-edit"></use>
</svg>
{{ _('Edit') }}
</a>
</div> </div>
</div> </div>

View File

@ -0,0 +1,12 @@
<div class="card address-card h-100">
<div class="check" style="position: absolute; right: 15px; top: 15px;">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check"><polyline points="20 6 9 17 4 12"></polyline></svg>
</div>
<div class="card-body">
<h5 class="card-title">{{ address.title }}</h5>
<p class="card-text text-muted">
{{ address.display }}
</p>
<a href="/addresses?name={{address.name}}" class="card-link">{{ _('Edit') }}</a>
</div>
</div>

View File

@ -14,31 +14,39 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
<div class="mb-3" data-section="shipping-address"> <div class="mb-3 frappe-card p-5" data-section="shipping-address">
<h6 class="text-uppercase">{{ _("Shipping Address") }}</h6> <h6>{{ _("Shipping Address") }}</h6>
<div class="row no-gutters" data-fieldname="shipping_address_name"> <hr>
{% for address in shipping_addresses %} {% for address in shipping_addresses %}
<div class="mr-3 mb-3 w-25" data-address-name="{{address.name}}" data-address-type="shipping" {% if doc.shipping_address_name == address.name %} data-active {% endif %}> {% if doc.shipping_address_name == address.name %}
<div class="row no-gutters" data-fieldname="shipping_address_name">
<div class="w-100 address-container" data-address-name="{{address.name}}" data-address-type="shipping" data-active>
{% include "templates/includes/cart/address_card.html" %} {% include "templates/includes/cart/address_card.html" %}
</div> </div>
</div>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
<div class="checkbox ml-1 mb-2">
<label for="input_same_billing">
<input type="checkbox" id="input_same_billing" checked>
<span class="label-area">{{ _('Billing Address is same as Shipping Address') }}</span>
</label>
</div> </div>
<div class="mb-3" data-section="billing-address"> <div class="mb-3 frappe-card p-5" data-section="billing-address">
<h6 class="text-uppercase">{{ _("Billing Address") }}</h6> <h6>{{ _("Billing Address") }}</h6>
<div class="row no-gutters" data-fieldname="customer_address"> <hr>
{% for address in billing_addresses %} {% for address in billing_addresses %}
<div class="mr-3 mb-3 w-25" data-address-name="{{address.name}}" data-address-type="billing" {% if doc.customer_address == address.name %} data-active {% endif %}> {% if doc.customer_address == address.name %}
<div class="row no-gutters" data-fieldname="customer_address">
<div class="w-100 address-container" data-address-name="{{address.name}}" data-address-type="billing" data-active>
{% include "templates/includes/cart/address_card.html" %} {% include "templates/includes/cart/address_card.html" %}
</div> </div>
</div>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
</div> <button class="btn btn-outline-primary btn-sm mt-1 btn-new-address bg-white">{{ _("Add a new address") }}</button>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="input_same_billing" checked>
<label class="custom-control-label" for="input_same_billing">{{ _('Billing Address is same as Shipping Address') }}</label>
</div>
<button class="btn btn-outline-primary btn-sm mt-3 btn-new-address">{{ _("Add a new address") }}</button>
<script> <script>
frappe.ready(() => { frappe.ready(() => {
@ -55,6 +63,7 @@ frappe.ready(() => {
}); });
$('.btn-new-address').click(() => { $('.btn-new-address').click(() => {
console.log('clicked');
const d = new frappe.ui.Dialog({ const d = new frappe.ui.Dialog({
title: __('New Address'), title: __('New Address'),
fields: [ fields: [
@ -168,5 +177,12 @@ frappe.ready(() => {
function toggle_billing_address_section(flag) { function toggle_billing_address_section(flag) {
$('[data-section="billing-address"]').toggle(flag); $('[data-section="billing-address"]').toggle(flag);
} }
$('.btn-change-address').click(() => {
// const d = new frappe.ui.Dialog({
// })
// d.show();
});
}); });
</script> </script>

View File

@ -0,0 +1,4 @@
<div class="mb-3 frappe-card p-5" data-section="shipping-address">
<h6>{{ _("Shipping Address") }}</h6>
</div>

View File

@ -1,15 +1,15 @@
{% for d in doc.items %} {% for d in doc.items %}
<tr data-name="{{ d.name }}"> <tr data-name="{{ d.name }}">
<td> <td>
<div class="font-weight-bold"> <div class="item-title mb-1">
{{ d.item_name }} {{ d.item_name }}
</div> </div>
<div> <div class="item-subtitle">
{{ d.item_code }} {{ d.item_code }}
</div> </div>
{%- set variant_of = frappe.db.get_value('Item', d.item_code, 'variant_of') %} {%- set variant_of = frappe.db.get_value('Item', d.item_code, 'variant_of') %}
{% if variant_of %} {% if variant_of %}
<span class="text-muted"> <span class="item-subtitle">
{{ _('Variant of') }} <a href="{{frappe.db.get_value('Item', variant_of, 'route')}}">{{ variant_of }}</a> {{ _('Variant of') }} <a href="{{frappe.db.get_value('Item', variant_of, 'route')}}">{{ variant_of }}</a>
</span> </span>
{% endif %} {% endif %}
@ -20,20 +20,20 @@
<td class="text-right"> <td class="text-right">
<div class="input-group number-spinner"> <div class="input-group number-spinner">
<span class="input-group-prepend d-none d-sm-inline-block"> <span class="input-group-prepend d-none d-sm-inline-block">
<button class="btn btn-outline-secondary cart-btn" data-dir="dwn"></button> <button class="btn cart-btn" data-dir="dwn"></button>
</span> </span>
<input class="form-control text-right cart-qty border-secondary" value="{{ d.get_formatted('qty') }}" data-item-code="{{ d.item_code }}"> <input class="form-control text-center cart-qty" value="{{ d.get_formatted('qty') }}" data-item-code="{{ d.item_code }}">
<span class="input-group-append d-none d-sm-inline-block"> <span class="input-group-append d-none d-sm-inline-block">
<button class="btn btn-outline-secondary cart-btn" data-dir="up">+</button> <button class="btn cart-btn" data-dir="up">+</button>
</span> </span>
</div> </div>
</td> </td>
{% if cart_settings.enable_checkout %} {% if cart_settings.enable_checkout %}
<td class="text-right"> <td class="text-right item-subtotal">
<div> <div>
{{ d.get_formatted('amount') }} {{ d.get_formatted('amount') }}
</div> </div>
<span class="text-muted"> <span class="item-rate">
{{ _('Rate:') }} {{ d.get_formatted('rate') }} {{ _('Rate:') }} {{ d.get_formatted('rate') }}
</span> </span>
</td> </td>

View File

@ -90,6 +90,10 @@
<div class="card {{ align_items_class }}"> <div class="card {{ align_items_class }}">
{% if image %} {% if image %}
<img class="card-img" src="{{ image }}" alt="{{ title }}"> <img class="card-img" src="{{ image }}" alt="{{ title }}">
{% else %}
<div class="card-img-top no-image">
{{ frappe.utils.get_abbr(title) }}
</div>
{% endif %} {% endif %}
{{ item_card_body(title, description, url, rate, category, is_featured, align) }} {{ item_card_body(title, description, url, rate, category, is_featured, align) }}
</div> </div>

View File

@ -2,9 +2,11 @@
{% block navbar_right_extension %} {% block navbar_right_extension %}
<li class="shopping-cart cart-icon hidden"> <li class="shopping-cart cart-icon hidden">
<a href="/cart" class="nav-link"> <a class="nav-link" href="/cart">
{{ _("Cart") }} <svg class="icon icon-lg">
<span class="badge badge-primary" id="cart-count"></span> <use href="#icon-assets"></use>
</svg>
<span class="badge badge-primary cart-badge" id="cart-count"></span>
</a> </a>
</li> </li>
{% endblock %} {% endblock %}

View File

@ -88,10 +88,11 @@
{% endif %} {% endif %}
<tr> <tr>
<th class="text-right" colspan="2"> <th></th>
<th class="item-grand-total">
{{ _("Grand Total") }} {{ _("Grand Total") }}
</th> </th>
<th class="text-right"> <th class="text-right item-grand-total">
{{ doc.get_formatted("grand_total") }} {{ doc.get_formatted("grand_total") }}
</th> </th>
</tr> </tr>

View File

@ -2,7 +2,7 @@
{% block title %} {{ _("Shopping Cart") }} {% endblock %} {% block title %} {{ _("Shopping Cart") }} {% endblock %}
{% block header %}<h1>{{ _("Shopping Cart") }}</h1>{% endblock %} {% block header %}<h3 class="shopping-cart-header mt-2 mb-6">{{ _("Shopping Cart") }}</h1>{% endblock %}
<!-- <!--
{% block script %} {% block script %}
@ -18,15 +18,20 @@
{% from "templates/includes/macros.html" import item_name_and_description %} {% from "templates/includes/macros.html" import item_name_and_description %}
<div class="cart-container">
<div id="cart-error" class="alert alert-danger" style="display: none;"></div>
{% if doc.items %} {% if doc.items %}
<table class="table table-bordered mt-3"> <div class="cart-container">
<div class="row m-0">
<div class="col-md-8 frappe-card p-5">
<div>
<div id="cart-error" class="alert alert-danger" style="display: none;"></div>
<div class="cart-items-header">
{{ _('Items') }}
</div>
<table class="table mt-3 cart-table">
<thead> <thead>
<tr> <tr>
<th width="60%">{{ _('Item') }}</th> <th width="60%">{{ _('Item') }}</th>
<th width="20%" class="text-right">{{ _('Quantity') }}</th> <th width="20%">{{ _('Quantity') }}</th>
{% if cart_settings.enable_checkout %} {% if cart_settings.enable_checkout %}
<th width="20%" class="text-right">{{ _('Subtotal') }}</th> <th width="20%" class="text-right">{{ _('Subtotal') }}</th>
{% endif %} {% endif %}
@ -41,10 +46,20 @@
</tfoot> </tfoot>
{% endif %} {% endif %}
</table> </table>
</div>
<div class="row">
<div class="col-4">
{% if cart_settings.enable_checkout %}
<a class="btn btn-outline-primary" href="/orders">
{{ _('See past orders') }}
</a>
{% else %} {% else %}
<p class="text-muted">{{ _('Your cart is Empty') }}</p> <a class="btn btn-outline-primary" href="/quotations">
{{ _('See past quotations') }}
</a>
{% endif %} {% endif %}
</div>
<div class="col-8">
{% if doc.items %} {% if doc.items %}
<div class="place-order-container"> <div class="place-order-container">
{% if cart_settings.enable_checkout %} {% if cart_settings.enable_checkout %}
@ -58,6 +73,9 @@
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
</div>
</div>
{% if doc.items %} {% if doc.items %}
{% if doc.tc_name %} {% if doc.tc_name %}
@ -86,26 +104,33 @@
</script> </script>
</div> </div>
{% endif %} {% endif %}
</div>
<div class="cart-addresses mt-5"> <div class="col-md-4">
<div class="cart-addresses">
{% include "templates/includes/cart/cart_address.html" %} {% include "templates/includes/cart/cart_address.html" %}
</div> </div>
</div>
{% endif %} {% endif %}
</div> </div>
</div>
<div class="row mt-5"> {% else %}
<div class="col-12"> <div class="cart-empty frappe-card">
<div class="cart-empty-state">
<img src="/assets/erpnext/images/ui-states/cart-empty-state.png" alt="Empty State">
</div>
<div class="cart-empty-message mt-4">{{ _('Your cart is Empty') }}</p>
{% if cart_settings.enable_checkout %} {% if cart_settings.enable_checkout %}
<a href="/orders"> <a class="btn btn-outline-primary" href="/orders">
{{ _('See past orders') }} {{ _('See past orders') }}
</a> </a>
{% else %} {% else %}
<a href="/quotations"> <a class="btn btn-outline-primary" href="/quotations">
{{ _('See past quotations') }} {{ _('See past quotations') }}
</a> </a>
{% endif %} {% endif %}
</div> </div>
</div> {% endif %}
{% endblock %} {% endblock %}

View File

@ -137,13 +137,15 @@
</script> </script>
</div> </div>
</div> </div>
<div class="row"> <div class="row product-paging-area mt-5">
<div class="col-12"> <div class="col-3">
</div>
<div class="col-9 text-right">
{% if frappe.form_dict.start|int > 0 %} {% if frappe.form_dict.start|int > 0 %}
<button class="btn btn-outline-secondary btn-prev" data-start="{{ frappe.form_dict.start|int - page_length }}">{{ _("Prev") }}</button> <button class="btn btn-default btn-prev" data-start="{{ frappe.form_dict.start|int - page_length }}">{{ _("Prev") }}</button>
{% endif %} {% endif %}
{% if items|length >= page_length %} {% if items|length >= page_length %}
<button class="btn btn-outline-secondary btn-next" data-start="{{ frappe.form_dict.start|int + page_length }}">{{ _("Next") }}</button> <button class="btn btn-default btn-next" data-start="{{ frappe.form_dict.start|int + page_length }}">{{ _("Next") }}</button>
{% endif %} {% endif %}
</div> </div>
</div> </div>