diff --git a/erpnext/public/scss/point-of-sale.scss b/erpnext/public/scss/point-of-sale.scss index 4d5bc21de5a..37ca8fd13d2 100644 --- a/erpnext/public/scss/point-of-sale.scss +++ b/erpnext/public/scss/point-of-sale.scss @@ -52,9 +52,31 @@ } .seperator { + margin-left: var(--margin-sm); + margin-right: var(--margin-sm); border-bottom: 1px solid var(--gray-300); } + .primary-action { + @extend .pointer-no-select; + display: flex; + align-items: center; + justify-content: center; + padding: var(--padding-sm); + margin: var(--margin-xs); + margin-top: var(--margin-sm); + margin-bottom: var(--margin-xs); + border-radius: var(--border-radius-md); + font-size: var(--text-lg); + font-weight: 700; + } + + .highlighted-numpad-btn { + box-shadow: inset 0 0px 4px 0px rgba(0, 0, 0, 0.15) !important; + font-weight: 700; + background-color: var(--gray-50); + } + > .items-selector { grid-column: span 6 / span 6; display: flex; @@ -255,7 +277,254 @@ } > .cart-container { + @extend .pos-card; + display: flex; + flex-direction: column; + align-items: center; + margin-top: var(--margin-md); + position: relative; + height: 100%; + > .abs-cart-container { + position: absolute; + display: flex; + flex-direction: column; + padding: var(--padding-md); + width: 100%; + height: 100%; + + > .cart-label { + @extend .label; + padding-bottom: var(--padding-md); + padding-left: var(--margin-sm); + } + + > .cart-header { + display: flex; + width: 100%; + font-size: var(--text-md); + padding-left: var(--padding-xs); + padding-right: var(--padding-xs); + padding-bottom: var(--padding-md); + + > .name-header { + flex: 1 1 0%; + margin-left: var(--margin-xs); + } + + > .qty-header { + margin-right: var(--margin-lg); + } + + > .rate-amount-header { + margin-right: var(--margin-xs); + text-align: right; + } + } + + .no-item-wrapper { + display: flex; + align-items: center; + justify-content: center; + background-color: var(--gray-50); + border-radius: var(--border-radius-md); + font-size: var(--text-md); + font-weight: 500; + width: 100%; + height: 100%; + } + + > .cart-items-section { + display: flex; + flex-direction: column; + flex: 1 1 0%; + overflow-y: scroll; + + > .cart-item-wrapper { + @extend .pointer-no-select; + display: flex; + align-items: center; + padding: var(--padding-sm); + border-radius: var(--border-radius-md); + + &:hover { + background-color: var(--gray-50); + } + + > .item-image { + display: flex; + align-items: center; + justify-content: center; + width: 2rem; + height: 2rem; + border-radius: var(--border-radius-md); + color: var(--gray-500); + margin-right: var(--margin-md); + + > img { + @extend .image; + } + } + + > .item-abbr { + @extend .abbr; + font-size: var(--text-lg); + } + + + > .item-name-desc { + @extend .nowrap; + display: flex; + flex-direction: column; + flex: 1 1 0%; + flex-shrink: 1; + + > .item-name { + font-weight: 700; + } + + > .item-desc { + font-size: var(--text-sm); + color: var(--gray-600); + font-weight: 500; + } + } + + > .item-qty-rate { + display: flex; + flex-shrink: 0; + text-align: right; + margin-left: var(--margin-md); + + > .item-qty { + display: flex; + align-items: center; + margin-right: var(--margin-lg); + font-weight: 700; + } + + > .item-rate-amount { + display: flex; + flex-direction: column; + flex-shrink: 0; + text-align: right; + + > .item-rate { + font-weight: 700; + } + + > .item-amount { + font-size: var(--text-md); + font-weight: 600; + } + } + } + + } + } + + > .cart-totals-section { + display: flex; + flex-direction: column; + flex-shrink: 0; + width: 100%; + margin-top: var(--margin-md); + + > .net-total-container { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--padding-sm); + font-weight: 500; + font-size: var(--text-md); + } + + > .taxes-container { + display: none; + align-items: center; + justify-content: space-between; + padding: var(--padding-sm); + font-weight: 500; + font-size: var(--text-md); + + > .tax-label { + display: flex; + align-items: center; + + > .tax-desc { + margin-left: var(--margin-md); + } + } + } + + > .grand-total-container { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--padding-sm); + font-weight: 700; + font-size: var(--text-lg); + } + + > .checkout-btn { + @extend .primary-action; + background-color: var(--blue-200); + color: white; + } + } + + > .numpad-section { + display: none; + flex-direction: column; + flex-shrink: 0; + margin-top: var(--margin-sm); + padding: var(--padding-sm); + padding-bottom: 0px; + width: 100%; + + > .numpad-totals { + display: flex; + justify-content: space-between; + margin-bottom: var(--margin-md); + font-size: var(--text-md); + font-weight: 700; + } + + > .numpad-container { + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + gap: var(--margin-md); + margin-bottom: var(--margin-md); + + > .numpad-btn { + @extend .pointer-no-select; + border-radius: var(--border-radius-md); + display: flex; + align-items: center; + justify-content: center; + padding: var(--padding-md); + box-shadow: var(--shadow-sm); + } + + > .col-span-2 { + grid-column: span 2 / span 2; + } + + > .remove-btn { + font-weight: 700; + color: var(--red-500); + } + } + + > .checkout-btn { + @extend .primary-action; + margin: 0px; + margin-bottom: var(--margin-sm); + background-color: var(--blue-200); + color: white; + } + } + } } } diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js index 11453f7cf07..e0a2ee7767e 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_cart.js +++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js @@ -43,16 +43,17 @@ erpnext.PointOfSale.ItemCart = class { init_cart_components() { this.$component.append( - `
-
-
-
Item
-
Qty
-
Amount
+ `
+
+
Item Cart
+
+
Item
+
Qty
+
Amount
-
-
-
+
+
+
` ); @@ -71,13 +72,10 @@ erpnext.PointOfSale.ItemCart = class { } make_no_items_placeholder() { - this.$cart_header.addClass('d-none'); + this.$cart_header.css('display', 'none'); this.$cart_items_wrapper.html( - `
-
No items in cart
-
` - ) - this.$cart_items_wrapper.addClass('mt-4 border-grey border-dashed'); + `
No items in cart
` + ); } make_cart_totals_section() { @@ -87,30 +85,18 @@ erpnext.PointOfSale.ItemCart = class { `
+ Add Discount
-
-
-
-
Net Total
-
-
-
0.00
-
-
-
-
-
-
Grand Total
-
-
-
0.00
-
-
-
- Checkout -
-
- Edit Cart -
+
+
Net Total
+
0.00
+
+
+
+
Grand Total
+
0.00
+
+
Checkout
+
+ Edit Cart
` ) @@ -136,23 +122,20 @@ erpnext.PointOfSale.ItemCart = class { [ '', '', '', 'col-span-2' ], [ '', '', '', 'col-span-2' ], [ '', '', '', 'col-span-2' ], - [ '', '', '', 'col-span-2 text-bold text-danger' ] + [ '', '', '', 'col-span-2 remove-btn' ] ], fieldnames_map: { 'Quantity': 'qty', 'Discount': 'discount_percentage' } }) this.$numpad_section.prepend( - `
+ `
` ) this.$numpad_section.append( - `
- Checkout -
` + `
Checkout
` ) } @@ -167,10 +150,9 @@ erpnext.PointOfSale.ItemCart = class { }); this.$customer_section.on('click', '.customer-display', function(e) { - // don't triggger the event if .reset-customer-btn btn is clicked which is under .customer-header - if ($(e.target).closest('.reset-customer-btn').length) return; + if ($(this).find('.reset-customer-btn').length == 0) return; - const show = !me.$cart_container.hasClass('d-none'); + const show = me.$cart_container.is(':visible'); me.toggle_customer_info(show); }); @@ -283,20 +265,15 @@ erpnext.PointOfSale.ItemCart = class { toggle_item_highlight(item) { const $cart_item = $(item); - const item_is_highlighted = $cart_item.hasClass("shadow-base"); - if (!item || item_is_highlighted) { + if (!item) { this.item_is_selected = false; - this.$cart_container.find('.cart-item-wrapper').removeClass("shadow-base").css("opacity", "1"); + this.$cart_container.find('.cart-item-wrapper').css("background-color", ""); } else { - $cart_item.addClass("shadow-base"); + $cart_item.css("background-color", "var(--gray-50)"); this.item_is_selected = true; - this.$cart_container.find('.cart-item-wrapper').css("opacity", "1"); - this.$cart_container.find('.cart-item-wrapper').not(item).removeClass("shadow-base").css("opacity", "0.65"); + this.$cart_container.find('.cart-item-wrapper').not(item).css("background-color", ""); } - // highlight with inner shadow-base - // $cart_item.addClass("shadow-base-inner bg-selected"); - // me.$cart_container.find('.cart-item-wrapper').not(this).removeClass("shadow-base-inner bg-selected"); } make_customer_selector() { @@ -464,6 +441,7 @@ erpnext.PointOfSale.ItemCart = class { } } + get_customer_image() { const { customer, image } = this.customer_info || {}; if (image) { @@ -485,57 +463,47 @@ erpnext.PointOfSale.ItemCart = class { render_net_total(value) { const currency = this.events.get_frm().doc.currency; - this.$totals_section.find('.net-total').html( - `
-
Net Total
-
-
-
${format_currency(value, currency)}
-
` + this.$totals_section.find('.net-total-container').html( + `
Net Total
${format_currency(value, currency)}
` ) - this.$numpad_section.find('.numpad-net-total').html(`Net Total: ${format_currency(value, currency)}`) + this.$numpad_section.find('.numpad-net-total').html( + `
Net Total: ${format_currency(value, currency)}
` + ); } render_grand_total(value) { const currency = this.events.get_frm().doc.currency; - this.$totals_section.find('.grand-total').html( - `
-
Grand Total
-
-
-
${format_currency(value, currency)}
-
` + this.$totals_section.find('.grand-total-container').html( + `
Grand Total
${format_currency(value, currency)}
` ) - this.$numpad_section.find('.numpad-grand-total').html(`Grand Total: ${format_currency(value, currency)}`) + this.$numpad_section.find('.numpad-grand-total').html( + `
Grand Total: ${format_currency(value, currency)}
` + ) } render_taxes(value, taxes) { if (taxes.length) { const currency = this.events.get_frm().doc.currency; - this.$totals_section.find('.taxes').html( - `
-
-
Tax Charges
-
- ${ - taxes.map((t, i) => { - let margin_left = ''; - if (i !== 0) margin_left = 'ml-2'; - const description = /[0-9]+/.test(t.description) ? t.description : `${t.description} @ ${t.rate}%`; - return `${description}` - }).join('') - } -
+ this.$totals_section.find('.taxes-container').css('display', 'flex').html( + `
+
Tax Charges
+
+ ${ + taxes.map((t, i) => { + let margin_left = ''; + if (i !== 0) margin_left = '10px'; + const description = /[0-9]+/.test(t.description) ? t.description : `${t.description} @ ${t.rate}%`; + return `${description}` + }).join('') + }
-
-
${format_currency(value, currency)}
-
-
` +
+
${format_currency(value, currency)}
` ) } else { - this.$totals_section.find('.taxes').html('') + this.$totals_section.find('.taxes-container').css('display', 'none').html(''); } } @@ -564,9 +532,9 @@ erpnext.PointOfSale.ItemCart = class { this.render_cart_item(item_row, $item); } - const no_of_cart_items = this.$cart_items_wrapper.children().length; - no_of_cart_items > 0 && this.highlight_checkout_btn(no_of_cart_items > 0); - + const no_of_cart_items = this.$cart_items_wrapper.find('.cart-item-wrapper').length; + this.highlight_checkout_btn(no_of_cart_items > 0); + this.update_empty_cart_section(no_of_cart_items); } @@ -576,32 +544,33 @@ erpnext.PointOfSale.ItemCart = class { if (!$item_to_update.length) { this.$cart_items_wrapper.append( - `
-
` +
+
` ) $item_to_update = this.get_cart_item(item_data); } $item_to_update.html( - `
-
+ `${get_item_image_html()} +
+
${item_data.item_name}
${get_description_html()}
- ${get_rate_discount_html()} -
` + ${get_rate_discount_html()}` ) set_dynamic_rate_header_width(); this.scroll_to_item($item_to_update); function set_dynamic_rate_header_width() { - const rate_cols = Array.from(me.$cart_items_wrapper.find(".rate-col")); - me.$cart_header.find(".rate-list-header").css("width", ""); - me.$cart_items_wrapper.find(".rate-col").css("width", ""); + const rate_cols = Array.from(me.$cart_items_wrapper.find(".item-rate-amount")); + me.$cart_header.find(".rate-amount-header").css("width", ""); + me.$cart_items_wrapper.find(".item-rate-amount").css("width", ""); let max_width = rate_cols.reduce((max_width, elm) => { if ($(elm).width() > max_width) max_width = $(elm).width(); @@ -611,30 +580,26 @@ erpnext.PointOfSale.ItemCart = class { max_width += 1; if (max_width == 1) max_width = ""; - me.$cart_header.find(".rate-list-header").css("width", max_width); - me.$cart_items_wrapper.find(".rate-col").css("width", max_width); + me.$cart_header.find(".rate-amount-header").css("width", max_width); + me.$cart_items_wrapper.find(".item-rate-amount").css("width", max_width); } function get_rate_discount_html() { if (item_data.rate && item_data.amount && item_data.rate !== item_data.amount) { return ` -
-
- ${item_data.qty || 0} -
-
-
${format_currency(item_data.amount, currency)}
-
${format_currency(item_data.rate, currency)}
+
+
${item_data.qty || 0}
+
+
${format_currency(item_data.amount, currency)}
+
${format_currency(item_data.rate, currency)}
` } else { return ` -
-
- ${item_data.qty || 0} -
-
-
${format_currency(item_data.rate, currency)}
+
+
${item_data.qty || 0}
+
+
${format_currency(item_data.rate, currency)}
` } @@ -650,10 +615,19 @@ erpnext.PointOfSale.ItemCart = class { } } item_data.description = frappe.ellipsis(item_data.description, 45); - return `
${item_data.description}
` + return `
${item_data.description}
` } return ``; } + + function get_item_image_html() { + const { image, item_name } = item_data; + if (image) { + return `
${image}
` + } else { + return `
${frappe.get_abbr(item_name)}
` + } + } } scroll_to_item($item) { @@ -669,20 +643,23 @@ erpnext.PointOfSale.ItemCart = class { toggle_checkout_btn(show_checkout) { if (show_checkout) { - this.$totals_section.find('.checkout-btn').removeClass('d-none'); - this.$totals_section.find('.edit-cart-btn').addClass('d-none'); + this.$totals_section.find('.checkout-btn').css('display', 'flex'); + this.$totals_section.find('.edit-cart-btn').css('display', 'none'); } else { - this.$totals_section.find('.checkout-btn').addClass('d-none'); - this.$totals_section.find('.edit-cart-btn').removeClass('d-none'); + this.$totals_section.find('.checkout-btn').css('display', 'none'); + this.$totals_section.find('.edit-cart-btn').css('display', 'flex'); } } highlight_checkout_btn(toggle) { - const has_primary_class = this.$totals_section.find('.checkout-btn').hasClass('bg-primary'); - if (toggle && !has_primary_class) { - this.$totals_section.find('.checkout-btn').addClass('bg-primary text-white text-lg'); - } else if (!toggle && has_primary_class) { - this.$totals_section.find('.checkout-btn').removeClass('bg-primary text-white text-lg'); + if (toggle) { + this.$cart_container.find('.checkout-btn').css({ + 'background-color': 'var(--blue-500)' + }); + } else { + this.$cart_container.find('.checkout-btn').css({ + 'background-color': 'var(--blue-200)' + }); } } @@ -690,8 +667,7 @@ erpnext.PointOfSale.ItemCart = class { const $no_item_element = this.$cart_items_wrapper.find('.no-item-wrapper'); // if cart has items and no item is present - no_of_cart_items > 0 && $no_item_element && $no_item_element.remove() - && this.$cart_items_wrapper.removeClass('mt-4 border-grey border-dashed') && this.$cart_header.removeClass('d-none'); + no_of_cart_items > 0 && $no_item_element && $no_item_element.remove() && this.$cart_header.css('display', 'flex'); no_of_cart_items === 0 && !$no_item_element.length && this.make_no_items_placeholder(); } @@ -754,36 +730,36 @@ erpnext.PointOfSale.ItemCart = class { } highlight_numpad_btn($btn, curr_action) { - const curr_action_is_highlighted = $btn.hasClass('shadow-base-inner'); + const curr_action_is_highlighted = $btn.hasClass('highlighted-numpad-btn'); const curr_action_is_action = ['qty', 'discount_percentage', 'rate', 'done'].includes(curr_action); if (!curr_action_is_highlighted) { - $btn.addClass('shadow-base-inner bg-selected'); + $btn.addClass('highlighted-numpad-btn'); } if (this.prev_action === curr_action && curr_action_is_highlighted) { // if Qty is pressed twice - $btn.removeClass('shadow-base-inner bg-selected'); + $btn.removeClass('highlighted-numpad-btn'); } if (this.prev_action && this.prev_action !== curr_action && curr_action_is_action) { // Order: Qty -> Rate then remove Qty highlight const prev_btn = $(`[data-button-value='${this.prev_action}']`); - prev_btn.removeClass('shadow-base-inner bg-selected'); + prev_btn.removeClass('highlighted-numpad-btn'); } if (!curr_action_is_action || curr_action === 'done') { // if numbers are clicked setTimeout(() => { - $btn.removeClass('shadow-base-inner bg-selected'); - }, 100); + $btn.removeClass('highlighted-numpad-btn'); + }, 200); } } toggle_numpad(show) { if (show) { - this.$totals_section.addClass('d-none'); - this.$numpad_section.removeClass('d-none'); + this.$totals_section.css('display', 'none'); + this.$numpad_section.css('display', 'flex'); } else { - this.$totals_section.removeClass('d-none'); - this.$numpad_section.addClass('d-none'); + this.$totals_section.css('display', 'flex'); + this.$numpad_section.css('display', 'none'); } this.reset_numpad(); } @@ -791,7 +767,7 @@ erpnext.PointOfSale.ItemCart = class { reset_numpad() { this.numpad_value = ''; this.prev_action = undefined; - this.$numpad_section.find('.shadow-base-inner').removeClass('shadow-base-inner bg-selected'); + this.$numpad_section.find('.highlighted-numpad-btn').removeClass('highlighted-numpad-btn'); } toggle_numpad_field_edit(fieldname) { @@ -804,7 +780,7 @@ erpnext.PointOfSale.ItemCart = class { if (show) { const { customer } = this.customer_info || {}; - this.$cart_container.addClass('d-none'); + this.$cart_container.css('display', 'none'); this.$customer_section.css({ 'height': '100%', 'padding-top': '0px', @@ -842,7 +818,7 @@ erpnext.PointOfSale.ItemCart = class { this.fetch_customer_transactions(); } else { - this.$cart_container.removeClass('d-none'); + this.$cart_container.css('display', 'flex'); this.$customer_section.css({ 'height': '', 'padding-top': '', @@ -988,20 +964,18 @@ erpnext.PointOfSale.ItemCart = class { this.update_totals_section(frm); if(frm.doc.docstatus === 1) { - this.$totals_section.find('.checkout-btn').addClass('d-none'); - this.$totals_section.find('.edit-cart-btn').addClass('d-none'); - this.$totals_section.find('.grand-total').removeClass('border-b-grey'); + this.$totals_section.find('.checkout-btn').css('display', 'none'); + this.$totals_section.find('.edit-cart-btn').css('display', 'none'); } else { - this.$totals_section.find('.checkout-btn').removeClass('d-none'); - this.$totals_section.find('.edit-cart-btn').addClass('d-none'); - this.$totals_section.find('.grand-total').addClass('border-b-grey'); + this.$totals_section.find('.checkout-btn').css('display', 'flex'); + this.$totals_section.find('.edit-cart-btn').css('display', 'none'); } this.toggle_component(true); } toggle_component(show) { - show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none'); + show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none'); } } diff --git a/erpnext/selling/page/point_of_sale/pos_number_pad.js b/erpnext/selling/page/point_of_sale/pos_number_pad.js index 4b8e8418055..edde7d84dfb 100644 --- a/erpnext/selling/page/point_of_sale/pos_number_pad.js +++ b/erpnext/selling/page/point_of_sale/pos_number_pad.js @@ -25,14 +25,13 @@ erpnext.PointOfSale.NumberPad = class { const fieldname = fieldnames && fieldnames[number] ? fieldnames[number] : typeof number === 'string' ? frappe.scrub(number) : number; - return a2 + `
${number}
` + return a2 + `
${number}
` }, '') }, ''); } this.wrapper.html( - `
+ `
${get_keys()}
` )