feat: pos item details with new ui

This commit is contained in:
Saqib Ansari 2020-11-11 22:59:10 +05:30
parent cc208839cf
commit fc3315a6d7
4 changed files with 160 additions and 64 deletions

View File

@ -119,7 +119,6 @@
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: var(--margin-lg);
flex: 1 1 0%;
padding: var(--padding-lg);
padding-top: var(--padding-xs);
@ -471,6 +470,13 @@
background-color: var(--blue-200);
color: white;
}
> .edit-cart-btn {
@extend .primary-action;
display: none;
background-color: var(--gray-100);
font-weight: 500;
}
}
> .numpad-section {
@ -542,7 +548,7 @@
> .invoice-name-date {
display: flex;
flex-direction: column;
justify-content: end;
justify-content: flex-end;
> .invoice-name {
@extend .nowrap;
@ -580,4 +586,108 @@
}
}
}
> .item-details-container {
@extend .pos-card;
grid-column: span 4 / span 4;
display: none;
flex-direction: column;
padding: var(--padding-lg);
padding-top: var(--padding-md);
> .item-details-header {
display: flex;
justify-content: space-between;
margin-bottom: var(--margin-md);
> .close-btn {
@extend .pointer-no-select;
}
}
> .item-display {
display: flex;
> .item-name-desc-price {
flex: 1 1 0%;
display: flex;
flex-direction: column;
justify-content: flex-end;
margin-right: var(--margin-md);
> .item-name {
font-size: var(--text-3xl);
font-weight: 600;
}
> .item-desc {
font-size: var(--text-md);
font-weight: 500;
}
> .item-price {
font-size: var(--text-3xl);
font-weight: 700;
}
}
> .item-image {
display: flex;
align-items: center;
justify-content: center;
width: 11rem;
height: 11rem;
border-radius: var(--border-radius-md);
margin-left: var(--margin-md);
color: var(--gray-500);
> img {
@extend .image;
}
> .item-abbr {
@extend .abbr;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--border-radius-md);
font-size: var(--text-3xl);
width: 100%;
height: 100%;
}
}
}
> .discount-section {
display: flex;
align-items: center;
margin-bottom: var(--margin-sm);
> .item-rate {
font-weight: 500;
margin-right: var(--margin-sm);
text-decoration: line-through;
}
> .item-discount {
padding: 3px var(--padding-sm);
border-radius: var(--border-radius-sm);
background-color: var(--green-100);
color: var(--green-700);
font-size: var(--text-sm);
font-weight: 700;
}
}
> .form-container {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
column-gap: var(--padding-xs);
> .auto-fetch-btn {
@extend .pointer-no-select;
margin: auto var(--margin-xs);
}
}
}
}

View File

@ -95,9 +95,7 @@ erpnext.PointOfSale.ItemCart = class {
<div>0.00</div>
</div>
<div class="checkout-btn">Checkout</div>
<div class="edit-cart-btn flex items-center justify-center h-16 pr-8 pl-8 text-center text-grey no-select pointer d-none text-md text-bold">
Edit Cart
</div>`
<div class="edit-cart-btn">Edit Cart</div>`
)
this.$add_discount_elem = this.$component.find(".add-discount");
@ -176,7 +174,7 @@ erpnext.PointOfSale.ItemCart = class {
});
this.$component.on('click', '.checkout-btn', function() {
if (!$(this).hasClass('bg-primary')) return;
if ($(this).attr('style').indexOf('--blue-500') == -1) return;
me.events.checkout();
me.toggle_checkout_btn(false);
@ -265,8 +263,9 @@ erpnext.PointOfSale.ItemCart = class {
toggle_item_highlight(item) {
const $cart_item = $(item);
const item_is_highlighted = $cart_item.attr("style") == "background-color:var(--gray-50);";
if (!item) {
if (!item || item_is_highlighted) {
this.item_is_selected = false;
this.$cart_container.find('.cart-item-wrapper').css("background-color", "");
} else {
@ -522,7 +521,7 @@ erpnext.PointOfSale.ItemCart = class {
const $item = this.get_cart_item(item);
if (remove_item) {
$item && $item.remove();
$item && $item.next().remove() && $item.remove();
} else {
const { item_code, batch_no, uom } = item;
const search_field = batch_no ? 'batch_no' : 'item_code';

View File

@ -16,35 +16,36 @@ erpnext.PointOfSale.ItemDetails = class {
prepare_dom() {
this.wrapper.append(
`<section class="col-span-4 flex shadow rounded item-details bg-white mx-h-70 h-100 d-none"></section>`
`<section class="item-details-container"></section>`
)
this.$component = this.wrapper.find('.item-details');
this.$component = this.wrapper.find('.item-details-container');
}
init_child_components() {
this.$component.html(
`<div class="details-container flex flex-col p-8 rounded w-full">
<div class="flex justify-between mb-2">
<div class="text-grey">ITEM DETAILS</div>
<div class="close-btn text-grey hover-underline pointer no-select">Close</div>
`<div class="item-details-header">
<div class="label">Item Details</div>
<div class="close-btn">
<svg width="32" height="32" viewBox="0 0 14 14" fill="none">
<path d="M4.93764 4.93759L7.00003 6.99998M9.06243 9.06238L7.00003 6.99998M7.00003 6.99998L4.93764 9.06238L9.06243 4.93759" stroke="#8D99A6"/>
</svg>
</div>
<div class="item-defaults flex">
<div class="flex-1 flex flex-col justify-end mr-4 mb-2">
<div class="item-name text-xl font-weight-450"></div>
<div class="item-description text-md-0 text-grey-200"></div>
<div class="item-price text-xl font-bold"></div>
</div>
<div class="item-image flex items-center justify-center w-46 h-46 bg-light-grey rounded ml-4 text-6xl text-grey-100"></div>
</div>
<div class="item-display">
<div class="item-name-desc-price">
<div class="item-name"></div>
<div class="item-desc"></div>
<div class="item-price"></div>
</div>
<div class="discount-section flex items-center"></div>
<div class="text-grey mt-4 mb-6">STOCK DETAILS</div>
<div class="form-container grid grid-cols-2 row-gap-2 col-gap-4 grid-auto-row"></div>
</div>`
<div class="item-image"></div>
</div>
<div class="discount-section"></div>
<div class="form-container"></div>`
)
this.$item_name = this.$component.find('.item-name');
this.$item_description = this.$component.find('.item-description');
this.$item_description = this.$component.find('.item-desc');
this.$item_price = this.$component.find('.item-price');
this.$item_image = this.$component.find('.item-image');
this.$form_container = this.$component.find('.form-container');
@ -52,7 +53,7 @@ erpnext.PointOfSale.ItemDetails = class {
}
toggle_item_details_section(item) {
const { item_code, batch_no, uom } = this.current_item;
const { item_code, batch_no, uom } = this.current_item;
const item_code_is_same = item && item_code === item.item_code;
const batch_is_same = item && batch_no == item.batch_no;
const uom_is_same = item && uom === item.uom;
@ -104,11 +105,11 @@ erpnext.PointOfSale.ItemDetails = class {
}
render_dom(item) {
let { item_code ,item_name, description, image, price_list_rate } = item;
let { item_name, description, image, price_list_rate } = item;
function get_description_html() {
if (description) {
description = description.indexOf('...') === -1 && description.length > 75 ? description.substr(0, 73) + '...' : description;
description = description.indexOf('...') === -1 && description.length > 140 ? description.substr(0, 139) + '...' : description;
return description;
}
return ``;
@ -118,11 +119,9 @@ erpnext.PointOfSale.ItemDetails = class {
this.$item_description.html(get_description_html());
this.$item_price.html(format_currency(price_list_rate, this.currency));
if (image) {
this.$item_image.html(
`<img class="h-full" src="${image}" alt="${image}" style="object-fit: cover;">`
);
this.$item_image.html(`<img src="${image}" alt="${image}">`);
} else {
this.$item_image.html(frappe.get_abbr(item_code));
this.$item_image.html(`<div class="item-abbr">${frappe.get_abbr(item_name)}</div>`);
}
}
@ -130,12 +129,8 @@ erpnext.PointOfSale.ItemDetails = class {
render_discount_dom(item) {
if (item.discount_percentage) {
this.$dicount_section.html(
`<div class="text-grey line-through mr-4 text-md mb-2">
${format_currency(item.price_list_rate, this.currency)}
</div>
<div class="p-1 pr-3 pl-3 rounded w-fit text-bold bg-green-200 mb-2">
${item.discount_percentage}% off
</div>`
`<div class="item-rate">${format_currency(item.price_list_rate, this.currency)}</div>
<div class="item-discount">${item.discount_percentage}% off</div>`
)
this.$item_price.html(format_currency(item.rate, this.currency));
} else {
@ -149,9 +144,7 @@ erpnext.PointOfSale.ItemDetails = class {
fields_to_display.forEach((fieldname, idx) => {
this.$form_container.append(
`<div class="">
<div class="item_detail_field ${fieldname}-control" data-fieldname="${fieldname}"></div>
</div>`
`<div class="${fieldname}-control" data-fieldname="${fieldname}"></div>`
)
const field_meta = this.item_meta.fields.find(df => df.fieldname === fieldname);
@ -185,22 +178,15 @@ erpnext.PointOfSale.ItemDetails = class {
make_auto_serial_selection_btn(item) {
if (item.has_serial_no) {
this.$form_container.append(
`<div class="grid-filler no-select"></div>`
)
if (!item.has_batch_no) {
this.$form_container.append(
`<div class="grid-filler no-select"></div>`
)
}
this.$form_container.append(
`<div class="auto-fetch-btn bg-grey-100 border border-grey text-bold rounded pt-3 pb-3 pl-6 pr-8 text-grey pointer no-select mt-2"
style="height: 3.3rem">
Auto Fetch Serial Numbers
</div>`
`<div class="btn btn-sm btn-secondary auto-fetch-btn">Auto Fetch Serial Numbers</div>`
)
this.$form_container.find('.serial_no-control').find('textarea').css('height', '9rem');
this.$form_container.find('.serial_no-control').parent().addClass('row-span-2');
this.$form_container.find('.serial_no-control').find('textarea').css('height', '6rem');
}
}
@ -294,8 +280,13 @@ erpnext.PointOfSale.ItemDetails = class {
}
frappe.model.on("POS Invoice Item", "*", (fieldname, value, item_row) => {
const field_control = me[`${fieldname}_control`];
if (field_control) {
const field_control = this[`${fieldname}_control`];
const { item_code, batch_no, uom } = this.current_item;
const item_code_is_same = item_code === item_row.item_code;
const batch_is_same = batch_no == item_row.batch_no;
const uom_is_same = uom === item_row.uom;
if (field_control && item_code_is_same && batch_is_same && uom_is_same) {
field_control.set_value(value);
cur_pos.update_cart_html(item_row);
}
@ -409,6 +400,6 @@ erpnext.PointOfSale.ItemDetails = class {
}
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');
}
}

View File

@ -248,20 +248,16 @@ erpnext.PointOfSale.ItemSelector = class {
resize_selector(minimize) {
minimize ?
this.$component.find('.search-field').removeClass('mr-8') :
this.$component.find('.search-field').addClass('mr-8');
minimize ?
this.$component.find('.filter-section').addClass('flex-col') :
this.$component.find('.filter-section').removeClass('flex-col');
this.$component.find('.filter-section').css('grid-template-columns', 'repeat(1, minmax(0, 1fr))') :
this.$component.find('.filter-section').css('grid-template-columns', 'repeat(12, minmax(0, 1fr))');
minimize ?
this.$component.removeClass('col-span-6').addClass('col-span-2') :
this.$component.removeClass('col-span-2').addClass('col-span-6')
this.$component.css('grid-column', 'span 2 / span 2') :
this.$component.css('grid-column', 'span 6 / span 6')
minimize ?
this.$items_container.removeClass('grid-cols-4').addClass('grid-cols-1') :
this.$items_container.removeClass('grid-cols-1').addClass('grid-cols-4')
this.$items_container.css('grid-template-columns', 'repeat(1, minmax(0, 1fr))') :
this.$items_container.css('grid-template-columns', 'repeat(4, minmax(0, 1fr))')
}
toggle_component(show) {