[REF] pos*: introduce bootstrap
pos*: point_of_sale,pos_discount,pos_hr,pos_loyalty, pos_restaurant,pos_sale,pos_sale_product_configurator,pos_six Prior to this commit, the point_of_sale module relied on custom CSS. To enhance user experience, increase flexibility, and simplify maintenance, most of the custom css was replaced in this PR with Bootstrap utility classes. Task: 3354582 Authored-by: Xavier Luyckx (xlu) <xlu@odoo.com> Part-of: odoo/odoo#129544 Co-authored-by: vlst <vlst@odoo.com>, Pedram (pebr)
This commit is contained in:
committed by
vlst
co-authored by
vlst <vlst@odoo.com>, Pedram (pebr)
parent
eeee7dc9e7
commit
c087603d0b
@@ -77,16 +77,32 @@
|
||||
|
||||
# Main PoS assets, they are loaded in the PoS UI and in the PoS unit tests
|
||||
'point_of_sale._assets_pos': [
|
||||
# scss variables and utilities
|
||||
'point_of_sale/static/src/scss/pos_variables_extra.scss',
|
||||
# 'preparation_display' bootstrap customization layer
|
||||
'web/static/src/scss/functions.scss',
|
||||
# 'point_of_sale/static/src/scss/primary_variables.scss', TO DO - CREATE
|
||||
|
||||
# 'webclient' bootstrap customization layer
|
||||
('include', 'web._assets_helpers'),
|
||||
'web/static/src/scss/bootstrap_overridden.scss',
|
||||
('include', 'web._assets_backend_helpers'),
|
||||
|
||||
'web/static/src/scss/pre_variables.scss',
|
||||
'web/static/lib/bootstrap/scss/_variables.scss',
|
||||
'web/static/fonts/fonts.scss',
|
||||
|
||||
# Import Bootstrap
|
||||
('include', 'web._assets_bootstrap_backend'),
|
||||
|
||||
# Icons
|
||||
'web/static/src/libs/fontawesome/css/font-awesome.css',
|
||||
'web/static/lib/odoo_ui_icons/*',
|
||||
'web/static/src/webclient/icons.scss',
|
||||
|
||||
# scss variables and utilities
|
||||
'point_of_sale/static/src/scss/pos_variables_extra.scss',
|
||||
'web/static/src/scss/bootstrap_overridden.scss',
|
||||
'web/static/fonts/fonts.scss',
|
||||
'web/static/src/legacy/scss/fontawesome_overridden.scss',
|
||||
|
||||
|
||||
# JS framework
|
||||
'web/static/src/boot.js',
|
||||
'web/static/src/session.js',
|
||||
@@ -228,14 +244,6 @@
|
||||
'web/static/tests/main.js',
|
||||
'web/static/tests/setup.js',
|
||||
|
||||
# These 2 lines below are taken from web.assets_frontend
|
||||
# They're required for the web.frontend_legacy to work properly
|
||||
# It is expected to add other lines coming from the web.assets_frontend
|
||||
# if we need to add more and more legacy stuff that would require other scss or js.
|
||||
('include', 'web._assets_helpers'),
|
||||
'web/static/src/scss/pre_variables.scss',
|
||||
'web/static/lib/bootstrap/scss/_variables.scss',
|
||||
|
||||
('include', 'web.frontend_legacy'),
|
||||
("include", "web.assets_backend_legacy_lazy"),
|
||||
## END copy of web.tests_assets
|
||||
|
||||
@@ -3,20 +3,15 @@
|
||||
|
||||
<t t-name="point_of_sale.ErrorBarcodePopup" owl="1">
|
||||
<div class="popup popup-barcode">
|
||||
<header class="title drag-handle">
|
||||
<span>Unknown Barcode</span>
|
||||
<br />
|
||||
<span class="barcode">
|
||||
<t t-esc="props.code" />
|
||||
</span>
|
||||
<header class="title drag-handle modal-header">
|
||||
<h5 class="modal-title">Unknown Barcode: <span class="fst-italic" t-esc="props.code"/>
|
||||
</h5>
|
||||
</header>
|
||||
<main class="body">
|
||||
<main class="modal-body">
|
||||
<t t-esc="translatedMessage" />
|
||||
</main>
|
||||
<footer class="footer">
|
||||
<div class="button cancel" t-on-click="confirm">
|
||||
Ok
|
||||
</div>
|
||||
<footer class="footer modal-footer">
|
||||
<button type="button" class="btn btn-primary" t-on-click="confirm">Ok</button>
|
||||
</footer>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -4,87 +4,6 @@
|
||||
right: 10px;
|
||||
top: 106px;
|
||||
width: 200px;
|
||||
font-size: 10px;
|
||||
|
||||
background: rgba(0, 0, 0, 0.82);
|
||||
color: white;
|
||||
padding-bottom: 10px;
|
||||
cursor: move;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.debug-widget .toggle {
|
||||
position: absolute;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
padding: 10px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.debug-widget .content {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.debug-widget header {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.debug-widget h1 {
|
||||
background: black;
|
||||
padding-top: 10px;
|
||||
padding-left: 10px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.debug-widget .category {
|
||||
background: black;
|
||||
padding-left: 10px;
|
||||
margin: 0px;
|
||||
font-weight: bold;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.debug-widget .button {
|
||||
padding: 5px;
|
||||
padding-left: 15px;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.debug-widget .button:active {
|
||||
background: rgba(96, 21, 177, 0.45);
|
||||
}
|
||||
|
||||
.debug-widget input {
|
||||
margin-left: 10px;
|
||||
margin-top: 7px;
|
||||
padding: 4px;
|
||||
width: 180px;
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.debug-widget .status {
|
||||
padding: 5px;
|
||||
padding-left: 15px;
|
||||
display: block;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.debug-widget .status.on {
|
||||
background-color: #6cd11d;
|
||||
}
|
||||
|
||||
.debug-widget .event {
|
||||
padding: 5px;
|
||||
padding-left: 15px;
|
||||
display: block;
|
||||
cursor: default;
|
||||
background-color: #1E1E1E;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,88 +3,100 @@
|
||||
|
||||
<t t-name="point_of_sale.DebugWidget" owl="1">
|
||||
<Transition visible="props.state.showWidget" name="'o-fade'" leaveDuration="200" t-slot-scope="transition">
|
||||
<div class="debug-widget" t-att-class="transition.className" t-ref="root" t-att-style="style">
|
||||
<div class="debug-widget bg-100 p-2 shadow-lg" t-att-class="transition.className" t-ref="root" t-att-style="style">
|
||||
<header class="drag-handle">
|
||||
<h1>Debug Window</h1>
|
||||
<h2>Debug Window</h2>
|
||||
</header>
|
||||
<div class="toggle" t-on-click="() => debug.toggleWidget()" title="Dismiss"
|
||||
role="img" aria-label="Dismiss"><i class="fa fa-times" /></div>
|
||||
<div class="content">
|
||||
<p class="category">Electronic Scale</p>
|
||||
<ul>
|
||||
<li>
|
||||
<input t-model="state.weightInput" type="text" class="weight"></input>
|
||||
</li>
|
||||
<li class="button set_weight" t-on-click="setWeight">Set Weight</li>
|
||||
<li class="button reset_weight" t-on-click="resetWeight">Reset</li>
|
||||
</ul>
|
||||
<div class="toggle position-absolute top-0 end-0 p-2" t-on-click="() => debug.toggleWidget()" title="Dismiss"
|
||||
role="img" aria-label="Dismiss"><i class="fa fa-fw fa-times" /></div>
|
||||
<div class="content overflow-hidden">
|
||||
|
||||
<p class="category">Barcode Scanner</p>
|
||||
<ul>
|
||||
<li>
|
||||
<input t-model="state.barcodeInput" type="text" class="ean" t-att-disabled="!barcodeReader" t-attf-placeholder="{{ !barcodeReader ? 'No nomenclature' : '' }}"/>
|
||||
</li>
|
||||
<li class="button barcode" t-on-click="barcodeScan">Scan</li>
|
||||
<li class="button custom_ean" t-on-click="barcodeScanEAN">Scan EAN-13</li>
|
||||
</ul>
|
||||
<div class="debug-electronic-scale">
|
||||
<h5 class="category">Electronic Scale</h5>
|
||||
<input t-model="state.weightInput" type="text" class="weight form-control"></input>
|
||||
<ul class="d-flex flex-column align-items-start mb-3">
|
||||
<li class="set_weight btn btn-link" t-on-click="setWeight">Set Weight</li>
|
||||
<li class="reset_weight btn btn-link" t-on-click="resetWeight">Reset</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="category">Orders</p>
|
||||
|
||||
<ul>
|
||||
<li class="button" t-on-click="deleteOrders">
|
||||
Delete Paid Orders
|
||||
</li>
|
||||
<li class="button" t-on-click="deleteUnpaidOrders">
|
||||
Delete Unpaid Orders
|
||||
</li>
|
||||
<li t-if="!state.isPaidOrdersReady" class="button"
|
||||
t-on-click="preparePaidOrders">
|
||||
Export Paid Orders
|
||||
</li>
|
||||
<a t-else="" t-att-download="paidOrdersFilename" t-att-href="paidOrdersURL"
|
||||
t-on-click="() => { state.isPaidOrdersReady = !state.isPaidOrdersReady }">
|
||||
<li class="button">
|
||||
Download Paid Orders
|
||||
<div class="debug-barcode-scanner">
|
||||
<h5 class="category">Barcode Scanner</h5>
|
||||
<ul class="d-flex flex-column align-items-start mb-3">
|
||||
<li>
|
||||
<input t-model="state.barcodeInput" type="text" class="ean form-control" t-att-disabled="!barcodeReader" t-attf-placeholder="{{ !barcodeReader ? 'No nomenclature' : '' }}"/>
|
||||
</li>
|
||||
</a>
|
||||
<li t-if="!state.isUnpaidOrdersReady" class="button"
|
||||
t-on-click="prepareUnpaidOrders">
|
||||
Export Unpaid Orders
|
||||
</li>
|
||||
<a t-else="" t-att-download="unpaidOrdersFilename"
|
||||
t-att-href="unpaidOrdersURL"
|
||||
t-on-click="() => { state.isUnpaidOrdersReady = !state.isUnpaidOrdersReady }">
|
||||
<li class="button">
|
||||
Download Unpaid Orders
|
||||
</li>
|
||||
</a>
|
||||
<li class="button import_orders" style="position:relative">
|
||||
Import Orders
|
||||
<input t-on-change="importOrders" type="file"
|
||||
style="opacity:0;position:absolute;top:0;left:0;right:0;bottom:0;margin:0;cursor:pointer" />
|
||||
</li>
|
||||
</ul>
|
||||
<li class="button btn btn-link barcode" t-on-click="barcodeScan">Scan</li>
|
||||
<li class="button btn btn-link custom_ean" t-on-click="barcodeScanEAN">Scan EAN-13</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="category">Hardware Status</p>
|
||||
<ul>
|
||||
<li class="status weighing">Weighing</li>
|
||||
<li class="button display_refresh" t-on-click="refreshDisplay">
|
||||
Refresh Display
|
||||
</li>
|
||||
</ul>
|
||||
<p class="category">Hardware Events</p>
|
||||
<ul>
|
||||
<li class="event" t-ref="open_cashbox">Open Cashbox</li>
|
||||
<li class="event" t-ref="print_receipt">Print Receipt</li>
|
||||
<li class="event" t-ref="scale_read">Read Weighing Scale</li>
|
||||
</ul>
|
||||
<p class="category">Others</p>
|
||||
<ul>
|
||||
<li class="event">
|
||||
<span>Buffer: </span>
|
||||
<t t-esc="bufferRepr" />
|
||||
</li>
|
||||
</ul>
|
||||
<div class="debug-orders">
|
||||
<h5 class="category">Orders</h5>
|
||||
<ul class="mb-3">
|
||||
<li class="button btn btn-link" t-on-click="deleteOrders">
|
||||
Delete Paid Orders
|
||||
</li>
|
||||
<li class="button btn btn-link" t-on-click="deleteUnpaidOrders">
|
||||
Delete Unpaid Orders
|
||||
</li>
|
||||
<li t-if="!state.isPaidOrdersReady" class="button btn btn-link"
|
||||
t-on-click="preparePaidOrders">
|
||||
Export Paid Orders
|
||||
</li>
|
||||
<a t-else="" t-att-download="paidOrdersFilename" t-att-href="paidOrdersURL"
|
||||
t-on-click="() => { state.isPaidOrdersReady = !state.isPaidOrdersReady }">
|
||||
<li class="button btn btn-link">
|
||||
Download Paid Orders
|
||||
</li>
|
||||
</a>
|
||||
<li t-if="!state.isUnpaidOrdersReady" class="button btn btn-link"
|
||||
t-on-click="prepareUnpaidOrders">
|
||||
Export Unpaid Orders
|
||||
</li>
|
||||
<a t-else="" t-att-download="unpaidOrdersFilename"
|
||||
t-att-href="unpaidOrdersURL"
|
||||
t-on-click="() => { state.isUnpaidOrdersReady = !state.isUnpaidOrdersReady }">
|
||||
<li class="button btn btn-link">
|
||||
Download Unpaid Orders
|
||||
</li>
|
||||
</a>
|
||||
<li class="button btn btn-link import_orders" style="position:relative">
|
||||
Import Orders
|
||||
<input t-on-change="importOrders" type="file"
|
||||
style="opacity:0;position:absolute;top:0;left:0;right:0;bottom:0;margin:0;cursor:pointer" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="debug-hardware-status d-flex flex-column">
|
||||
<h5 class="category">Hardware Status</h5>
|
||||
<ul class="mb-3">
|
||||
<li class="status weighing">Weighing</li>
|
||||
<li class="button btn btn-link display_refresh" t-on-click="refreshDisplay">
|
||||
Refresh Display
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="debug-hardware-events">
|
||||
<h5 class="category">Hardware Events</h5>
|
||||
<ul class="mb-3">
|
||||
<li class="event" t-ref="open_cashbox">Open Cashbox</li>
|
||||
<li class="event" t-ref="print_receipt">Print Receipt</li>
|
||||
<li class="event" t-ref="scale_read">Read Weighing Scale</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="debug-others">
|
||||
<h5 class="category">Others</h5>
|
||||
<ul class="mb-3">
|
||||
<li class="event">
|
||||
<span>Buffer: </span>
|
||||
<t t-esc="bufferRepr" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
|
||||
<t t-name="point_of_sale.OrderImportPopup" owl="1">
|
||||
<div class="popup popup-import">
|
||||
<header class="title drag-handle">
|
||||
<span>Finished Importing Orders</span>
|
||||
</header>
|
||||
<ul class="body">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title title drag-handle">
|
||||
Finished Importing Orders
|
||||
</h4>
|
||||
</div>
|
||||
<main class="body modal-body">
|
||||
<li>Successfully imported <b><t t-esc="props.report.paid or 0" /></b> paid orders</li>
|
||||
<li>Successfully imported <b><t t-esc="props.report.unpaid or 0" /></b> unpaid orders</li>
|
||||
<t t-if="unpaidSkipped">
|
||||
@@ -23,9 +25,9 @@
|
||||
</ul>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
<footer class="footer">
|
||||
<div class="button cancel" t-on-click="confirm">
|
||||
</main>
|
||||
<footer class="footer modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-primary" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -3,14 +3,16 @@
|
||||
|
||||
<t t-name="point_of_sale.ErrorPopup" owl="1">
|
||||
<div class="popup popup-error">
|
||||
<p class="title">
|
||||
<t t-esc="props.title" />
|
||||
</p>
|
||||
<p class="body">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title title">
|
||||
<t t-esc="props.title" />
|
||||
</h4>
|
||||
</div>
|
||||
<main class="modal-body">
|
||||
<t t-esc="props.body" />
|
||||
</p>
|
||||
<div class="footer">
|
||||
<div class="button cancel" t-on-click="confirm">
|
||||
</main>
|
||||
<div class="footer modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-primary " t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,17 +3,19 @@
|
||||
|
||||
<t t-name="point_of_sale.ErrorTracebackPopup" owl="1">
|
||||
<div class="popup popup-error">
|
||||
<header class="title">
|
||||
<t t-esc="props.title" />
|
||||
</header>
|
||||
<main class="body traceback">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title title">
|
||||
<t t-esc="props.title" />
|
||||
</h4>
|
||||
</div>
|
||||
<main class="modal-body body traceback">
|
||||
<t t-esc="props.body" />
|
||||
</main>
|
||||
<footer class="footer">
|
||||
<div t-if="!props.exitButtonIsShown" class="button cancel" t-on-click="confirm">
|
||||
<footer class="footer modal-footer">
|
||||
<div t-if="!props.exitButtonIsShown" class="button cancel btn btn-lg btn-primary" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
<div t-if="props.exitButtonIsShown" class="button cancel" t-on-click="() => this.pos.closePos()">
|
||||
<div t-if="props.exitButtonIsShown" class="button cancel btn btn-lg btn-secondary" t-on-click="() => this.pos.closePos()">
|
||||
<t t-esc="props.exitButtonText" />
|
||||
</div>
|
||||
<a t-att-download="tracebackFilename" t-att-href="tracebackUrl">
|
||||
@@ -23,7 +25,7 @@
|
||||
title="Download error traceback"></i>
|
||||
</div>
|
||||
</a>
|
||||
<div class="button icon email" t-on-click="emailTraceback">
|
||||
<div class="button icon email btn btn-lg btn-secondary" t-on-click="emailTraceback">
|
||||
<i class="fa fa-paper-plane" role="img" aria-label="Send by email"
|
||||
title="Send by email"></i>
|
||||
</div>
|
||||
|
||||
@@ -3,14 +3,16 @@
|
||||
|
||||
<t t-name="point_of_sale.OfflineErrorPopup" owl="1">
|
||||
<div class="popup offline">
|
||||
<header class="title">
|
||||
<t t-esc="props.title" />
|
||||
</header>
|
||||
<main class="body">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title title">
|
||||
<t t-esc="props.title" />
|
||||
</h4>
|
||||
</div>
|
||||
<main class="modal-body">
|
||||
<t t-esc=" props.body" />
|
||||
</main>
|
||||
<footer class="footer footer-flex">
|
||||
<div class="button dont-show-again highlight" t-on-click="confirm">
|
||||
<footer class="footer footer-flex modal-footer">
|
||||
<div class="button dont-show-again highlight btn btn-lg btn-primary w-auto" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
<t t-name="point_of_sale.BackButton" owl="1">
|
||||
<span
|
||||
class="order-button floor-button"
|
||||
class="order-button floor-button d-flex align-items-center gap-2 px-4 fw-bolder cursor-pointer"
|
||||
t-on-click="backToFloorScreen"
|
||||
>
|
||||
<i class="fa fa-angle-left" role="img" aria-label="Go Back" title="Go Back" />
|
||||
<i class="fa fa-2x fa-angle-left" role="img" aria-label="Go Back" title="Go Back" />
|
||||
<span t-if="!ui.isSmall">BACK</span>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
.cash-move-popup {
|
||||
top: 20% !important;
|
||||
|
||||
.input-amount {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
|
||||
.input-container {
|
||||
padding: 0px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.input-type {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
padding: 0 12px;
|
||||
margin-right: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
border: solid 1px rgba(60,60,60,0.1);
|
||||
background: rgba(0,0,0,0.05);
|
||||
white-space: nowrap;
|
||||
|
||||
&.highlight {
|
||||
background: $primary !important;
|
||||
border: solid 1px #64AF8A !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
&.red-highlight {
|
||||
background: #bd2222 !important;
|
||||
border: solid 1px #bd2222 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
min-height: auto;
|
||||
text-align: right;
|
||||
padding-right: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: rgb(197, 52, 0);
|
||||
text-align: left;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
// FIXME POSREF increased selector specificity to override default style. Should just be "footer"
|
||||
footer.cash-move.cash-move {
|
||||
display: block;
|
||||
width: calc(100% - 36px);
|
||||
padding: 10px 18px 10px 18px;
|
||||
|
||||
.button.confirm {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.button.cancel {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.input-container .input-field,
|
||||
.input-container .input-field:focus {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
padding: 0px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.cash-move {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
@@ -3,32 +3,49 @@
|
||||
|
||||
<t t-name="point_of_sale.CashMovePopup" owl="1">
|
||||
<div class="popup cash-move-popup">
|
||||
<main class="body">
|
||||
<div class="cash-move">
|
||||
<div class="input-amount">
|
||||
<span t-on-click="() => this.onClickButton('in')" class="input-type" t-att-class="{ highlight: state.type === 'in' }">
|
||||
Cash In
|
||||
</span>
|
||||
<span t-on-click="() => this.onClickButton('out')" class="input-type" t-att-class="{ 'red-highlight': state.type === 'out' }">
|
||||
Cash Out
|
||||
</span>
|
||||
<main class="modal-body">
|
||||
<div class="cash-move d-flex flex-column">
|
||||
<div class="input-amount d-flex mb-2 gap-2">
|
||||
<div class="input-group">
|
||||
<button t-on-click="() => this.onClickButton('in')" class="input-type btn btn-secondary flex-fill py-2 fw-bolder" t-att-class="{ highlight btn-success: state.type === 'in' }">
|
||||
Cash In
|
||||
</button>
|
||||
<button t-on-click="() => this.onClickButton('out')" class="input-type btn btn-secondary flex-fill py-2 fw-bolder" t-att-class="{ 'red-highlight btn-danger': state.type === 'out' }">
|
||||
Cash Out
|
||||
</button>
|
||||
</div>
|
||||
<div class="input-container popup-input" t-on-input="handleInputChange" >
|
||||
<span class="currency" t-esc="pos.currency.symbol" t-if="pos.currency.position=='before'"/>
|
||||
<input class="input-field" type="text" name="amount" t-model="state.amount" t-ref="amountInput" t-on-keypress="_onAmountKeypress"/>
|
||||
<span class="currency" t-esc="pos.currency.symbol" t-if="pos.currency.position=='after'"/>
|
||||
</div>
|
||||
<div class="input-field input-group">
|
||||
<t t-if="pos.currency.symbol.length > 1">
|
||||
<span class="left-currency input-group-text" t-esc="pos.currency.symbol" t-if="pos.currency.position=='before'"/>
|
||||
</t>
|
||||
<input type="text" class="form-control" name="amount" t-model="state.amount" t-ref="amountInput" t-on-keypress="_onAmountKeypress"/>
|
||||
<t t-if="pos.currency.symbol.length > 1">
|
||||
<span class="left-currency input-group-text" t-esc="pos.currency.symbol" t-if="pos.currency.position=='after'"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span class="currency input-group-text" t-esc="pos.currency.symbol" />
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<textarea name="reason" t-model="state.reason" placeholder="Reason"></textarea>
|
||||
<span t-if="state.errorMessage" class="error-message">
|
||||
<div class="form-floating">
|
||||
<textarea class="form-control" placeholder="Leave a reason here" name="reason" id="reason" t-model="state.reason" style="height:100px;"></textarea>
|
||||
<label for="reason">Reason</label>
|
||||
</div>
|
||||
<span t-if="state.errorMessage" class="error-message alert alert-danger mt-2">
|
||||
<t t-esc="state.errorMessage" />
|
||||
</span>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="footer cash-move">
|
||||
<div class="button confirm disable highlight dynamic-size" t-on-click="confirm">
|
||||
<footer class="footer cash-move modal-footer">
|
||||
<div class="button confirm disable highlight dynamic-size btn-btn-lg btn-primary" t-on-click="confirm">
|
||||
Confirm <span t-esc="env.utils.formatCurrency(state.parsedAmount)"/>
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<div class="button cancel btn btn-lg btn-secondary" t-on-click="cancel">
|
||||
Discard
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.CashierName" owl="1">
|
||||
<div t-att-class="cssClass">
|
||||
<span class="cashier-name"><img t-att-src="avatar" t-att-alt="username" class="avatar"/> <span t-if="!ui.isSmall" t-esc="username" class="username"/></span>
|
||||
<div t-att-class="cssClass" class="btn btn-light border-0 rounded-0">
|
||||
<span class="cashier-name d-flex align-items-center gap-1"><img t-att-src="avatar" t-att-alt="username" class="avatar rounded-3"/> <span t-if="!ui.isSmall" t-esc="username" class="username"/></span>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
this.hardwareProxy.openCashbox(action);
|
||||
const { confirmed, payload } = await this.popup.add(MoneyDetailsPopup, {
|
||||
moneyDetails: this.moneyDetails,
|
||||
total: this.manualInputCashCount
|
||||
total: this.manualInputCashCountpayments
|
||||
? 0
|
||||
: this.state.payments[this.defaultCashDetails.id].counted,
|
||||
action: action,
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
|
||||
<t t-name="point_of_sale.ClosePosPopup" owl="1">
|
||||
<div class="popup close-pos-popup">
|
||||
<header>
|
||||
<div class="title">Closing Session</div>
|
||||
<div class="total-orders">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Closing Session</h4>
|
||||
<div class="total-orders fw-bolder">
|
||||
Total <t t-esc="ordersDetails.quantity"/> orders:
|
||||
<span class="amount" t-esc="env.utils.formatCurrency(ordersDetails.amount)"/>
|
||||
</div>
|
||||
</header>
|
||||
<main class="body">
|
||||
<div class="payment-methods-overview">
|
||||
<table>
|
||||
</div>
|
||||
<main class="modal-body">
|
||||
<div class="payment-methods-overview overflow-auto">
|
||||
<table class="text-start">
|
||||
<thead>
|
||||
<tr>
|
||||
<tr class="text-dark">
|
||||
<th>Payment Method</th>
|
||||
<th>Expected</th>
|
||||
<th style="width: 20%">Counted</th>
|
||||
@@ -26,24 +26,24 @@
|
||||
<tr>
|
||||
<td t-esc="defaultCashDetails.name"/>
|
||||
<td t-esc="env.utils.formatCurrency(defaultCashDetails.amount)"/>
|
||||
<td class="flex" t-on-input="(event) => this.handleInputChange(defaultCashDetails.id, event)">
|
||||
<input class="pos-input" t-ref="closingCashInput" t-on-focus="ev=>ev.target.select()"/>
|
||||
<div class="button icon ClosePosPopup" t-on-click="openDetailsPopup">
|
||||
<i class="fa fa-money" role="img" title="Open the money details popup"/>
|
||||
<td class="d-flex" t-on-input="(event) => this.handleInputChange(defaultCashDetails.id, event)">
|
||||
<input class="pos-input form-control" t-ref="closingCashInput" t-on-focus="ev=>ev.target.select()"/>
|
||||
<div class="button icon ClosePosPopup btn btn-secondary" t-on-click="openDetailsPopup">
|
||||
<i class="fa fa-money fa-2x" role="img" title="Open the money details popup"/>
|
||||
</div>
|
||||
</td>
|
||||
<td t-esc="env.utils.formatCurrency(state.payments[defaultCashDetails.id].difference)" t-att-class="{'warning': state.payments[defaultCashDetails.id].difference}"/>
|
||||
<td t-esc="env.utils.formatCurrency(state.payments[defaultCashDetails.id].difference)" t-att-class="{'warning text-danger fw-bolder': state.payments[defaultCashDetails.id].difference}"/>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody class="cash-overview">
|
||||
<tbody class="cash-overview d-flex flex-column mb-2 border-start small text-muted">
|
||||
<tr>
|
||||
<td>Opening</td>
|
||||
<td t-esc="env.utils.formatCurrency(defaultCashDetails.opening)"/>
|
||||
</tr>
|
||||
<tr t-foreach="defaultCashDetails.moves" t-as="move" t-key="move_index">
|
||||
<td>
|
||||
<div class="flex">
|
||||
<div class="cash-sign" t-esc="move.amount < 0 ? '-' : '+'"/>
|
||||
<div class="flex d-flex flex-row">
|
||||
<div class="cash-sign me-1" t-esc="move.amount < 0 ? '-' : '+'"/>
|
||||
<t t-esc="move.name"/>
|
||||
</div>
|
||||
</td>
|
||||
@@ -51,8 +51,8 @@
|
||||
</tr>
|
||||
<tr t-if="defaultCashDetails.payment_amount">
|
||||
<td>
|
||||
<div class="flex">
|
||||
<div class="cash-sign" t-esc="defaultCashDetails.payment_amount < 0 ? '-' : '+'"/>
|
||||
<div class="flex d-flex flex-row">
|
||||
<div class="cash-sign me-1" t-esc="defaultCashDetails.payment_amount < 0 ? '-' : '+'"/>
|
||||
Payments in <t t-esc="defaultCashDetails.name"/>
|
||||
</div>
|
||||
</td>
|
||||
@@ -66,41 +66,43 @@
|
||||
<td t-esc="env.utils.formatCurrency(pm.amount)"/>
|
||||
<t t-set="_showDiff" t-value="_getShowDiff(pm)" />
|
||||
<td t-if="_showDiff" t-on-input="(event) => this.handleInputChange(pm.id, event)">
|
||||
<input class="pos-input" t-ref="closingCashInput_{{pm.id}}" t-on-focus="ev=>ev.target.select()"/>
|
||||
<input class="pos-input form-control" t-ref="closingCashInput_{{pm.id}}" t-on-focus="ev=>ev.target.select()"/>
|
||||
</td>
|
||||
<td t-if="_showDiff" t-esc="env.utils.formatCurrency(state.payments[pm.id].difference)" t-att-class="{'warning': state.payments[pm.id].difference}"/>
|
||||
<td t-if="_showDiff" t-esc="env.utils.formatCurrency(state.payments[pm.id].difference)" t-att-class="{'warning text-danger fw-bolder': state.payments[pm.id].difference}"/>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
<main class="body notes">
|
||||
<div class="notes-container">
|
||||
<div class="opening-notes-container" t-if="openingNotes" >
|
||||
Opening note
|
||||
<textarea class="opening-notes">
|
||||
<div class="notes-container d-flex flex-column gap-3 border-top mt-3 pt-3">
|
||||
<div class="opening-notes-container d-flex flex-column align-items-start" t-if="openingNotes" >
|
||||
<label class="form-label" for="openingNotes">Opening note</label>
|
||||
<textarea class="opening-notes form-control" id="openingNotes">
|
||||
<t t-esc="openingNotes"/>
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="closing-notes-container">
|
||||
Closing note
|
||||
<textarea class="closing-notes" placeholder="Add a closing note..." t-model="state.notes"/>
|
||||
<div class="closing-notes-container d-flex flex-column align-items-start">
|
||||
<label class="form-label" for="closingNotes">Closing note</label>
|
||||
<textarea class="closing-notes form-control" id="closingNotes" placeholder="Add a closing note..." t-model="state.notes"/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="footer">
|
||||
<div class="button highlight" t-on-click="confirm">Close Session</div>
|
||||
<div class="button" t-att-class="{'disabled': !canCancel()}" t-on-click="cancel">Discard</div>
|
||||
<footer class="footer modal-footer justify-content-between">
|
||||
<!-- Download Sale Details -->
|
||||
<div class="small button icon"
|
||||
t-on-click="downloadSalesReport"
|
||||
title="Download a report with all the sales of the current PoS Session">
|
||||
<div class="daily sale">Daily Sale</div>
|
||||
<i class="fa fa-download" role="img"/>
|
||||
<div class="modal-footer-left d-flex gap-2">
|
||||
<button class="button icon btn btn-lg btn-secondary"
|
||||
t-on-click="downloadSalesReport"
|
||||
title="Download a report with all the sales of the current PoS Session">
|
||||
Daily Sale
|
||||
<i class="fa fa-download" role="img"/>
|
||||
</button>
|
||||
<!-- Print Sale Details -->
|
||||
<button t-if="hardwareProxy.printer" class="button icon btn btn-lg btn-secondary">
|
||||
<SaleDetailsButton/>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Print Sale Details -->
|
||||
<div t-if="hardwareProxy.printer" class="small button icon">
|
||||
<SaleDetailsButton/>
|
||||
<div class="modal-footer-right d-flex gap-2">
|
||||
<button class="button btn btn-lg btn-secondary" t-att-class="{'disabled': !canCancel()}" t-on-click="cancel">Discard</button>
|
||||
<button class="button highlight btn btn-lg btn-primary" t-on-click="confirm">Close Session</button>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
+7
-6
@@ -2,20 +2,21 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.CustomerFacingDisplayButton" owl="1">
|
||||
<div class="menu-item navbar-button" t-on-click="() => {customerDisplay.connect(); this.displayMessage(message);}">
|
||||
<div t-if="customerDisplay.status === 'warning'" class="js_warning oe_icon oe_orange">
|
||||
<button class="menu-item navbar-button btn btn-light rounded-0 d-flex align-items-center px-3 cursor-pointer" t-on-click="() => {customerDisplay.connect(); this.displayMessage(message);}">
|
||||
<div t-if="customerDisplay.status === 'warning'" class="js_warning oe_icon oe_orange text-warning">
|
||||
<i class="fa fa-fw fa-desktop" role="img" t-attf-aria-label="Customer Screen Warning : {{message}}" t-attf-title="Customer Screen Warning : {{message}}"></i>
|
||||
</div>
|
||||
<div t-if="customerDisplay.status === 'failure'" class="js_disconnected oe_icon oe_red">
|
||||
<div t-if="customerDisplay.status === 'failure'" class="js_disconnected oe_icon oe_red text-danger">
|
||||
<i class="fa fa-fw fa-desktop" role="img" t-attf-aria-label="Customer Screen : {{message}}" t-attf-title="Customer Screen : {{message}}"></i>
|
||||
</div>
|
||||
<div t-if="customerDisplay.status === 'not_found'" class="js_disconnected oe_icon oe_red">
|
||||
<div t-if="customerDisplay.status === 'not_found'" class="js_disconnected oe_icon oe_red text-danger">
|
||||
<i class="fa fa-fw fa-desktop" role="img" t-attf-aria-label="Customer Screen Not Found : {{message}}" t-attf-title="Customer Screen Not Found : {{message}}"></i>
|
||||
</div>
|
||||
<div t-if="customerDisplay.status === 'success'" class="js_connected oe_icon oe_green">
|
||||
<div t-if="customerDisplay.status === 'success'" class="js_connected oe_icon oe_green text-success">
|
||||
<i class="fa fa-fw fa-desktop" role="img" aria-label="Customer Screen Connected" title="Customer Screen Connected"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span class="ms-1">Customer Screen</span>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
.pos-topheader {
|
||||
height: $navbar-height;
|
||||
}
|
||||
|
||||
.pos-branding{
|
||||
max-width: $left-pane-width;
|
||||
}
|
||||
|
||||
.status-buttons {
|
||||
> div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: $o-horizontal-padding * 0.75;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
z-index: $zindex-dropdown;
|
||||
}
|
||||
|
||||
.sub-menu {
|
||||
top: $navbar-height * 2/3;
|
||||
right: $navbar-height * -1/3 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,51 +2,54 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.Navbar" owl="1">
|
||||
<div class="pos-topheader">
|
||||
<div class="pos-topheader d-flex w-100 p-0 m-0 bg-white border-bottom">
|
||||
<div t-if="pos.tempScreen" class="block-top-header" />
|
||||
<div t-if="!ui.isSmall" class="pos-branding">
|
||||
<img class="pos-logo" t-on-click="() => debug.toggleWidget()" src="/point_of_sale/static/src/img/logo.png" alt="Logo" />
|
||||
<div t-if="!ui.isSmall" class="pos-branding d-flex justify-content-start flex-grow-1 h-100 p-0 my0 text-start">
|
||||
<img class="pos-logo h-75 ms-2 me-auto align-self-center" t-on-click="() => debug.toggleWidget()" src="/web/static/img/logo.png" alt="Logo" />
|
||||
</div>
|
||||
<div class="pos-rightheader">
|
||||
<div class="pos-rightheader d-flex flex-grow-1 h-100">
|
||||
<BackButton t-if="showBackButton()"/>
|
||||
<div class="status-buttons">
|
||||
<div class="status-buttons d-flex flex-grow-1 flex-basis-0 justify-content-end h-100">
|
||||
<CashierName />
|
||||
<SaleDetailsButton t-if="hardwareProxy.printer" isHeaderButton="true"/>
|
||||
<ProxyStatus t-if="pos.config.use_proxy" />
|
||||
<CustomerFacingDisplayButton t-if="customerFacingDisplayButtonIsShown" />
|
||||
<SyncNotification />
|
||||
</div>
|
||||
<div t-if="isBurgerMenuClosed()" class="navbar-button menu-button" t-on-click="openMenu">
|
||||
<div t-if="isBurgerMenuClosed()" class="navbar-button menu-button btn btn-light rounded-0 d-flex align-items-center px-3 cursor-pointer" t-on-click="openMenu">
|
||||
<i class="fa fa-bars" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div t-else="" class="navbar-button menu menu-button" t-on-click="closeMenu">
|
||||
<div t-else="" class="navbar-button menu menu-button btn btn-light rounded-0 d-flex align-items-center px-3 cursor-pointer" t-on-click="closeMenu">
|
||||
<ul>
|
||||
<li class="menu-item">
|
||||
<li class="menu-item position-relative d-flex">
|
||||
<i class="fa fa-bars" aria-hidden="true"></i>
|
||||
<ul class="sub-menu">
|
||||
<li class="menu-item navbar-button ticket-button" t-on-click="onTicketButtonClick">
|
||||
<div class="with-badge" t-att-badge="orderCount">
|
||||
<span>Orders</span>
|
||||
</div>
|
||||
<ul class="dropdown-menu sub-menu position-absolute d-flex flex-column align-items-stretch w-100 bg-white shadow-lg z-index-1">
|
||||
<li class="ticket-button" t-on-click="onTicketButtonClick">
|
||||
<a class="dropdown-item with-badge py-2">
|
||||
Orders
|
||||
<span class="badge text-bg-info rounded-pill py-1 ms-2" t-esc="orderCount"/>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="showCashMoveButton" class="menu-item navbar-button" t-on-click="onCashMoveButtonClick">
|
||||
<span>Cash In/Out</span>
|
||||
<a class="dropdown-item py-2">
|
||||
Cash In/Out
|
||||
</a>
|
||||
</li>
|
||||
<CustomerFacingDisplayButton t-if="CustomerFacingDisplayButtonIsShown"/>
|
||||
<li class="menu-item navbar-button backend-button" t-on-click="() => pos.closePos()">
|
||||
<span>
|
||||
<li class="backend-button" t-on-click="() => pos.closePos()">
|
||||
<a class="dropdown-item py-2">
|
||||
Backend
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item navbar-button close-button" t-on-click="closeSession">
|
||||
<span>
|
||||
<li class="close-button" t-on-click="closeSession">
|
||||
<a class="dropdown-item py-2">
|
||||
Close Session
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="showToggleProductView" class="menu-item navbar-button close-button" t-on-click="toggleProductView">
|
||||
<span>
|
||||
<a class="dropdown-item py-2">
|
||||
Switch Product View
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="this.env.debug" t-on-click="() => debug.toggleWidget()" class="menu-item navbar-button">
|
||||
<span>Debug Window</span>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.ProxyStatus" owl="1">
|
||||
<div class="oe_status js_proxy" t-on-click="() => this.pos.connectToProxy()">
|
||||
<button class="oe_status js_proxy btn btn-light" t-on-click="() => this.pos.connectToProxy()">
|
||||
<span t-if="this.message and !ui.isSmall" class="js_msg">
|
||||
<t t-esc="this.message" />
|
||||
</span>
|
||||
<span t-if="connectionInfo.status === 'connected' and !this.message" class="js_connected oe_green">
|
||||
<span t-if="connectionInfo.status === 'connected' and !this.message" class="js_connected text-success">
|
||||
<i class="fa fa-fw fa-sitemap" role="img" aria-label="Proxy Connected"
|
||||
title="Proxy Connected"></i>
|
||||
</span>
|
||||
@@ -14,15 +14,15 @@
|
||||
<i class="fa fa-fw fa-spin fa-circle-o-notch" role="img" aria-label="Connecting to Proxy"
|
||||
title="Connecting to Proxy"></i>
|
||||
</span>
|
||||
<span t-elif="connectionInfo.status === 'disconnected'" class="js_disconnected oe_red">
|
||||
<span t-elif="connectionInfo.status === 'disconnected'" class="js_disconnected text-danger">
|
||||
<i class="fa fa-fw fa-sitemap" role="img" aria-label="Proxy Disconnected"
|
||||
title="Proxy Disconnected"></i>
|
||||
</span>
|
||||
<span t-elif="connectionInfo.status === 'warning' or this.message" class="js_warning oe_orange">
|
||||
<span t-elif="connectionInfo.status === 'warning' or this.message" class="js_warning text-warning">
|
||||
<i class="fa fa-fw fa-sitemap" role="img" aria-label="Proxy Warning"
|
||||
title="Proxy Warning"></i>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.SaleDetailsButton" owl="1">
|
||||
<div t-att-class="{'oe_status': props.isHeaderButton }" t-on-click="onClick">
|
||||
<div class="js_connected oe_icon"
|
||||
<div t-att-class="{'oe_status cursor-pointer': props.isHeaderButton }" t-on-click="onClick">
|
||||
<div class="js_connected oe_icon text-white"
|
||||
title="Print a report with all the sales of the current PoS Session">
|
||||
<i class="fa fa-fw fa-print" role="img" aria-label="Print"></i>
|
||||
</div>
|
||||
|
||||
@@ -2,24 +2,24 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.SyncNotification" owl="1">
|
||||
<div class="oe_status" t-on-click="onClick">
|
||||
<div class="oe_status btn btn-light rounded-0" t-on-click="onClick">
|
||||
<span t-if="sync.pending" class="js_msg">
|
||||
<t t-esc="sync.pending" />
|
||||
<span> </span>
|
||||
</span>
|
||||
<div t-if="sync.status === 'connected'" class="js_connected oe_icon oe_green">
|
||||
<div t-if="sync.status === 'connected'" class="js_connected oe_icon text-success">
|
||||
<i class="fa fa-fw fa-wifi" role="img" aria-label="Synchronisation Connected"
|
||||
title="Synchronisation Connected"></i>
|
||||
</div>
|
||||
<div t-if="sync.status === 'connecting'" class="js_connecting oe_icon">
|
||||
<div t-if="sync.status === 'connecting'" class="js_connecting oe_icon text-white">
|
||||
<i class="fa fa-fw fa-spin fa-circle-o-notch" role="img"
|
||||
aria-label="Synchronisation Connecting" title="Synchronisation Connecting"></i>
|
||||
</div>
|
||||
<div t-if="sync.status === 'disconnected'" class="js_disconnected oe_icon oe_orange">
|
||||
<div t-if="sync.status === 'disconnected'" class="js_disconnected oe_icon text-warning">
|
||||
<i class="fa fa-fw fa-wifi" role="img" aria-label="Synchronisation Disconnected"
|
||||
title="Synchronisation Disconnected"></i>
|
||||
</div>
|
||||
<div t-if="sync.status === 'error'" class="js_error oe_icon oe_red">
|
||||
<div t-if="sync.status === 'error'" class="js_error oe_icon text-danger">
|
||||
<i class="fa fa-fw fa-warning" role="img" aria-label="Synchronisation Error"
|
||||
title="Synchronisation Error"></i>
|
||||
</div>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
.o_pos_notification_manager {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 2rem;
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.o_notification {
|
||||
pointer-events: auto;
|
||||
width: 350px;
|
||||
background-color: #333333AA;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
padding: 16px;
|
||||
margin: .5rem;
|
||||
font-size: 1rem;
|
||||
|
||||
span {
|
||||
white-space: pre-line;
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.Notification" owl="1">
|
||||
<div class="o_notification" t-att-class="props.className" t-on-click="props.close">
|
||||
<div class="o_notification o-fade o-fade-enter-active p-3 m-2 text-bg-dark bg-opacity-75 text-center pe-none" t-att-class="props.className" t-on-click="props.close">
|
||||
<span t-esc="props.message"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="point_of_sale.NotificationContainer" owl="1">
|
||||
<div class="o_pos_notification_manager">
|
||||
<div class="o_pos_notification_manager fixed-bottom d-flex flex-column align-items-center justify-content-end p-4 pe-none">
|
||||
<t t-foreach="props.notifications" t-as="notification" t-key="notification">
|
||||
<Transition name="'o-fade'" visible="notification_value.visible" leaveDuration="leaveDuration" t-slot-scope="transition" onLeave="notification_value.delete">
|
||||
<Notification message="notification_value.message" close="notification_value.close" className="transition.className"/>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/* --- Styling of OpenERP Elements --- */
|
||||
/* .ui-dialog, .modal-dialog {
|
||||
background: white;
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
font-family: sans-serif;
|
||||
box-shadow: 0px 10px 40px rgba(0,0,0,0.4);
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
height: 400px;
|
||||
overflow: scroll;
|
||||
} */
|
||||
|
||||
.ui-dialog .ui-icon-closethick{
|
||||
float: right;
|
||||
}
|
||||
div.modal.in {
|
||||
position: absolute;
|
||||
background: white;
|
||||
padding: 20px;
|
||||
box-shadow: 0px 10px 20px black;
|
||||
border-radius: 3px;
|
||||
max-width: 600px;
|
||||
max-height: 400px;
|
||||
margin-top: -200px;
|
||||
margin-left: -300px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
/* @media screen and (max-width: 768px) {
|
||||
.ui-dialog, .modal-dialog {
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
} */
|
||||
@@ -4,7 +4,7 @@
|
||||
<t t-name="point_of_sale.PopupContainer" owl="1">
|
||||
<div t-if="Object.keys(props.popups).length > 0" class="popups">
|
||||
<t t-foreach="props.popups" t-as="popup" t-key="popup">
|
||||
<div t-if="popup_last || popup_value.props.keepBehind" role="dialog" class="modal-dialog">
|
||||
<div t-if="popup_last || popup_value.props.keepBehind" role="dialog" class="modal-dialog position-absolute start-0 top-0 d-flex align-items-center justify-content-center h-100 w-100 mw-100 m-0 p-0 pe-auto bg-dark bg-opacity-50">
|
||||
<t t-component="popup_value.component" t-props="popup_value.props" isActive="popup_last" />
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
.pos {
|
||||
background: $gray-900;
|
||||
--btn-height-size: 54px;
|
||||
direction: ltr;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #f0eeee;
|
||||
color: $gray-700;
|
||||
/* Some elements inside .pos are allowed to be moved/resized. When
|
||||
* this 'move/resize' event is performed in touch devices, .pos
|
||||
* element also tries to scroll (as the default action of touchstart+
|
||||
* touchmove events).
|
||||
* Position is fixed to prevent the movement of .pos element during
|
||||
* the described touch events.
|
||||
*/
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
text-shadow: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* ********* Generic element styling ********* */
|
||||
|
||||
.pos a {
|
||||
text-decoration: none;
|
||||
color: $gray-700;
|
||||
}
|
||||
|
||||
.pos ul, .pos ol {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.pos li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
/* --- Generic Restyling and Resets --- */
|
||||
|
||||
html {
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
td {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.oe_hidden{
|
||||
display: none !important;
|
||||
}
|
||||
.oe_invisible{
|
||||
visibility: hidden !important;
|
||||
}
|
||||
.clearfix:after {
|
||||
content:" ";
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
line-height: 0;
|
||||
height: 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.pos input::-webkit-outer-spin-button,
|
||||
.pos input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pos .oe_hidden{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.pos ul, .pos li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
|
||||
/* ********* POS CONTENT ********* */
|
||||
|
||||
.pos-content {
|
||||
height: calc(100% - #{$navbar-height});
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.Chrome" owl="1">
|
||||
<div class="pos" t-att-class="{ 'big-scrollbars': pos.hasBigScrollBars }">
|
||||
<div class="pos">
|
||||
<div class="pos-receipt-print"></div>
|
||||
<Navbar />
|
||||
<div class="pos-content">
|
||||
<div class="window">
|
||||
<div class="subwindow">
|
||||
<div class="pos-content position-relative w-100 bg-200">
|
||||
<div class="window position-relative h-100 w-100 border-0 overflow-hidden">
|
||||
<div class="subwindow w-100 h-100">
|
||||
<div class="subwindow-container">
|
||||
<div class="subwindow-container-fix screens">
|
||||
<!-- FIXME POSREF: better error handling in main screens (currently, a crash in owl lifecycle of a main screen blows up the application and the error can't be displayed) -->
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
.partner-picture {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
& > img {
|
||||
position: absolute;
|
||||
top: -9999px;
|
||||
bottom: -9999px;
|
||||
right: -9999px;
|
||||
left: -9999px;
|
||||
max-height: 64px;
|
||||
margin: auto;
|
||||
}
|
||||
.image-uploader {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
+43
-39
@@ -1,34 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="point_of_sale.PartnerDetailsEdit" owl="1">
|
||||
<section class="partner-details edit">
|
||||
<div class="partner-picture">
|
||||
<t t-if="partnerImageUrl">
|
||||
<img t-att-src="partnerImageUrl" alt="Partner" style="width: 64px; height: 64px; object-fit: cover;" />
|
||||
</t>
|
||||
<t t-else="">
|
||||
<i class="fa fa-camera" role="img" aria-label="Picture" title="Picture"></i>
|
||||
</t>
|
||||
<input type="file" class="image-uploader" t-on-change="uploadImage" />
|
||||
<section class="partner-details edit d-flex flex-column w-100 m-3">
|
||||
<div class="partner-details-header d-flex pe-2 gap-2">
|
||||
<div class="partner-picture position-relative rounded text-center overflow-hidden">
|
||||
<t t-if="partnerImageUrl">
|
||||
<img class="rounded" t-att-src="partnerImageUrl" alt="Partner" style="width: 64px; height: 64px; object-fit: cover;" />
|
||||
</t>
|
||||
<t t-else="">
|
||||
<i class="fa fa-camera" role="img" aria-label="Picture" title="Picture"></i>
|
||||
</t>
|
||||
<input type="file" class="image-uploader" t-on-change="uploadImage" />
|
||||
</div>
|
||||
<input class="detail partner-name form-control form-control-lg" name="name" t-att-value="props.partner.name or ''" placeholder="Name" t-on-change="captureChange" />
|
||||
</div>
|
||||
<input class="detail partner-name" name="name" placeholder="Name" t-model="changes.name" />
|
||||
<div class="partner-details-box clearfix">
|
||||
<div class="partner-details-left">
|
||||
<div class="partner-details-box clearfix d-flex flex-column flex-sm-row gap-2 mt-4">
|
||||
<div class="partner-details-left d-flex flex-column gap-3 w-100">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Street</span>
|
||||
<input class="detail" name="street" t-att-class="{'border-red': missingFields.includes('street')}" t-model="changes.street" placeholder="Street" />
|
||||
<label class="form-label label" for="street">Street</label>
|
||||
<input class="detail form-control" id="street" name="street" t-model="changes.street" placeholder="Street" t-att-class="{'border-danger': missingFields.includes('street')}"/>
|
||||
</div>
|
||||
<div class="partner-detail">
|
||||
<span class="label">City</span>
|
||||
<input class="detail" name="city" t-att-class="{'border-red': missingFields.includes('city')}" t-model="changes.city" placeholder="City" />
|
||||
<label class="form-label label" for="city">City</label>
|
||||
<input class="detail form-control" id="city" name="city" t-model="changes.city" placeholder="City" t-att-class="{'border-danger': missingFields.includes('city')}" />
|
||||
</div>
|
||||
<div class="partner-detail">
|
||||
<span class="label">Postcode</span>
|
||||
<input class="detail" name="zip" t-att-class="{'border-red': missingFields.includes('zip')}" t-model="changes.zip" placeholder="ZIP" />
|
||||
<label class="form-label label" for="postcode">Postcode</label>
|
||||
<input class="detail form-control" id="postcode" name="zip" t-model="changes.zip" placeholder="ZIP" t-att-class="{'border-danger': missingFields.includes('zip')}" />
|
||||
</div>
|
||||
<div class="partner-detail" t-if="pos.states.some((state) => state.country_id[0] == changes.country_id)">
|
||||
<span class="label">State</span>
|
||||
<select class="detail" name="state_id" t-att-class="{'border-red': missingFields.includes('state_id')}" t-model="changes.state_id">
|
||||
<div class="partner-detail">
|
||||
<label class="form-label label" for="state">State</label>
|
||||
<select class="detail form-select" id="state" name="state_id" t-model="changes.state_id" t-att-class="{'border-danger': missingFields.includes('state_id')}">
|
||||
<option value="">None</option>
|
||||
<t t-foreach="pos.states" t-as="state" t-key="state.id">
|
||||
<option t-if="changes.country_id == state.country_id[0]" t-att-value="state.id">
|
||||
@@ -38,8 +40,8 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="partner-detail">
|
||||
<span class="label">Country</span>
|
||||
<select class="detail" name="country_id" t-att-class="{'border-red': missingFields.includes('country_id')}" t-model="changes.country_id">
|
||||
<label class="form-label label" for="country">Country</label>
|
||||
<select class="detail form-select" id="country" name="country_id" t-model="changes.country_id" t-att-class="{'border-danger': missingFields.includes('country_id')}">
|
||||
<option value="">None</option>
|
||||
<t t-foreach="pos.countries" t-as="country" t-key="country.id">
|
||||
<option t-att-value="country.id">
|
||||
@@ -49,10 +51,10 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="partner-details-right">
|
||||
<div class="partner-details-right d-flex flex-column gap-3 w-100">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Language</span>
|
||||
<select class="detail" name="lang" t-att-class="{'border-red': missingFields.includes('lang')}" t-model="changes.lang">
|
||||
<label class="form-label label" for="language">Language</label>
|
||||
<select class="detail form-select" id="language" name="lang" t-model="changes.lang" t-att-class="{'border-danger': missingFields.includes('lang')}">
|
||||
<t t-foreach="pos.langs" t-as="lang" t-key="lang.id">
|
||||
<option t-att-value="lang.code" t-att-selected="changes.lang ? ((lang.code === changes.lang) ? true : undefined) : lang.code === pos.user.lang? true : undefined">
|
||||
<t t-esc="lang.name" />
|
||||
@@ -61,30 +63,32 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="partner-detail">
|
||||
<span class="label">Email</span>
|
||||
<input class="detail" name="email" t-att-class="{'border-red': missingFields.includes('email')}" type="email" t-model="changes.email" />
|
||||
<label class="form-label label" for="email">Email</label>
|
||||
<input class="detail form-control" id="email" name="email" type="email" t-model="changes.email" t-att-class="{'border-danger': missingFields.includes('email')}" />
|
||||
</div>
|
||||
<div class="partner-detail">
|
||||
<span class="label">Phone</span>
|
||||
<input class="detail" name="phone" t-att-class="{'border-red': missingFields.includes('phone')}" type="tel" t-model="changes.phone" />
|
||||
<label class="form-label label" for="phone">Phone</label>
|
||||
<input class="detail form-control" id="phone" name="phone" type="tel" t-model="changes.phone" t-att-class="{'border-danger': missingFields.includes('phone')}" />
|
||||
</div>
|
||||
<div class="partner-detail">
|
||||
<span class="label">Mobile</span>
|
||||
<input class="detail" name="mobile" t-att-class="{'border-red': missingFields.includes('mobile')}" type="tel" t-model="changes.mobile" />
|
||||
<label class="form-label label" for="mobile">Mobile</label>
|
||||
<input class="detail form-control" id="mobile" name="mobile" type="tel"
|
||||
t-model="changes.mobile"
|
||||
t-att-class="{'border-danger': missingFields.includes('tel')}" />
|
||||
</div>
|
||||
<div class="partner-detail">
|
||||
<span class="label">Barcode</span>
|
||||
<input class="detail barcode" name="barcode" t-model="changes.barcode" t-att-class="{'border-red': missingFields.includes('barcode')}" />
|
||||
<label class="form-label label" for="barcode">Barcode</label>
|
||||
<input class="detail barcode form-control" id="barcode" name="barcode" t-model="changes.barcode" t-att-class="{'border-danger': missingFields.includes('barcode')}" />
|
||||
</div>
|
||||
<div class="partner-detail">
|
||||
<span class="label">Tax ID</span>
|
||||
<input class="detail vat" name="vat" t-model="changes.vat" t-att-class="{'border-red': missingFields.includes('vat')}" />
|
||||
<label class="form-label label" for="vat">Tax ID</label>
|
||||
<input class="detail vat form-control" id="vat" name="vat" t-model="changes.vat" t-att-class="{'border-danger': missingFields.includes('vat')}" />
|
||||
</div>
|
||||
<div t-if="pos.pricelists.length gt 1" class="partner-detail">
|
||||
<span class="label">Pricelist</span>
|
||||
<select class="detail" name="property_product_pricelist" t-att-class="{'border-red': missingFields.includes('property_product_pricelist')}" t-model="changes.property_product_pricelist">
|
||||
<label class="form-label label" for="pricelist">Pricelist</label>
|
||||
<select class="detail form-select" id="pricelist" name="property_product_pricelist" t-model="changes.property_product_pricelist" t-att-class="{'border-danger': missingFields.includes('property_product_pricelist')}">
|
||||
<t t-foreach="pos.pricelists" t-as="pricelist" t-key="pricelist.id">
|
||||
<option t-att-value="pricelist.id" t-att-selected="changes.property_product_pricelist ? (pricelist.id === changes.property_product_pricelist[0] ? true : undefined) : pricelist.id === pos.default_pricelist.id ? true : undefined">
|
||||
<option t-att-value="pricelist.id" t-att-selected="props.partner.property_product_pricelist ? (pricelist.id === props.partner.property_product_pricelist[0] ? true : undefined) : pricelist.id === pos.default_pricelist.id ? true : undefined">
|
||||
<t t-esc="pricelist.display_name" />
|
||||
</option>
|
||||
</t>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ export class PartnerLine extends Component {
|
||||
static template = "point_of_sale.PartnerLine";
|
||||
|
||||
get highlight() {
|
||||
return this._isPartnerSelected ? "highlight" : "";
|
||||
return this._isPartnerSelected ? "highlight text-bg-primary" : "";
|
||||
}
|
||||
get _isPartnerSelected() {
|
||||
return this.props.partner === this.props.selectedPartner;
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
@include media-breakpoint-down(lg) {
|
||||
|
||||
.partner-line {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
padding: 12px 24px;
|
||||
border-bottom: 1px solid $o-gray-300;
|
||||
|
||||
td {
|
||||
border: 0;
|
||||
flex-basis: 100%;
|
||||
padding: 5px;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.partner-line-balance{
|
||||
order: 3;
|
||||
}
|
||||
.partner-line .pos-right-align{
|
||||
text-align: left ;
|
||||
}
|
||||
.partner-line-email {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.edit-partner-button-cell {
|
||||
order: 4;
|
||||
}
|
||||
.partner-line-last-column-placeholder {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -2,19 +2,19 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.PartnerLine" owl="1">
|
||||
<tr t-attf-class="partner-line {{highlight}}" t-att-data-id="props.partner.id"
|
||||
<tr t-attf-class="partner-line gap-2 gap-lg-0 align-top {{highlight}}" t-att-data-id="props.partner.id"
|
||||
t-on-click="() => this.props.onClickPartner(props.partner)">
|
||||
<td>
|
||||
<div>
|
||||
<t t-esc="props.partner.name or ''" />
|
||||
</div>
|
||||
<div class="company-field">
|
||||
<div class="company-field text-bg-muted">
|
||||
<t t-esc="props.partner.parent_name or ''" />
|
||||
</div>
|
||||
<div t-if="_isPartnerSelected" class="unselect-tag">
|
||||
<i class="fa fa-times"></i>
|
||||
<button t-if="_isPartnerSelected" class="unselect-tag d-lg-inline-block d-none btn btn-light mt-2">
|
||||
<i class="fa fa-times me-1"></i>
|
||||
<span> unselect </span>
|
||||
</div>
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<div class="partner-line-adress" t-if="props.partner.address">
|
||||
@@ -23,22 +23,22 @@
|
||||
</td>
|
||||
<td class="partner-line-email" >
|
||||
<div t-if="props.partner.phone">
|
||||
<i class="fa fa-fw fa-phone"/><t t-esc="props.partner.phone"/>
|
||||
<i class="fa fa-fw fa-phone me-2"/><t t-esc="props.partner.phone"/>
|
||||
</div>
|
||||
<div t-if="props.partner.mobile">
|
||||
<i class="fa fa-fw fa-mobile fa-lg"/><t t-esc="props.partner.mobile"/>
|
||||
<i class="fa fa-fw fa-mobile fa-lg me-2"/><t t-esc="props.partner.mobile"/>
|
||||
</div>
|
||||
<div t-if="props.partner.email" class="email-field">
|
||||
<i class="fa fa-fw fa-paper-plane-o"/><t t-esc="props.partner.email" />
|
||||
<i class="fa fa-fw fa-paper-plane-o me-2"/><t t-esc="props.partner.email" />
|
||||
</div>
|
||||
</td>
|
||||
<td class="partner-line-balance" t-if="props.isBalanceDisplayed"></td>
|
||||
<td class="edit-partner-button-cell">
|
||||
<button class="edit-partner-button" t-on-click.stop="() => props.onClickEdit(props.partner)">DETAILS</button>
|
||||
<div t-if="_isPartnerSelected" class="unselect-tag-mobile">
|
||||
<button class="edit-partner-button btn btn-light" t-on-click.stop="() => props.onClickEdit(props.partner)">DETAILS</button>
|
||||
<button t-if="_isPartnerSelected" class="unselect-tag-mobile d-inline-block d-lg-none btn btn-outline-light ms-2">
|
||||
<i class="fa fa-times"></i>
|
||||
<span> unselect </span>
|
||||
</div>
|
||||
</button>
|
||||
</td>
|
||||
<td class="partner-line-last-column-placeholder oe_invisible"></td>
|
||||
</tr>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
.partner-list th.partner-line-last-column-placeholder,
|
||||
.partner-list td.partner-line-last-column-placeholder {
|
||||
padding: 0;
|
||||
}
|
||||
.partnerlist-screen {
|
||||
tr {
|
||||
&.partner-line {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background: rgba($primary, 0.2);
|
||||
}
|
||||
&:active {
|
||||
background-color: $primary;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(lg) {
|
||||
|
||||
.table {
|
||||
border: transparent;
|
||||
}
|
||||
.partner-list {
|
||||
thead {
|
||||
display: none;
|
||||
}
|
||||
td {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,58 +4,62 @@
|
||||
<t t-name="point_of_sale.PartnerListScreen" owl="1">
|
||||
<div class="partnerlist-screen screen">
|
||||
<div class="screen-content">
|
||||
<div class="top-content">
|
||||
<div class="button highlight" t-if="state.detailIsShown" t-on-click="() => this.partnerEditor.save()">
|
||||
<div class="top-content d-flex align-items-center p-2 border-bottom text-center">
|
||||
<div class="button highlight btn btn-lg btn-primary" t-if="state.detailIsShown" t-on-click="() => this.partnerEditor.save()">
|
||||
<i t-if="ui.isSmall" class="fa fa-floppy-o"/>
|
||||
<t t-else="">
|
||||
<span> Save</span>
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="!state.detailIsShown" class="button new-customer highlight" role="img" aria-label="Add a customer"
|
||||
<button t-if="!state.detailIsShown" class="button new-customer highlight btn btn-lg btn-primary" role="img" aria-label="Add a customer"
|
||||
t-on-click="createPartner"
|
||||
title="Add a customer">
|
||||
<i t-if="ui.isSmall" class="fa fa-plus"/>
|
||||
<t t-else=""> Create</t>
|
||||
</div>
|
||||
<div class="button back" t-on-click="back">
|
||||
</button>
|
||||
<div class="button back btn btn-lg btn-secondary mx-2" t-on-click="back">
|
||||
<i t-if="ui.isSmall" class="fa fa-angle-double-left"/>
|
||||
<t t-else=""> Discard</t>
|
||||
</div>
|
||||
<div class="top-right-buttons">
|
||||
<div t-if="state.detailIsShown and state.editModeProps.partner.id" class="button more-info" t-on-click="goToOrders">
|
||||
<span> Orders</span>
|
||||
</div>
|
||||
<a t-if="state.detailIsShown && state.editModeProps.partner.id" class="button more-info" t-att-href="partnerLink" target="_blank"> More info</a>
|
||||
<div class="search-bar-container sb-partner" t-if="!state.detailIsShown">
|
||||
<div class="pos-search-bar">
|
||||
<i class="fa fa-search" t-on-click="_onPressEnterKey"/>
|
||||
<input t-ref="search-word-input-partner" placeholder="Search Customers..." size="1" t-on-keyup="updatePartnerList" />
|
||||
<i class="fa fa-times" t-on-click="_clearSearch"/>
|
||||
<div class="top-right-buttons d-flex gap-2 w-100 justify-content-end">
|
||||
<div t-if="state.detailIsShown and state.editModeProps.partner.id" class="button more-info">
|
||||
<a t-on-click="goToOrders" class="btn btn-lg btn-outline-secondary" target="_blank"> Orders </a>
|
||||
</div>
|
||||
<div t-if="state.detailIsShown && state.editModeProps.partner.id" class="button more-info">
|
||||
<a t-att-href="partnerLink" class="btn btn-lg btn-outline-secondary" target="_blank"> More info</a>
|
||||
</div>
|
||||
<div class="search-bar-container sb-partner d-flex align-items-center flex-grow-1 h-100" t-if="!state.detailIsShown">
|
||||
<div class="input-group h-100">
|
||||
<div class="pos-search-bar form-control d-flex align-items-center bg-view">
|
||||
<i class="oi oi-search me-2" t-on-click="_onPressEnterKey"/>
|
||||
<input class="flex-grow-1 w-auto h-100 border-0 p-2 me-4" type="text" autofocus="autofocus" t-ref="search-word-input-partner" placeholder="Search Customers..." size="1" t-on-keyup="updatePartnerList" />
|
||||
<i class="fa fa-times position-absolute end-0 me-2 pe-1 cursor-pointer" t-on-click="_clearSearch"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section class="full-content">
|
||||
<section class="full-content position-absolute start-0 end-0 bottom-0 overflow-auto">
|
||||
<div class="partner-window">
|
||||
<section class="subwindow collapsed">
|
||||
<div class="subwindow-container collapsed">
|
||||
<section class="subwindow collapsed h-0">
|
||||
<div class="subwindow-container collapsed position-relative d-table-cell h-0">
|
||||
<div t-if="state.detailIsShown" class="partner-details-contents subwindow-container-fix">
|
||||
<PartnerDetailsEdit t-props="state.editModeProps" saveChanges.bind="saveChanges" imperativeHandle="partnerEditor" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="subwindow list">
|
||||
<div class="subwindow-container">
|
||||
<div class="subwindow-container position-relative d-table-cell h-100 vw-100">
|
||||
<div t-if="!state.detailIsShown" class="subwindow-container-fix scrollable-y">
|
||||
<table class="partner-list">
|
||||
<table class="partner-list table table-striped w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Address</th>
|
||||
<th class="partner-line-email">Contact</th>
|
||||
<th class="pos-right-align" t-if="isBalanceDisplayed">Balance</th>
|
||||
<th class="partner-line-details"></th>
|
||||
<th class="partner-line-last-column-placeholder oe_invisible"></th>
|
||||
<th class="py-2">Name</th>
|
||||
<th class="py-2">Address</th>
|
||||
<th class="partner-line-email py-2">Contact</th>
|
||||
<th class="pos-right-align py-2" t-if="isBalanceDisplayed">Balance</th>
|
||||
<th class="partner-line-details py-2"></th>
|
||||
<th class="partner-line-last-column-placeholder oe_invisible py-2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="partner-list-contents">
|
||||
@@ -70,8 +74,8 @@
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
<div t-if="state.query" class="search-more-button">
|
||||
<div class="button" t-on-click="_onPressEnterKey">Search more</div>
|
||||
<div t-if="state.query" class="search-more-button d-flex justify-content-center mt-2">
|
||||
<button class="btn btn-lg btn-primary" t-on-click="_onPressEnterKey">Search more</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
.payment-numpad .numpad button {
|
||||
font-size: clamp(map-get($font-sizes, 6), 3vw, 36px);
|
||||
}
|
||||
|
||||
.payment-numpad .numpad button:nth-child(16) img {
|
||||
width: 35%;
|
||||
max-width: 64px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
.payment-numpad .numpad button:nth-child(16) img {
|
||||
max-width: 48px;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.PaymentScreenNumpad" owl="1">
|
||||
<div class="numpad">
|
||||
<div class="numpad d-grid text-center flex-grow-1 h-100 w-100">
|
||||
<PSNumpadInputButton value="'1'" />
|
||||
<PSNumpadInputButton value="'2'" />
|
||||
<PSNumpadInputButton value="'3'" />
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.PSNumpadInputButton" owl="1">
|
||||
<button t-attf-class="{{ _class }}"
|
||||
<button t-attf-class="{{ _class }} btn btn-secondary w-100 rounded-0 py-3"
|
||||
t-on-click="() => this.numberBuffer.sendKey(props.value)">
|
||||
<t t-slot="default">
|
||||
<t t-if="props.text">
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
.paymentlines .electronic_payment {
|
||||
background: $gray-200;
|
||||
border-collapse: unset;
|
||||
font-size: 16px;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.paymentline .electronic_status {
|
||||
flex-grow: 1;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
/* make the name of the payment line to be truncated with ellipsis */
|
||||
white-space: nowrap;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
padding: map-get($spacers, 3);
|
||||
}
|
||||
|
||||
.paymentlines .electronic_payment div:first-child {
|
||||
flex-grow: 2;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.paymentlines .electronic_payment div:last-child {
|
||||
flex-grow: 1;
|
||||
text-align: center;
|
||||
padding: map-get($spacers, 3);
|
||||
}
|
||||
+13
-13
@@ -2,15 +2,15 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.PaymentScreenPaymentLines" owl="1">
|
||||
<div class="paymentlines">
|
||||
<p class="title-category">Summary</p>
|
||||
<div class="paymentlines d-flex flex-column">
|
||||
<p class="title-category py-1 px-3 m-0 text-bg-300 fw-bolder">Summary</p>
|
||||
<t t-foreach="props.paymentLines" t-as="line" t-key="line.cid">
|
||||
<t t-if="line.selected">
|
||||
<div class="paymentline selected"
|
||||
<div class="paymentline selected d-flex align-items-center bg-200"
|
||||
t-att-class="selectedLineClass(line)">
|
||||
<div class="payment-infos" t-on-click="() => this.selectLine(line)">
|
||||
<div class="payment-infos d-flex align-items-center justify-content-between flex-grow-1 px-3 py-4 my-2 text-truncate cursor-pointer" t-on-click="() => this.selectLine(line)">
|
||||
<span class="payment-name"><t t-esc="line.payment_method.name"/></span>
|
||||
<div class="payment-amount">
|
||||
<div class="payment-amount px-3">
|
||||
<t t-if="line and line.payment_status and ['done', 'waitingCard', 'waiting', 'reversing', 'reversed'].includes(line.payment_status)">
|
||||
<t t-esc="env.utils.formatCurrency(line.get_amount(), false)" />
|
||||
</t>
|
||||
@@ -21,11 +21,11 @@
|
||||
</div>
|
||||
|
||||
<t t-if="!line.payment_status or !['done', 'reversed', 'waitingCard', 'waitingCapture'].includes(line.payment_status)">
|
||||
<div class="delete-button"
|
||||
<button class="delete-button btn btn-link mx-2 px-3"
|
||||
t-on-click="() => this.props.deleteLine(line.cid)"
|
||||
aria-label="Delete" title="Delete">
|
||||
<i class="fa fa-times-circle" />
|
||||
</div>
|
||||
<i class="fa fa-2x fa-times-circle" />
|
||||
</button>
|
||||
</t>
|
||||
</div>
|
||||
<t t-if="line and line.payment_status">
|
||||
@@ -101,11 +101,11 @@
|
||||
</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="paymentline"
|
||||
<div class="paymentline d-flex align-items-center bg-view"
|
||||
t-att-class="unselectedLineClass(line)">
|
||||
<div class="payment-infos" t-on-click="() => this.selectLine(line)">
|
||||
<div class="payment-infos d-flex align-items-center justify-content-between flex-grow-1 px-3 py-4 my-2 text-truncate cursor-pointer" t-on-click="() => this.selectLine(line)">
|
||||
<t t-esc="line.payment_method.name" />
|
||||
<div class="payment-amount">
|
||||
<div class="payment-amount px-3">
|
||||
<t t-if="line and line.payment_status and ['done', 'waitingCard', 'waiting', 'reversing', 'reversed'].includes(line.payment_status)">
|
||||
<t t-esc="env.utils.formatCurrency(line.get_amount(), false)" />
|
||||
</t>
|
||||
@@ -115,10 +115,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="!line.payment_status or !['done', 'reversed'].includes(line.payment_status)">
|
||||
<div class="delete-button"
|
||||
<div class="delete-button delete-button btn btn-link mx-2 px-3"
|
||||
t-on-click="() => this.props.deleteLine(line.cid)"
|
||||
aria-label="Delete" title="Delete">
|
||||
<i class="fa fa-times-circle" />
|
||||
<i class="fa fa-2x fa-times-circle" />
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
.payment-screen .center-content {
|
||||
grid-template-rows: auto 1fr;
|
||||
width: 30rem;
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(lg) {
|
||||
.payment-screen {
|
||||
|
||||
.main-content {
|
||||
grid-template-columns: 300px 1fr;
|
||||
grid-template-rows: 1fr auto;
|
||||
}
|
||||
.center-content {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.payment-status-container > div:first-child {
|
||||
margin-top: map-get($spacers, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
.payment-screen .main-content {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.payment-screen .center-content {
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.payment-screen .left-content,
|
||||
.payment-screen .right-content {
|
||||
justify-content: flex-start;
|
||||
overflow: initial;
|
||||
}
|
||||
.screen .right-content {
|
||||
grid-column: span 1;
|
||||
}
|
||||
|
||||
.pos .paymentlines-container {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.payment-method-icon {
|
||||
max-width: 50px;
|
||||
max-height: 50px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,32 +3,33 @@
|
||||
|
||||
<t t-name="point_of_sale.PaymentScreen" owl="1">
|
||||
<div class="payment-screen screen" t-att-class="{ oe_hidden: !props.isShown }">
|
||||
<div class="screen-content">
|
||||
<div class="screen-content d-flex flex-column h-100">
|
||||
<t t-if="!ui.isSmall">
|
||||
<div class="top-content">
|
||||
<div class="button back"
|
||||
t-on-click="() => pos.showScreen('ProductScreen')">
|
||||
<i class="fa fa-angle-double-left fa-fw"></i>
|
||||
<div class="top-content d-flex align-items-center p-2 border-bottom text-center">
|
||||
<div class="button back btn btn-lg btn-secondary" t-on-click="() => pos.showScreen('ProductScreen')">
|
||||
<i class="fa fa-angle-double-left me-2"></i>
|
||||
<span class="back_text">Back</span>
|
||||
</div>
|
||||
<div class="top-content-center"><h1>Payment</h1></div>
|
||||
<div class="top-content-center flex-grow-1">
|
||||
<h2 class="mb-0">Payment</h2>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<div class="main-content">
|
||||
<div class="left-content">
|
||||
<div class="main-content d-flex flex-grow-1 flex-wrap overflow-y-auto">
|
||||
<div class="left-content d-flex flex-column justify-content-between w-100 mh-100 border-0">
|
||||
<t t-if="ui.isSmall">
|
||||
<section class="paymentlines-container">
|
||||
<section class="paymentlines-container px-4 pt-0">
|
||||
<PaymentScreenStatus order="currentOrder" />
|
||||
</section>
|
||||
</t>
|
||||
<div class="paymentmethods-container">
|
||||
<div class="paymentmethods">
|
||||
<p class="title-category">Payment method</p>
|
||||
<div class="paymentmethods-container overflow-auto">
|
||||
<div class="paymentmethods d-flex flex-column">
|
||||
<p class="title-category py-1 px-3 m-0 text-bg-300 fw-bolder">Payment method</p>
|
||||
<t t-foreach="payment_methods_from_config" t-as="paymentMethod"
|
||||
t-key="paymentMethod.id">
|
||||
<div class="button paymentmethod"
|
||||
<div class="button paymentmethod btn btn-light rounded-0 fw-bolder"
|
||||
t-on-click="() => this.addNewPaymentLine(paymentMethod)">
|
||||
<div class="payment-method-display">
|
||||
<div class="payment-method-display d-flex align-items-center flex-grow-1 py-3">
|
||||
<div><img class="payment-method-icon" t-att-src="paymentMethodImage(paymentMethod.id)"/></div>
|
||||
<span class="payment-name"><t t-esc="paymentMethod.name" /></span>
|
||||
</div>
|
||||
@@ -45,30 +46,30 @@
|
||||
selectLine.bind="selectPaymentLine"
|
||||
updateSelectedPaymentline.bind="updateSelectedPaymentline"/>
|
||||
</div>
|
||||
<div t-if="!ui.isSmall" class="button next validation" t-att-class="{ highlight: currentOrder.is_paid() and currentOrder._isValidEmptyOrder() }"
|
||||
<div t-if="!ui.isSmall" class="button next validation btn btn-primary btn-lg py-5 rounded-0 d-flex flex-column align-items-center justify-content-center fw-bolder" t-attf-class="{{currentOrder.is_paid() and currentOrder._isValidEmptyOrder() ? 'highlight' : 'disabled'}}"
|
||||
t-on-click="() => this.validateOrder()">
|
||||
<div class="pay-circle">
|
||||
<div class="pay-circle d-flex align-items-center justify-content-center mb-2">
|
||||
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
</div>
|
||||
<span class="next_text">Validate</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center-content" t-if="!ui.isSmall">
|
||||
<section class="paymentlines-container">
|
||||
<div class="center-content d-grid px-3 pb-3 pb-md-0 pb-lg-3 bg-300" t-if="!ui.isSmall">
|
||||
<section class="paymentlines-container bg-view rounded my-3 p-3">
|
||||
<PaymentScreenStatus order="currentOrder" />
|
||||
</section>
|
||||
|
||||
<div class="payment-buttons-container">
|
||||
<section class="payment-numpad">
|
||||
<div class="payment-buttons-container d-flex flex-wrap">
|
||||
<section class="payment-numpad flex-grow-1">
|
||||
<PaymentScreenNumpad />
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-content">
|
||||
<div class="payment-buttons">
|
||||
<div class="partner-button">
|
||||
<div class="button" t-att-class="{ highlight: currentOrder.get_partner() }" t-on-click="() => this.selectPartner(false, [])">
|
||||
<i class="fa fa-user" role="img" title="Customer" />
|
||||
<div class="payment-buttons d-flex flex-column flex-md-row flex-lg-column flex-lg-column flex-grow-1 flex-wrap gap-3 gap-lg-0 p-3 p-lg-0 bg-300 ">
|
||||
<div class="partner-button d-grid flex-grow-1 flex-basis-25 border">
|
||||
<div class="button btn btn-light py-3 text-start rounded-0" t-att-class="{ 'highlight text-bg-primary': currentOrder.get_partner() }" t-on-click="() => this.selectPartner(false, [])">
|
||||
<i class="fa fa-user me-2" role="img" title="Customer" />
|
||||
<t t-set="partner" t-value="currentOrder.get_partner()" />
|
||||
<span>
|
||||
<t t-if="partner">
|
||||
@@ -80,25 +81,25 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="payment-controls">
|
||||
<div class="button js_invoice"
|
||||
t-att-class="{ highlight: currentOrder.is_to_invoice() }"
|
||||
<div class="payment-controls d-grid flex-grow-1 flex-basis-25 border">
|
||||
<button class="button js_invoice btn btn-light py-3 text-start rounded-0"
|
||||
t-att-class="{ 'highlight text-bg-primary': currentOrder.is_to_invoice() }"
|
||||
t-on-click="toggleIsToInvoice">
|
||||
<i class="fa fa-file-text-o" /> Invoice
|
||||
</div>
|
||||
<div t-if="pos.config.iface_tipproduct and pos.config.tip_product_id" class="button js_tip"
|
||||
t-att-class="{ highlight: currentOrder.get_tip() }"
|
||||
<i class="fa fa-file-text-o me-2" /> Invoice
|
||||
</button>
|
||||
<button t-if="pos.config.iface_tipproduct and pos.config.tip_product_id" class="button js_tip btn btn-light py-3 text-start rounded-0"
|
||||
t-att-class="{ 'highlight text-bg-primary': currentOrder.get_tip() }"
|
||||
t-on-click="addTip">
|
||||
<i class="fa fa-heart" /> Tip <t t-if="currentOrder.get_tip() != 0">(<t t-esc="env.utils.formatCurrency(currentOrder.get_tip())"/>)</t>
|
||||
</div>
|
||||
<div t-if="pos.config.iface_cashdrawer" class="button js_cashdrawer"
|
||||
<i class="fa fa-heart me-2" /> Tip <t t-if="currentOrder.get_tip() != 0">(<t t-esc="env.utils.formatCurrency(currentOrder.get_tip())"/>)</t>
|
||||
</button>
|
||||
<button t-if="pos.config.iface_cashdrawer" class="button js_cashdrawer btn btn-light py-3 text-start rounded-0"
|
||||
t-on-click="openCashbox">
|
||||
<i class="fa fa-archive" /> Open Cashbox
|
||||
</div>
|
||||
<div t-if="pos.config.ship_later" class="button"
|
||||
t-att-class="{ highlight: currentOrder.getShippingDate() }"
|
||||
<i class="fa fa-archive me-2" /> Open Cashbox
|
||||
</button>
|
||||
<div t-if="pos.config.ship_later" class="button btn btn-light py-3 text-start rounded-0"
|
||||
t-att-class="{ 'highlight text-bg-primary': currentOrder.getShippingDate() }"
|
||||
t-on-click="toggleShippingDatePicker">
|
||||
<i class="fa fa-clock-o" /> Ship Later
|
||||
<i class="fa fa-clock-o me-2" /> Ship Later
|
||||
<span t-if="currentOrder.getShippingDate()">
|
||||
(<t t-esc="currentOrder.getShippingDate()"/>)
|
||||
</span>
|
||||
@@ -108,8 +109,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="ui.isSmall">
|
||||
<div class="switchpane">
|
||||
<button class="btn-switchpane validation-button"
|
||||
<div class="switchpane d-flex">
|
||||
<button class="btn-switchpane validation-button btn btn-primary flex-fill py-5 rounded-0 fw-bolder"
|
||||
t-att-class="{ secondary: !(currentOrder.is_paid() and currentOrder._isValidEmptyOrder()) }"
|
||||
t-on-click="() => this.validateOrder()">
|
||||
<span>Validate</span>
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
.paymentlines-empty .total {
|
||||
font-size: 3rem;
|
||||
text-shadow: 0px 2px white, 0px 2px 2px rgba(0, 0, 0, 0.27);
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
.paymentlines-empty .message {
|
||||
padding-bottom: map-get($spacers, 3);
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -3,26 +3,26 @@
|
||||
|
||||
<t t-name="point_of_sale.PaymentScreenStatus" owl="1">
|
||||
<div t-if="props.order.get_paymentlines().length === 0" class="paymentlines-empty">
|
||||
<div class="total">
|
||||
<div class="total text-center py-2 text-success">
|
||||
<t t-esc="totalDueText" />
|
||||
</div>
|
||||
<div class="message">
|
||||
<div class="message text-center">
|
||||
Please select a payment method.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div t-else="">
|
||||
<div class="payment-status-container">
|
||||
<div class="payment-status-container d-flex flex-column-reverse flex-lg-row justify-content-between fs-2">
|
||||
<div>
|
||||
<div class="payment-status-remaining">
|
||||
<span class="label">Remaining</span>
|
||||
<span class="label pe-2">Remaining</span>
|
||||
<span class="amount"
|
||||
t-att-class="{ highlight: props.order.get_due() > 0 }">
|
||||
t-att-class="{ 'highlight text-primary fw-bolder': props.order.get_due() > 0 }">
|
||||
<t t-esc="remainingText" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="payment-status-total-due">
|
||||
<span class="label">Total Due</span>
|
||||
<div class="payment-status-total-due py-2 fs-3 text-muted">
|
||||
<span class="label pe-2">Total Due</span>
|
||||
<span>
|
||||
<t t-esc="totalDueText" />
|
||||
</span>
|
||||
@@ -30,9 +30,9 @@
|
||||
</div>
|
||||
<div>
|
||||
<div class="payment-status-change">
|
||||
<span class="label">Change</span>
|
||||
<span class="label pe-2">Change</span>
|
||||
<span class="amount"
|
||||
t-att-class="{ highlight: props.order.get_change() > 0 }">
|
||||
t-att-class="{ 'highlight text-primary fw-bolder': props.order.get_change() > 0 }">
|
||||
<t t-esc="changeText" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.set-partner span {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
.pay-order-button, .set-partner {
|
||||
height: 56px;
|
||||
}
|
||||
+19
-13
@@ -2,25 +2,31 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.ActionpadWidget" owl="1">
|
||||
<div class="actionpad">
|
||||
<button class="button mobile-more-button" t-if="ui.isSmall and props.onClickMore" t-on-click="props.onClickMore">
|
||||
<div class="actionpad d-flex flex-column flex-grow-1 w-50 p-0 border-end">
|
||||
<button class="button mobile-more-button btn btn-secondary flex-fill border-bottom" t-if="ui.isSmall and props.onClickMore" t-on-click="props.onClickMore">
|
||||
<span>More...</span>
|
||||
</button>
|
||||
<button class="button set-partner" t-att-class="{'decentered': isLongName}"
|
||||
<button class="button set-partner btn btn-light rounded-0 py-2 flex-shrink-1 fw-bolder"
|
||||
t-on-click="() => this.pos.selectPartner()">
|
||||
<t t-if="!ui.isSmall"><i class="fa fa-user" role="img" aria-label="Customer" title="Customer" /></t>
|
||||
<t t-if="props.partner">
|
||||
<t t-esc="props.partner.name" />
|
||||
</t>
|
||||
<t t-else="">
|
||||
Customer
|
||||
</t>
|
||||
<div class="d-flex justify-content-center align-items-center ">
|
||||
<span class="d-flex justify-content-center align-items-center rounded-circle me-2 text-bg-dark" t-if="!ui.isSmall">
|
||||
<i class="fa fa-user" role="img" aria-label="Customer" title="Customer" />
|
||||
</span>
|
||||
<div t-if="props.partner" class="text-truncate fw-bolder">
|
||||
<t t-esc="props.partner.name" />
|
||||
</div>
|
||||
<div t-else="fw-bolder">
|
||||
Customer
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="button pay validation pay-order-button" t-att-class="{ 'with-more-button': props.onClickMore and ui.isSmall }" t-on-click="props.actionToTrigger ? this.props.actionToTrigger : () => pos.get_order().pay()">
|
||||
<div class="pay-circle" t-att-class="{ 'highlight': this.highlightPay }">
|
||||
<button class="button pay validation pay-order-button btn btn-primary btn-lg py-5 rounded-0 highlight d-flex flex-column flex-fill align-items-center justify-content-center fw-bolder"
|
||||
t-att-class="{ 'with-more-button': props.onClickMore and ui.isSmall }"
|
||||
t-on-click="props.actionToTrigger ? this.props.actionToTrigger : () => pos.get_order().pay()">
|
||||
<div class="pay-circle d-flex align-items-center justify-content-center py-2 mb-2" t-att-class="{ 'highlight': this.highlightPay }">
|
||||
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
</div>
|
||||
<t t-esc="props.actionName" />
|
||||
<t class="text-white" t-esc="props.actionName" />
|
||||
</button>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
+3
-3
@@ -2,14 +2,14 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.CategoryButton" owl="1">
|
||||
<span class="category-button" t-on-click="() => this.props.switchCategory(props.category.id)">
|
||||
<button class="category-button btn btn-light" t-on-click="() => this.props.switchCategory(props.category.id)">
|
||||
<div class="category-img">
|
||||
<img t-att-src="imageUrl" alt="Category" />
|
||||
</div>
|
||||
<div class="category-name">
|
||||
<div class="category-name mt-2 fw-bolder">
|
||||
<t t-esc="props.category.name" />
|
||||
</div>
|
||||
</span>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
.control-buttons {
|
||||
white-space: nowrap;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.control-button {
|
||||
flex: 1 1 29%;
|
||||
padding: $o-horizontal-padding * 0.75;
|
||||
}
|
||||
|
||||
/* .control-button.highlight,
|
||||
.button.highlight {
|
||||
background: $primary !important;
|
||||
border-color: $primary !important;
|
||||
color: white !important;
|
||||
} */
|
||||
.control-button.altlight,
|
||||
.button.altlight {
|
||||
background: #7F82AC !important;
|
||||
border: solid 1px #756A99 !important;
|
||||
color: white !important;
|
||||
}
|
||||
+4
-4
@@ -2,15 +2,15 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.ControlButtonPopup" owl="1">
|
||||
<div class="popup popup-control-buttons">
|
||||
<div class="popup popup-control-buttons d-flex flex-column">
|
||||
<!-- When one of the buttons is clicked, close this popup. -->
|
||||
<div class="control-buttons" t-on-click="cancel">
|
||||
<div class="control-buttons d-flex flex-column p-2" t-on-click="cancel">
|
||||
<t t-foreach="controlButtons" t-as="cb" t-key="cb.name">
|
||||
<t t-component="cb.component" t-key="cb.name"/>
|
||||
</t>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<footer class="footer modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-primary" t-on-click="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="point_of_sale.CustomerButton" owl="1">
|
||||
<div class="control-button customer-button set-partner" t-on-click="() => this.pos.selectPartner()">
|
||||
<i class="fa fa-user" role="img" aria-label="Customer" title="Customer" />
|
||||
<div class="control-button customer-button btn btn-light rounded-0 fw-bolder" t-on-click="() => this.pos.selectPartner()">
|
||||
<i class="fa fa-user me-1" role="img" aria-label="Customer" title="Customer" />
|
||||
<t t-esc="this.partner.name" t-if="this.partner" />
|
||||
<t t-else="">
|
||||
Customer
|
||||
|
||||
+3
-3
@@ -2,11 +2,11 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.OrderlineCustomerNoteButton" owl="1">
|
||||
<div class="control-button" t-on-click="() => this.onClick()">
|
||||
<i class="fa fa-sticky-note" />
|
||||
<button class="control-button btn btn-light rounded-0 fw-bolder" t-on-click="() => this.onClick()">
|
||||
<i class="fa fa-sticky-note me-1" />
|
||||
<span> </span>
|
||||
<span>Customer Note</span>
|
||||
</div>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.SetFiscalPositionButton" owl="1">
|
||||
<div class="control-button o_fiscal_position_button" t-on-click="() => this.click()">
|
||||
<i class="fa fa-book" role="img" aria-label="Set fiscal position"
|
||||
<div class="control-button o_fiscal_position_button btn btn-light rounded-0 fw-bolder" t-on-click="() => this.click()">
|
||||
<i class="fa fa-book me-1" role="img" aria-label="Set fiscal position"
|
||||
title="Set fiscal position" />
|
||||
<t t-esc='currentFiscalPositionName' />
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.ProductInfoButton" owl="1">
|
||||
<div class="control-button" t-on-click="() => this.click()">
|
||||
<i class="fa fa-info-circle" role="img" aria-label="Info" title="Info"/>
|
||||
<button class="control-button btn btn-light rounded-0 fw-bolder" t-on-click="() => this.click()">
|
||||
<i class="fa fa-info-circle me-1" role="img" aria-label="Info" title="Info"/>
|
||||
Info
|
||||
</div>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.RefundButton" owl="1">
|
||||
<div class="control-button" t-on-click="() => this.click()">
|
||||
<i class="fa fa-undo" role="img" aria-label="Refund" title="Refund" />
|
||||
<button class="control-button btn btn-light rounded-0 fw-bolder" t-on-click="() => this.click()">
|
||||
<i class="fa fa-undo me-1" role="img" aria-label="Refund" title="Refund" />
|
||||
Refund
|
||||
</div>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/* ********* The Numpad ********* */
|
||||
|
||||
.pos .numpad {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
min-width: 216px;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
/* .pos .numpad button {
|
||||
float: left
|
||||
height: 54px;
|
||||
vertical-align: middle;
|
||||
color: $gray-700;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
border-right: 1px solid;
|
||||
border-bottom: 1px solid;
|
||||
border-color: $gray-300;
|
||||
transition: all 150ms linear;
|
||||
padding: unset;
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
} */
|
||||
|
||||
|
||||
.pos .mode-button {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.pos .mode-button.selected-mode {
|
||||
color: white;
|
||||
background: $o-brand-odoo;
|
||||
border-color: transparent;
|
||||
}
|
||||
.pos .mode-button.selected-mode:hover {
|
||||
background: $primary;
|
||||
color: white;
|
||||
border-color: transparent;
|
||||
}
|
||||
.pos .numpad .disabled-mode, .pos .numpad .disabled-mode:hover {
|
||||
background: $gray-200;
|
||||
color: $gray-500;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
@@ -2,35 +2,35 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.NumpadWidget" owl="1">
|
||||
<div class="numpad">
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('1')">1</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('2')">2</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('3')">3</button>
|
||||
<button class="mode-button" t-att-class="{'selected-mode': props.activeMode === 'quantity'}"
|
||||
<div class="numpad d-grid text-center flex-grow-1 w-50 bg-300">
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('1')">1</button>
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('2')">2</button>
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('3')">3</button>
|
||||
<button class="mode-button btn btn-light w-100 rounded-0 py-3" t-att-class="{'selected-mode': props.activeMode === 'quantity'}"
|
||||
t-on-click="() => this.changeMode('quantity')">Qty</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('4')">4</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('5')">5</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('6')">6</button>
|
||||
<button class="mode-button" t-att-class="{
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('4')">4</button>
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('5')">5</button>
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('6')">6</button>
|
||||
<button class="mode-button btn btn-light w-100 rounded-0 py-3 text-nowrap" t-att-class="{
|
||||
'selected-mode': props.activeMode === 'discount',
|
||||
'disabled-mode': !hasManualDiscount
|
||||
}"
|
||||
t-att-disabled="!hasManualDiscount"
|
||||
t-on-click="() => this.changeMode('discount')">% Disc</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('7')">7</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('8')">8</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('9')">9</button>
|
||||
<button class="mode-button" t-att-class="{
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('7')">7</button>
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('8')">8</button>
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('9')">9</button>
|
||||
<button class="mode-button btn btn-light w-100 rounded-0 py-3" t-att-class="{
|
||||
'selected-mode': props.activeMode === 'price',
|
||||
'disabled-mode': !hasPriceControlRights
|
||||
}" t-att-disabled="!hasPriceControlRights"
|
||||
t-on-click="() => this.changeMode('price')">Price</button>
|
||||
<button class="input-button numpad-minus" t-att-class="{ 'disabled-mode': props.disableSign }" t-on-click="() => this.sendInput('-')">+/-</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput('0')">0</button>
|
||||
<button class="input-button number-char" t-on-click="() => this.sendInput(decimalSeparator)">
|
||||
<button class="input-button numpad-minus btn btn-light w-100 rounded-0 py-3" t-att-class="{ 'disabled-mode': props.disableSign }" t-on-click="() => this.sendInput('-')">+/-</button>
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('0')">0</button>
|
||||
<button class="input-button number-char btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput(decimalSeparator)">
|
||||
<t t-esc="decimalSeparator" />
|
||||
</button>
|
||||
<button class="input-button numpad-backspace" t-on-click="() => this.sendInput('Backspace')">
|
||||
<button class="input-button numpad-backspace btn btn-light w-100 rounded-0 py-3" t-on-click="() => this.sendInput('Backspace')">
|
||||
<img style="pointer-events: none;" src="/point_of_sale/static/src/img/backspace.png"
|
||||
width="24" height="21" alt="Backspace" />
|
||||
</button>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* ********* The OrderWidget ********* */
|
||||
|
||||
|
||||
.pos .scrollable-y{
|
||||
overflow: hidden !important;
|
||||
overflow-y: auto !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
}
|
||||
@@ -2,17 +2,17 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.OrderWidget" owl="1">
|
||||
<div class="order-container" t-ref="scrollable">
|
||||
<div class="order">
|
||||
<div class="order-container w-100 h-100 overflow-y-auto bg-view" t-ref="scrollable">
|
||||
<div class="order d-flex flex-column h-100 text-start">
|
||||
<t t-if="orderlinesArray.length === 0" >
|
||||
<div class='order-empty'>
|
||||
<i class='fa fa-shopping-cart' role="img" aria-label="Shopping cart"
|
||||
<div class="order-empty d-flex flex-column align-items-center justify-content-center h-100 text-muted">
|
||||
<i class="fa fa-4x fa-shopping-cart" role="img" aria-label="Shopping cart"
|
||||
title="Shopping cart"/>
|
||||
<h1>This order is empty</h1>
|
||||
<h3 class="mt-2">This order is empty</h3>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<ul class="orderlines">
|
||||
<ul class="orderlines flex-grow-1 overflow-auto">
|
||||
<t t-foreach="orderlinesArray" t-as="orderline" t-key="orderline.id">
|
||||
<Orderline
|
||||
editPackLotLines.bind="editPackLotLines"
|
||||
|
||||
+4
-4
@@ -2,16 +2,16 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.OrderSummary" owl="1">
|
||||
<div class="summary clearfix">
|
||||
<div class="summary clearfix sticky-top w-100 py-2 px-3 border-top text-end fw-bolder">
|
||||
<t t-set="_total" t-value="getTotal()" />
|
||||
<t t-set="_tax" t-value="getTax()" />
|
||||
<div class="line">
|
||||
<div class="entry total">
|
||||
<span class="badge">Total: </span>
|
||||
<div class="entry total fs-2">
|
||||
Total:
|
||||
<span class="value">
|
||||
<t t-esc="_total" />
|
||||
</span>
|
||||
<div t-if="_tax.hasTax" class="subentry">
|
||||
<div t-if="_tax.hasTax" class="subentry fs-5 text-muted">
|
||||
Taxes:
|
||||
<span class="value">
|
||||
<t t-esc="_tax.displayAmount" />
|
||||
|
||||
@@ -36,9 +36,9 @@ export class Orderline extends Component {
|
||||
get addedClasses() {
|
||||
return {
|
||||
selected: this.props.line.selected,
|
||||
"has-change":
|
||||
"has-change ps-2 text-success border-start border-success border-4":
|
||||
this.props.line.hasChange && this.pos.config.module_pos_restaurant,
|
||||
"skip-change":
|
||||
"skip-change ps-2 text-secondary border-start border-secondary border-4":
|
||||
this.props.line.skipChange && this.pos.config.module_pos_restaurant,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/* ********* The OrderLineWidget ********* */
|
||||
|
||||
.orderline {
|
||||
box-sizing: border-box;
|
||||
transition: background 250ms ease-in-out;
|
||||
|
||||
&:active {
|
||||
background: rgba(140,143,183,0.05);
|
||||
transition: background 50ms ease-in-out;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: rgba($primary, 0.2);
|
||||
transition: background 250ms ease-in-out;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
+10
-11
@@ -2,14 +2,13 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.Orderline" owl="1">
|
||||
<li t-on-click="selectLine" class="orderline" t-att-class="addedClasses">
|
||||
<span class="product-name">
|
||||
<li t-on-click="selectLine" class="orderline w-100 m-0 py-2 px-3 cursor-pointer" t-att-class="addedClasses">
|
||||
<span class="product-name d-inline-block flex-grow-1 fw-bolder text-truncate">
|
||||
<t t-esc="props.line.get_full_product_name()"/>
|
||||
<span> </span>
|
||||
<t t-if="props.line.get_product().tracking!=='none' && (pos.picking_type.use_create_lots || pos.picking_type.use_existing_lots)">
|
||||
<t t-if="props.line.has_valid_product_lot()">
|
||||
<i t-on-click.stop="lotIconClicked"
|
||||
class="oe_link_icon fa fa-list oe_icon line-lot-icon oe_green"
|
||||
class="oe_link_icon fa fa-list oe_icon line-lot-icon ms-1 text-success"
|
||||
aria-label="Valid product lot"
|
||||
role="img"
|
||||
title="Valid product lot"
|
||||
@@ -17,7 +16,7 @@
|
||||
</t>
|
||||
<t t-else="">
|
||||
<i t-on-click.stop="lotIconClicked"
|
||||
class="oe_link_icon fa fa-list oe_icon line-lot-icon oe_red"
|
||||
class="oe_link_icon fa fa-list oe_icon line-lot-icon ms-1 text-danger"
|
||||
aria-label="Invalid product lot"
|
||||
role="img"
|
||||
title="Invalid product lot"
|
||||
@@ -25,13 +24,13 @@
|
||||
</t>
|
||||
</t>
|
||||
</span>
|
||||
<span class="price">
|
||||
<span class="price fw-bold float-end">
|
||||
<t t-esc="env.utils.formatCurrency(props.line.get_display_price())"/>
|
||||
</span>
|
||||
<ul class="info-list">
|
||||
<ul class="info-list ms-2">
|
||||
<t t-if="props.line.get_quantity_str() !== '1' || props.line.selected ">
|
||||
<li class="info">
|
||||
<em>
|
||||
<em class="fst-normal fw-bolder">
|
||||
<t t-esc="props.line.get_quantity_str()" />
|
||||
</em>
|
||||
<span> </span><t t-esc="props.line.get_unit().name" />
|
||||
@@ -60,14 +59,14 @@
|
||||
</li>
|
||||
</t>
|
||||
<t t-if="customerNote">
|
||||
<li class="info orderline-note">
|
||||
<i class="fa fa-sticky-note" role="img" aria-label="Customer Note" title="Customer Note"/>
|
||||
<li class="info orderline-note m-2 text-break">
|
||||
<i class="fa fa-sticky-note me-1 text-muted" role="img" aria-label="Customer Note" title="Customer Note"/>
|
||||
<t t-esc="customerNote" />
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
<t t-if="props.line.pack_lot_lines">
|
||||
<ul class="info-list">
|
||||
<ul class="info-list ms-2">
|
||||
<t t-foreach="props.line.get_lot_lines()" t-as="lot" t-key="lot.cid">
|
||||
<li>
|
||||
SN <t t-esc="lot.lot_name"/>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
.product-img img {
|
||||
height: 100px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.product:active {
|
||||
box-shadow: 0 0 0 3px $primary;
|
||||
}
|
||||
}
|
||||
|
||||
.product-name {
|
||||
|
||||
box-sizing: border-box;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
|
||||
&.no-image {
|
||||
-webkit-line-clamp: 9;
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,18 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.ProductItem" owl="1">
|
||||
<article t-attf-class="product {{this.pos.productListViewMode}}" tabindex="0" t-on-keypress="spaceClickProduct"
|
||||
<article t-attf-class="product {{this.pos.productListViewMode}} position-relative btn btn-light d-flex flex-column align-items-stretch p-0 m-0 text-start cursor-pointer overflow-hidden" tabindex="0" t-on-keypress="spaceClickProduct"
|
||||
t-on-click="() => this.pos.addProductToCurrentOrder(props.product)"
|
||||
t-att-data-product-id="props.product.id"
|
||||
t-attf-aria-labelledby="article_product_{{props.product.id}}">
|
||||
<div class="product-img">
|
||||
<img t-if="props.product.image_128" t-att-src="imageUrl" t-att-alt="props.product.display_name" />
|
||||
<img t-if="props.product.image_128" class="w-100" t-att-src="imageUrl" t-att-alt="props.product.display_name" />
|
||||
</div>
|
||||
<div class="product-content">
|
||||
<div t-attf-class="#{props.product.image_128 ? 'product-name' : 'product-name no-image' }" t-attf-id="article_product_{{props.product.id}}">
|
||||
<div class="product-content d-flex flex-column justify-content-between h-100 py-1">
|
||||
<div t-attf-class="mx-2 overflow-hidden lh-sm #{props.product.image_128 ? 'product-name' : 'product-name no-image' }" t-attf-id="article_product_{{props.product.id}}">
|
||||
<t t-esc="props.product.display_name" />
|
||||
</div>
|
||||
<span class="price-tag">
|
||||
<span class="price-tag text-primary py-1 px-2 fw-bolder">
|
||||
<t t-esc="price" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
+1
-2
@@ -24,8 +24,7 @@ export class ProductInfoPopup extends AbstractAwaitablePopup {
|
||||
this.cancel();
|
||||
}
|
||||
_hasMarginsCostsAccessRights() {
|
||||
const isAccessibleToEveryUser =
|
||||
this.pos.config.is_margins_costs_accessible_to_every_user;
|
||||
const isAccessibleToEveryUser = this.pos.config.is_margins_costs_accessible_to_every_user;
|
||||
const isCashierManager = this.pos.get_cashier().role === "manager";
|
||||
return isAccessibleToEveryUser || isCashierManager;
|
||||
}
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
.product-info-popup {
|
||||
max-width: 800px !important;
|
||||
|
||||
.modal-body {
|
||||
max-height: 70vh;
|
||||
}
|
||||
}
|
||||
+80
-77
@@ -2,29 +2,28 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="point_of_sale.ProductInfoPopup" owl="1">
|
||||
<div class="popup product-info-popup">
|
||||
<header class="title">
|
||||
Product information
|
||||
</header>
|
||||
<main class="body">
|
||||
<div class="section-product-info-title">
|
||||
<div class="column flex-start">
|
||||
<span t-esc="props.product.display_name" class="global-info-title product-name"/>
|
||||
<span><t t-if="props.product.default_code" t-esc="props.product.default_code"/> <t t-if="props.product.default_code and props.product.barcode"> - </t> <t t-if="props.product.barcode" t-esc="props.product.barcode"/></span>
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Product information</h4>
|
||||
</div>
|
||||
<main class="body modal-body overflow-auto">
|
||||
<div class="section-product-info-title d-flex flex-column flex-sm-row text-start gap-3 bg-info text-info bg-opacity-25 mx-n3 mt-n3 p-3">
|
||||
<div class="d-flex flex-column flex-grow-1 text-start w-100 w-sm-25">
|
||||
<span t-esc="props.product.display_name" class="global-info-title fs-2 fw-bolder text-truncate"/>
|
||||
<span class="fs-3"><t t-if="props.product.default_code" t-esc="props.product.default_code"/> <t t-if="props.product.default_code and props.product.barcode"> - </t> <t t-if="props.product.barcode" t-esc="props.product.barcode"/></span>
|
||||
</div>
|
||||
<div class="column flex-end">
|
||||
<span t-esc="env.utils.formatCurrency(productInfo.all_prices.price_with_tax)" class="global-info-title" />
|
||||
<t t-foreach="productInfo.all_prices.tax_details" t-as="tax" t-key="tax.name">
|
||||
<div><t t-esc="tax.name"/>: <t t-esc="env.utils.formatCurrency(tax.amount)"/></div>
|
||||
</t>
|
||||
<div class="d-flex flex-column justify-content-center text-start text-sm-end w-100 w-sm-25">
|
||||
<span t-esc="env.utils.formatCurrency(productInfo.all_prices.price_with_tax)" class="global-info-title fs-2 fw-bolder" />
|
||||
<span class="fs-3">
|
||||
<t t-foreach="productInfo.all_prices.tax_details" t-as="tax" t-key="tax.name">
|
||||
<div><t t-esc="tax.name"/>: <t t-esc="env.utils.formatCurrency(tax.amount)"/></div>
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-financials">
|
||||
<div class="section-title">
|
||||
<span>Financials</span>
|
||||
<div class="section-title-line"></div>
|
||||
</div>
|
||||
<div class="section-financials-body">
|
||||
<table>
|
||||
<div class="section-financials mt-3 mb-4 pb-4 border-bottom text-start">
|
||||
<h3 class="section-title">Financials</h3>
|
||||
<div class="section-financials-body d-flex flex-column flex-sm-row">
|
||||
<table class="table table-borderless mb-0">
|
||||
<tr>
|
||||
<td>Price excl. VAT:</td>
|
||||
<td><t t-esc="env.utils.formatCurrency(productInfo.all_prices.price_without_tax)"/></td>
|
||||
@@ -38,7 +37,7 @@
|
||||
<td><t t-esc="marginCurrency"/> (<t t-esc="marginPercent"/>%) </td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<table class="table table-borderless">
|
||||
<t t-foreach="productInfo.pricelists" t-as="pricelist" t-key="pricelist.name">
|
||||
<tr>
|
||||
<td t-esc="pricelist.name"/>
|
||||
@@ -48,71 +47,75 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-inventory" t-if="productInfo.warehouses.length > 0">
|
||||
<div class="section-title">
|
||||
<span>Inventory <t t-if="pos.pos_session.update_stock_at_closing">(as of opening)</t></span>
|
||||
<div class="section-title-line"></div>
|
||||
</div>
|
||||
<div class="section-inventory mt-3 mb-4 pb-4 border-bottom text-start" t-if="productInfo.warehouses.length > 0">
|
||||
<h3 class="section-title">
|
||||
Inventory
|
||||
<t t-if="pos.pos_session.update_stock_at_closing">(as of opening)</t>
|
||||
</h3>
|
||||
<div class="section-inventory-body">
|
||||
<table class="mobile-table">
|
||||
<t t-foreach="productInfo.warehouses" t-as="warehouse" t-key="warehouse.name">
|
||||
<tr>
|
||||
<td><span t-esc="warehouse.name" class="table-name"/>:</td>
|
||||
<td><t t-esc="warehouse.available_quantity"/> <t t-esc="warehouse.uom"/> available,</td>
|
||||
<td><t t-esc="warehouse.forecasted_quantity"/> forecasted</td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
<t t-foreach="productInfo.warehouses" t-as="warehouse" t-key="warehouse.name">
|
||||
<div class="d-flex flex-column flex-md-row gap-2">
|
||||
<div>
|
||||
<t t-esc="warehouse.name" class="table-name"/>
|
||||
:
|
||||
</div>
|
||||
<div>
|
||||
<span class="me-1 fw-bolder"><t t-esc="warehouse.available_quantity" class="table-name"/></span>
|
||||
<t t-esc="warehouse.uom"/> available,
|
||||
</div>
|
||||
<div>
|
||||
<span class="me-1 fw-bolder"><t t-esc="warehouse.forecasted_quantity"/></span>
|
||||
forecasted
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-supplier" t-if="productInfo.suppliers.length > 0">
|
||||
<div class="section-title">
|
||||
<span>Replenishment</span>
|
||||
<div class="section-title-line"></div>
|
||||
</div>
|
||||
<div class="section-supplier mt-3 mb-4 pb-4 border-bottom text-start" t-if="productInfo.suppliers.length > 0">
|
||||
<h3 class="section-title">Replenishment</h3>
|
||||
<div class="section-supplier-body">
|
||||
<table class="mobile-table">
|
||||
<t t-foreach="productInfo.suppliers" t-as="supplier" t-key="supplier.name">
|
||||
<tr>
|
||||
<td><span t-esc="supplier.name" class="table-name"/>:</td>
|
||||
<div class="mobile-line">
|
||||
<td><t t-esc="supplier.delay"/> Days</td>
|
||||
<td t-if="_hasMarginsCostsAccessRights()"><t t-esc="env.utils.formatCurrency(supplier.price)"/></td>
|
||||
</div>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
<t t-foreach="productInfo.suppliers" t-as="supplier" t-key="supplier.name">
|
||||
<div class="d-flex flex-column flex-md-row gap-2">
|
||||
<div>
|
||||
<span t-esc="supplier.name" class="table-name"/>:
|
||||
</div>
|
||||
<span class="me-1 fw-bolder">
|
||||
<t t-esc="supplier.delay"/>
|
||||
Days
|
||||
</span>
|
||||
<span t-if="_hasMarginsCostsAccessRights()">
|
||||
<t t-esc="env.utils.formatCurrency(supplier.price)"/>
|
||||
</span>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="extra">
|
||||
<div class="section-variants" t-if="productInfo.variants.length > 0">
|
||||
<div class="section-title">
|
||||
<span>Attributes</span>
|
||||
<div class="section-title-line"></div>
|
||||
</div>
|
||||
<div class="extra mt-3 mb-4 pb-4 border-bottom text-start" t-if="productInfo.variants.length > 0">
|
||||
<div class="section-variants">
|
||||
<h3 class="section-title">Attributes</h3>
|
||||
<div class="section-variants-body">
|
||||
<table class="mobile-table">
|
||||
<t t-foreach="productInfo.variants" t-as="variant" t-key="variant.name">
|
||||
<tr>
|
||||
<td><span t-esc="variant.name" class="table-name"/>:</td>
|
||||
<td class="table-value">
|
||||
<t t-foreach="variant.values" t-as="attribute_value" t-key="attribute_value.name">
|
||||
<span class="searchable" t-on-click="() => this.searchProduct(attribute_value.search)"><t t-esc="attribute_value.name"/></span> <t t-if="attribute_value_index lt variant.values.length - 1">, </t>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
<t t-foreach="productInfo.variants" t-as="variant" t-key="variant.name">
|
||||
<div class="d-flex flex-column align-items-start gap-2 mb-2">
|
||||
<div>
|
||||
<span t-esc="variant.name" class="table-name"/>:
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
<t t-foreach="variant.values" t-as="attribute_value" t-key="attribute_value.name">
|
||||
<span class="searchable btn btn-secondary" t-on-click="() => this.searchProduct(attribute_value.search)">
|
||||
<t t-esc="attribute_value.name"/>
|
||||
</span>
|
||||
<t t-if="attribute_value_index lt variant.values.length - 1"> </t>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section-order">
|
||||
<div class="section-title">
|
||||
<span>Order</span>
|
||||
<div class="section-title-line"></div>
|
||||
</div>
|
||||
<div class="section-order mt-3 mb-4 pb-4 border-bottom text-start">
|
||||
<h3 class="section-title">Order</h3>
|
||||
<div class="section-order-body">
|
||||
<table>
|
||||
<table class="table table-borderless w-100 w-sm-50 mb-0">
|
||||
<tr>
|
||||
<td>Total Price excl. VAT:</td>
|
||||
<td t-esc="orderPriceWithoutTaxCurrency" class="table-value"/>
|
||||
@@ -129,8 +132,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="footer">
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<footer class="footer modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-primary" t-on-click="cancel">
|
||||
Close
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
|
||||
.category-list-scroller{
|
||||
max-height:40vh;
|
||||
}
|
||||
|
||||
.category-button {
|
||||
.category-img {
|
||||
width: 120px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
& img {
|
||||
max-height: 100px;
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search Bar (PartnerList & Product Screens*/
|
||||
|
||||
.pos-search-bar:focus-within {
|
||||
background-color: $input-focus-bg;
|
||||
border-color: $input-focus-border-color;
|
||||
color: $input-focus-color;
|
||||
}
|
||||
|
||||
/* Product Screen Search Bar */
|
||||
|
||||
.info-load-product-message {
|
||||
background: lightblue;
|
||||
color: #017e84;
|
||||
padding: 8px;
|
||||
width: fit-content;
|
||||
display: block;
|
||||
margin : 3px auto 0 auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.pos .search-bar-container.sb-product {
|
||||
max-width: none;
|
||||
width: auto;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
+32
-32
@@ -2,57 +2,57 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.ProductsWidgetControlPanel" owl="1">
|
||||
<div class="products-widget-control" t-ref="products-widget-control">
|
||||
<div class="rightpane-header">
|
||||
<t t-if="this.pos.posHasValidProduct()">
|
||||
<div class="search-bar-container sb-product">
|
||||
<span t-if="state.isMobile" class="oe_status oe_icon icon" t-on-click="toggleMobileSearchBar">
|
||||
<i t-attf-class="fa {{state.mobileSearchBarIsShown ? 'fa-arrow-right' : 'fa-search'}}"/>
|
||||
</span>
|
||||
<t t-if="!state.isMobile || state.mobileSearchBarIsShown">
|
||||
<div class="pos-search-bar">
|
||||
<i class="fa fa-search"/>
|
||||
<input t-model="this.pos.searchProductWord" placeholder="Search Products..." type="text" autofocus="autofocus" t-on-keyup="updateSearch" />
|
||||
<i t-if="this.pos.searchProductWord" class="fa fa-times" t-on-click="_clearSearch"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
<div class="products-widget-control d-grid shadow-sm z-index-1" t-ref="products-widget-control">
|
||||
<div class="rightpane-header d-flex justify-content-between align-items-center text-center bg-view p-1 overflow-x-auto overflow-y-hidden">
|
||||
<t t-if="!props.hasNoCategories">
|
||||
<div class="categories-header">
|
||||
<div class="categories-header d-flex overflow-x-auto">
|
||||
<!-- Breadcrumbs -->
|
||||
<div class="breadcrumbs">
|
||||
<span class="breadcrumb">
|
||||
<span class="breadcrumb-button breadcrumb-home" t-on-click="() => this.props.switchCategory(0)">
|
||||
<i class="fa fa-home" role="img" aria-label="Home" title="Home"></i>
|
||||
</span>
|
||||
<div class="breadcrumbs d-flex">
|
||||
<span class="breadcrumb float-start d-flex align-items-center">
|
||||
<button class="breadcrumb-button breadcrumb-home btn btn-light fw-bolder" t-on-click="() => this.props.switchCategory(0)">
|
||||
<i class="fa fa-home fa-2x py-1" role="img" aria-label="Home" title="Home"></i>
|
||||
</button>
|
||||
</span>
|
||||
<t t-foreach="props.breadcrumbs" t-as="category" t-key="category.id">
|
||||
<span class="breadcrumb">
|
||||
<i class="breadcrumb-arrow fa fa-caret-right" aria-hidden="true"/>
|
||||
<span class="breadcrumb-button"
|
||||
<span class="breadcrumb float-start d-flex align-items-center">
|
||||
<i class="breadcrumb-arrow fa fa-caret-right px-2" aria-hidden="true"/>
|
||||
<button class="breadcrumb-button btn btn-light h-100 fw-bolder"
|
||||
t-on-click="() => this.props.switchCategory(category.id)">
|
||||
<t t-esc="category.name"></t>
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
</t>
|
||||
</div>
|
||||
<!-- Subcategories -->
|
||||
<div t-if="props.subcategories.length > 0 and !displayCategImages" class="category-list simple">
|
||||
<div t-if="props.subcategories.length > 0 and !displayCategImages" class="category-list simple d-flex align-items-center ms-1">
|
||||
<t t-foreach="props.subcategories" t-as="category" t-key="category.id">
|
||||
<span class="category-simple-button"
|
||||
<button class="category-simple-button btn btn-light h-100 fw-bolder"
|
||||
t-on-click="() => this.props.switchCategory(category.id)">
|
||||
<t t-esc="category.name" />
|
||||
</span>
|
||||
</button>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<div class="search-bar-container sb-product d-flex align-items-center h-100">
|
||||
<span t-if="state.isMobile" class="oe_status oe_icon icon d-flex align-items-center h-100 me-1 px-4 rounded text-bg-secondary cursor-pointer" t-on-click="toggleMobileSearchBar">
|
||||
<i t-attf-class="fa {{state.mobileSearchBarIsShown ? 'fa-arrow-right' : 'fa-search'}}"/>
|
||||
</span>
|
||||
<t t-if="!state.isMobile || state.mobileSearchBarIsShown">
|
||||
<div class="input-group h-100">
|
||||
<div class="pos-search-bar form-control d-flex align-items-center py-1 bg-view">
|
||||
<i class="oi oi-search me-2"/>
|
||||
<input class="flex-grow-1 w-auto h-100 border-0 px-2 me-4" t-model="this.pos.searchProductWord" placeholder="Search Products..." type="text" autofocus="autofocus" t-on-keyup="updateSearch" />
|
||||
<i t-if="this.pos.searchProductWord" class="fa fa-times position-absolute end-0 me-2 pe-1 cursor-pointer" t-on-click="_clearSearch"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="props.subcategories.length > 0 and displayCategImages">
|
||||
<div class="categories">
|
||||
<div class="category-list-scroller">
|
||||
<div class="category-list">
|
||||
<div class="categories border-bottom shadow-sm">
|
||||
<div class="category-list-scroller w-100 h-100 overflow-hidden overflow-y-auto">
|
||||
<div class="category-list d-flex flex-wrap px-1 py-2 gap-3">
|
||||
<t t-foreach="props.subcategories" t-as="category" t-key="category.id">
|
||||
<CategoryButton
|
||||
switchCategory.bind="props.switchCategory"
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
|
||||
/* ********* The product list ********* */
|
||||
|
||||
.product-list {
|
||||
grid-template-columns: repeat(auto-fill, minmax(122px, 1fr));
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
.product-list {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -2,7 +2,7 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.ProductsWidget" owl="1">
|
||||
<div class="products-widget">
|
||||
<div class="products-widget d-flex flex-column flex-grow-1 overflow-hidden">
|
||||
<ProductsWidgetControlPanel
|
||||
updateProductList.bind="updateProductList"
|
||||
clearSearch.bind="clearSearch"
|
||||
@@ -12,14 +12,14 @@
|
||||
subcategories="subcategories"
|
||||
hasNoCategories="hasNoCategories"
|
||||
loadProductFromServer.bind="onPressEnterKey" />
|
||||
<div class="product-list-container">
|
||||
<div t-if="productsToDisplay.length != 0 and posHasValidProduct" t-attf-class="{{this.pos.productListViewMode}} product-list">
|
||||
<div class="product-list-container flex-grow-1 overflow-hidden overflow-y-auto">
|
||||
<div t-if="productsToDisplay.length != 0 and posHasValidProduct" t-attf-class="{{this.pos.productListViewMode}} product-list d-grid gap-1 p-1">
|
||||
<t t-foreach="productsToDisplay" t-as="product" t-key="product.id">
|
||||
<ProductItem
|
||||
product="product" />
|
||||
</t>
|
||||
</div>
|
||||
<div t-else="" class="product-list-empty no-results-message">
|
||||
<div t-else="" class="product-list-empty no-results-message text-center mt-5">
|
||||
<t t-if="searchWord">
|
||||
<p>No products found for <b>"<t t-esc="searchWord"/>"</b> in this category.</p>
|
||||
</t>
|
||||
@@ -30,7 +30,7 @@
|
||||
<t t-else="">
|
||||
<div>
|
||||
<p>No products here, but don't worry, we've got your back.</p>
|
||||
<p>Play with <a role="button" class="button-no-demo" t-on-click="loadDemoDataProducts">our demo products</a> or <a role="button" class="button-no-demo" t-on-click="createNewProducts">create your own products</a></p>
|
||||
<p>Play with <a role="button" class="button-no-demo btn btn-lg btn-primary" t-on-click="loadDemoDataProducts">our demo products</a> or <a role="button" class="button-no-demo" t-on-click="createNewProducts">create your own products</a></p>
|
||||
<div t-if="state.showReloadMessage" class="info-load-product-message">
|
||||
Please reload this page once products have been created
|
||||
</div>
|
||||
@@ -38,8 +38,8 @@
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="searchWord" class="search-more-button">
|
||||
<div class="button" t-on-click="onPressEnterKey">Search more</div>
|
||||
<div t-if="searchWord" class="search-more-button d-flex justify-content-center">
|
||||
<button class="btn btn-primary btn-lg" t-on-click="onPressEnterKey">Search more</button>
|
||||
</div>
|
||||
<div class="portal search-database-button no-results-message" t-att-class="{ oe_hidden: !shouldShowButton }"></div>
|
||||
</div>
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
|
||||
<t t-name="point_of_sale.ProductScreen" owl="1">
|
||||
<div class="product-screen screen" t-att-class="{ oe_hidden: !props.isShown }">
|
||||
<div class="screen-full-width">
|
||||
<div class="leftpane pane-border" t-if="!ui.isSmall || pos.mobile_pane === 'left'">
|
||||
<div class="screen-full-width d-flex w-100 h-100">
|
||||
<div class="leftpane pane-border d-flex flex-column flex-grow-1 w-100 h-100 border-end border-3 bg-200" t-if="!ui.isSmall || pos.mobile_pane === 'left'">
|
||||
<OrderWidget/>
|
||||
<div class="pads">
|
||||
<div class="control-buttons">
|
||||
<div class="pads border-top">
|
||||
<div class="control-buttons d-flex flex-wrap border-bottom overflow-hidden">
|
||||
<t t-if="!ui.isSmall">
|
||||
<t t-foreach="controlButtons" t-as="cb" t-key="cb.name">
|
||||
<t t-component="cb.component" t-key="cb.name"/>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
<div class="subpads">
|
||||
<div class="subpads d-flex">
|
||||
<ActionpadWidget
|
||||
partner="partner"
|
||||
actionName="constructor.numpadActionName"
|
||||
@@ -26,20 +26,19 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rightpane" t-if="!ui.isSmall || pos.mobile_pane === 'right'">
|
||||
<div class="rightpane d-flex flex-column flex-grow-1 w-100 h-100 bg-300" t-if="!ui.isSmall || pos.mobile_pane === 'right'">
|
||||
<ProductsWidget />
|
||||
<t t-if="ui.isSmall">
|
||||
<div class="product-reminder" t-if="showProductReminder" t-key="animationKey">
|
||||
<span><t t-esc="selectedOrderlineQuantity"/> <t t-esc="selectedOrderlineDisplayName"/></span>
|
||||
<span><t t-esc="selectedOrderlineTotal"/></span>
|
||||
<div class="product-reminder d-flex justify-content-center align-items-center py-1 text-bg-warning bg-opacity-50 fw-bolder" t-if="showProductReminder" t-key="animationKey" >
|
||||
<span><t t-esc="selectedOrderlineQuantity"/> <t t-esc="selectedOrderlineDisplayName"/> <t t-esc="selectedOrderlineTotal"/></span>
|
||||
</div>
|
||||
<div class="switchpane">
|
||||
<button class="btn-switchpane pay-button" t-att-class="{'primary': primaryPayButton(), 'secondary': !primaryPayButton()}" t-on-click="() => currentOrder.pay()">
|
||||
<h1>Pay</h1>
|
||||
<div class="switchpane d-flex">
|
||||
<button class="btn-switchpane pay-button btn btn-primary flex-fill rounded-0 fw-bolder" t-att-class="{'primary': primaryPayButton(), 'secondary': !primaryPayButton()}" t-on-click="() => currentOrder.pay()">
|
||||
<span class="fs-1 d-block">Pay</span>
|
||||
<span><t t-esc="total" /></span>
|
||||
</button>
|
||||
<button class="btn-switchpane" t-att-class="{'primary': primaryReviewButton(), 'secondary': !primaryReviewButton()}" t-on-click="switchPane">
|
||||
<h1>Review</h1>
|
||||
<button class="btn-switchpane btn btn-secondary flex-fill rounded-0 fw-bolder" t-att-class="{'primary': primaryReviewButton(), 'secondary': !primaryReviewButton()}" t-on-click="switchPane">
|
||||
<span class="fs-1 d-block">Review</span>
|
||||
<span><t t-esc="items_number"/> items</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.OrderReceipt" owl="1">
|
||||
<div class="pos-receipt">
|
||||
<div class="pos-receipt d-inline-block m-3 p-3 border rounded bg-view text-start overflow-hidden">
|
||||
<t t-if="receipt.company.logo">
|
||||
<img class="pos-receipt-logo" t-att-src="receipt.company.logo" alt="Logo"/>
|
||||
<br/>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
.pos-receipt-container {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.receipt-screen .default-view .pos-receipt-container {
|
||||
flex: 0 1 400px;
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
.receipt-screen .default-view .pos-receipt-container {
|
||||
flex: 1;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@page {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
background: white;
|
||||
}
|
||||
body * {
|
||||
visibility: hidden;
|
||||
}
|
||||
.pos, .pos * {
|
||||
position: static !important;
|
||||
}
|
||||
.pos .receipt-screen .pos-receipt-container {
|
||||
position: absolute !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.pos .receipt-screen .pos-receipt-container, .pos .receipt-screen .pos-receipt-container * {
|
||||
visibility: visible;
|
||||
background: white !important;
|
||||
color: black !important;
|
||||
}
|
||||
.pos .pos-receipt {
|
||||
margin: 0 !important;
|
||||
margin-left: auto !important;
|
||||
margin-right: auto !important;
|
||||
border: none !important;
|
||||
font-size: 14px !important;
|
||||
width: 266px !important;
|
||||
}
|
||||
}
|
||||
@@ -3,80 +3,71 @@
|
||||
|
||||
<t t-name="point_of_sale.ReceiptScreen" owl="1">
|
||||
<div class="receipt-screen screen">
|
||||
<div class="screen-content">
|
||||
<div class="top-content" t-if="!ui.isSmall">
|
||||
<div class="top-content-center">
|
||||
<h1>
|
||||
<div class="screen-content d-flex flex-column justify-content-between h-100">
|
||||
<div class="top-content d-flex align-items-center py-3 border-bottom text-center" t-if="!ui.isSmall">
|
||||
<div class="top-content-center flex-grow-1">
|
||||
<h1 class="mb-0">
|
||||
<t t-esc="orderAmountPlusTip" />
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="default-view">
|
||||
<div class="actions">
|
||||
<div class="default-view d-flex flex-md-row flex-column overflow-hidden">
|
||||
<div class="actions flex-md-grow-1 flex-grow-0 flex-shrink-1 flex-basis-0 m-4">
|
||||
<h1>Payment Successful</h1>
|
||||
<div class="buttons">
|
||||
<div class="button print" t-on-click="printReceipt">
|
||||
<i class="fa fa-print" t-ref="order-print-receipt-button"></i> Print Receipt
|
||||
</div>
|
||||
<div class="buttons my-3">
|
||||
<button class="button print btn btn-lg btn-secondary w-100 py-3" t-on-click="printReceipt">
|
||||
<i class="fa fa-print ms-2" t-ref="order-print-receipt-button"></i> Print Receipt
|
||||
</button>
|
||||
</div>
|
||||
<form t-on-submit.prevent="onSendEmail" class="send-email">
|
||||
<div class="input-email">
|
||||
<input type="email" t-attf-placeholder="Email: {{currentOrder.getEmailItems().join(', ')}}" t-model="orderUiState.inputEmail" />
|
||||
<button class="send" t-att-class="{ highlight: isValidEmail() }" type="submit">
|
||||
<form t-on-submit.prevent="onSendEmail" class="send-email d-flex">
|
||||
<div class="input-email input-group">
|
||||
<input type="email" class="form-control py-3 bg-view" t-attf-placeholder="Email: {{currentOrder.getEmailItems().join(', ')}}" t-model="orderUiState.inputEmail" />
|
||||
<button class="send btn px-5" t-att-class="isValidEmail() ? 'highlight btn btn-primary' : 'btn-secondary disabled'" type="submit">
|
||||
<i class="fa fa-paper-plane" aria-hidden="true" t-ref="order-mail-receipt-button" />
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="notice">
|
||||
<div t-if="orderUiState.emailSuccessful !== null" t-attf-class="{{ orderUiState.emailSuccessful ? 'successful' : 'failed' }}">
|
||||
<div class="notice mt-2">
|
||||
<div t-if="orderUiState.emailSuccessful !== null" t-attf-class="{{ orderUiState.emailSuccessful ? 'successful text-success' : 'failed text-danger' }}">
|
||||
<t t-esc="orderUiState.emailNotice"></t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pos-receipt-container" t-ref="order-receipt">
|
||||
<div class="pos-receipt-container bg-200 text-center overflow-auto" t-ref="order-receipt">
|
||||
<OrderReceipt order="currentOrder"/>
|
||||
</div>
|
||||
</div>
|
||||
<t t-set="splittedOrder" t-value="this.currentOrder.originalSplittedOrder and !this.currentOrder.originalSplittedOrder.finalized"/>
|
||||
<div t-if="!ui.isSmall" class="validation-buttons">
|
||||
<div class="button next validation" t-att-class="{ highlight: !locked }"
|
||||
<div t-if="!ui.isSmall" class="validation-buttons d-flex w-100 gap-1 sticky-bottom">
|
||||
<button class="button next validation btn btn-primary w-100 py-5 rounded-0 fs-2" t-att-class="{ highlight: !locked }"
|
||||
t-if="!splittedOrder"
|
||||
t-on-click="orderDone" name="done">
|
||||
<div class="pay-circle">
|
||||
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
</div>
|
||||
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
New Order
|
||||
</div>
|
||||
<div t-if="isResumeVisible() and !splittedOrder" class="button next validation" t-att-class="{ highlight: !locked }"
|
||||
</button>
|
||||
<button t-if="isResumeVisible() and !splittedOrder" class="button next validation btn btn-primary w-100 py-5 rounded-0 fs-2" t-att-class="{ highlight: !locked }"
|
||||
t-on-click="resumeOrder" name="resume">
|
||||
<div class="pay-circle">
|
||||
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
</div>
|
||||
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
Resume Order
|
||||
</div>
|
||||
<div t-if="splittedOrder" class="button next validation" t-att-class="{ highlight: !locked }"
|
||||
</button>
|
||||
<button t-if="splittedOrder" class="button next validation btn btn-primary w-100 py-5 rounded-0 fs-2" t-att-class="{ highlight: !locked }"
|
||||
t-on-click="continueSplitting" name="resume">
|
||||
<div class="pay-circle">
|
||||
<i class="fa fa-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
</div>
|
||||
Continue
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div t-else="" class="switchpane">
|
||||
<div class="btn-switchpane validation-button" t-att-class="{ highlight: !locked }"
|
||||
<div t-else="" class="switchpane d-flex">
|
||||
<div class="btn-switchpane validation-button btn btn-primary flex-fill py-3 rounded-0 fw-bolder" t-att-class="{ highlight: !locked }"
|
||||
t-if="!splittedOrder"
|
||||
t-on-click="orderDone" name="done">
|
||||
New Order
|
||||
</div>
|
||||
<div t-if="isResumeVisible() and !splittedOrder" class="btn-switchpane validation-button" t-att-class="{ highlight: !locked }"
|
||||
<div t-if="isResumeVisible() and !splittedOrder" class="btn-switchpane validation-button btn btn-primary flex-fill py-3 rounded-0 fw-bolder" t-att-class="{ highlight: !locked }"
|
||||
t-on-click="resumeOrder" name="resume">
|
||||
Resume Order
|
||||
</div>
|
||||
<div t-if="splittedOrder" class="btn-switchpane validation-button" t-att-class="{ highlight: !locked }"
|
||||
<div t-if="splittedOrder" class="btn-switchpane validation-button btn btn-primary flex-fill py-3 rounded-0 fw-bolder" t-att-class="{ highlight: !locked }"
|
||||
t-on-click="continueSplitting" name="resume">
|
||||
<div class="pay-circle">
|
||||
<i class="fa fa-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
</div>
|
||||
Continue
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+10
-10
@@ -3,19 +3,19 @@
|
||||
|
||||
<t t-name="point_of_sale.ReprintReceiptScreen" owl="1">
|
||||
<div class="receipt-screen screen">
|
||||
<div class="screen-content">
|
||||
<div class="top-content">
|
||||
<span class="button back" t-on-click="confirm">
|
||||
<i class="fa fa-angle-double-left"></i>
|
||||
<div class="screen-content d-flex flex-column h-100">
|
||||
<div class="top-content d-flex align-items-center p-2 border-bottom text-center">
|
||||
<button class="button back btn btn-lg btn-secondary" t-on-click="confirm">
|
||||
<i class="fa fa-angle-double-left me-2"></i>
|
||||
<span> </span>
|
||||
<span>Back</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="centered-content">
|
||||
<div class="button print" t-on-click="tryReprint">
|
||||
<i class="fa fa-print"></i> Print Receipt
|
||||
</div>
|
||||
<div class="pos-receipt-container" t-ref="order-receipt">
|
||||
<div class="centered-content d-grid mx-autp mt-3 border-0 overflow-hidden">
|
||||
<button class="button print btn btn-lg btn-primary" t-on-click="tryReprint">
|
||||
<i class="fa fa-print ms-2"></i> Print Receipt
|
||||
</button>
|
||||
<div class="pos-receipt-container mt-2 bg-200 text-center overflow-y-auto" t-ref="order-receipt">
|
||||
<OrderReceipt order="props.order"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.computed-price, .weight {
|
||||
font-family: Inconsolata;
|
||||
text-shadow: 0px 2px 0px rgb(210,210,210);
|
||||
box-shadow: 0px 2px 0px rgb(225,225,225) inset;
|
||||
}
|
||||
@@ -3,34 +3,36 @@
|
||||
|
||||
<t t-name="point_of_sale.ScaleScreen" owl="1">
|
||||
<div class="scale-screen screen">
|
||||
<div class="screen-content">
|
||||
<div class="top-content">
|
||||
<span class="button back" t-on-click="back">
|
||||
<i class="fa fa-angle-double-left"></i>
|
||||
<div class="screen-content d-flex flex-column h-100">
|
||||
<div class="top-content d-flex align-items-center p-2 border-bottom text-center">
|
||||
<button class="button back btn btn-lg btn-secondary" t-on-click="back">
|
||||
<i class="fa fa-angle-double-left me-2"></i>
|
||||
Back
|
||||
</span>
|
||||
<h1 class="product-name">
|
||||
</button>
|
||||
<h1 class="product-name flex-grow-1 m-0">
|
||||
<t t-esc="productName" />
|
||||
</h1>
|
||||
</div>
|
||||
<div class="centered-content">
|
||||
<div class="weight js-weight">
|
||||
<div class="centered-content w-100 mx-auto mt-3 border-left border-right text-center overflow-x-hidden overflow-y-auto">
|
||||
<div class="weight js-weight m-2 p-4 rounded bg-view text-center fs-1">
|
||||
<t t-esc="productWeightString" />
|
||||
</div>
|
||||
<div class="product-price">
|
||||
<t
|
||||
t-esc="env.utils.formatCurrency(productPrice) + '/' + productUom" />
|
||||
<div class="d-flex flex-row gap-2 m-2">
|
||||
<div class="product-price d-flex align-items-center justify-content-center flex-grow-1 rounded text-bg-info bg-opacity-25 text-info fs-2">
|
||||
<t
|
||||
t-esc="env.utils.formatCurrency(productPrice) + '/' + productUom" />
|
||||
</div>
|
||||
<div class="computed-price flex-grow-1 p-3 bg-view rounded text-center fs-2 fw-bold">
|
||||
<t t-esc="computedPriceString" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="computed-price">
|
||||
<t t-esc="computedPriceString" />
|
||||
</div>
|
||||
<div class="buy-product" t-on-click="confirm">
|
||||
<div class="buy-product btn btn-lg btn-primary d-flex align-items-center justify-content-center mx-2 mb-2 cursor-pointer" t-on-click="confirm">
|
||||
Order
|
||||
<i class="fa fa-angle-double-right"></i>
|
||||
<i class="fa fa-angle-double-right ms-2"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
</templates>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/* ********* The Screens ********* */
|
||||
|
||||
.pos .screen {
|
||||
height: calc(100vh - #{$navbar-height});
|
||||
background: $gray-100;
|
||||
}
|
||||
|
||||
/* a) Generic Screen Layout Constructs */
|
||||
|
||||
.full-content{
|
||||
top: 65px;
|
||||
}
|
||||
|
||||
.left-content{
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
border-right: solid 1px $gray-300;
|
||||
flex-grow: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.center-content{
|
||||
flex-grow: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.right-content {
|
||||
flex-grow: 1;
|
||||
min-width: 200px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
border-left: solid 1px $gray-300;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.left-content {
|
||||
max-width: 34%
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -2,11 +2,11 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.InvoiceButton" owl="1">
|
||||
<div class="control-button" t-on-click="() => this.click()" t-ref="invoice-button">
|
||||
<i class="fa fa-file-pdf-o"></i>
|
||||
<button class="control-button btn btn-light rounded-0 fw-bolder" t-on-click="() => this.click()" t-ref="invoice-button">
|
||||
<i class="fa fa-file-pdf-o me-1"></i>
|
||||
<span> </span>
|
||||
<span><t t-esc="commandName"></t></span>
|
||||
</div>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
+13
-13
@@ -2,25 +2,25 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.OrderDetails" owl="1">
|
||||
<div class="order-container">
|
||||
<div t-ref="scrollable" class="order-scroller touch-scrollable">
|
||||
<div class="order">
|
||||
<div class="order-container h-100 overflow-y-auto bg-view">
|
||||
<div t-ref="scrollable" class="order-scroller touch-scrollable h-100">
|
||||
<div class="order d-flex flex-column h-100 text-start">
|
||||
<t t-if="!props.order">
|
||||
<div class="order-empty">
|
||||
<i class="fa fa-shopping-cart" role="img" aria-label="Shopping cart"
|
||||
<div class="order-empty d-flex flex-column align-items-center justify-content-center h-100 text-muted">
|
||||
<i class="fa fa fa-4x fa-shopping-cart" role="img" aria-label="Shopping cart"
|
||||
title="Shopping cart" />
|
||||
<h1>Select an order</h1>
|
||||
<h3 class="mt-2">Select an order</h3>
|
||||
</div>
|
||||
</t>
|
||||
<t t-elif="orderlines.length === 0">
|
||||
<div class="order-empty">
|
||||
<i class="fa fa-shopping-cart" role="img" aria-label="Shopping cart"
|
||||
<i class="fa fa fa-4x fa-shopping-cart" role="img" aria-label="Shopping cart"
|
||||
title="Shopping cart" />
|
||||
<h1>Order is empty</h1>
|
||||
<h3 class="mt-2">Order is empty</h3>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="header-note" t-att-class="{ highlight: props.highlightHeaderNote }">
|
||||
<div class="header-note text-bg-view py-2 px-3 border-bottom" t-att-class="{ 'highlight text-danger': props.highlightHeaderNote }">
|
||||
Select the product(s) to refund and set the quantity
|
||||
</div>
|
||||
<ul class="orderlines">
|
||||
@@ -33,14 +33,14 @@
|
||||
</t>
|
||||
</ul>
|
||||
<!-- Not using OrderSummary because we don't need it's overrides in this view. -->
|
||||
<div class="summary clearfix">
|
||||
<div class="summary clearfix sticky-top w-100 py-2 px-3 border-top text-end fw-bolder">
|
||||
<div class="line">
|
||||
<div class="entry total">
|
||||
<span class="badge">Total: </span>
|
||||
<div class="entry total fs-2">
|
||||
Total:
|
||||
<span class="value">
|
||||
<t t-esc="total" />
|
||||
</span>
|
||||
<div t-if="tax" class="subentry">
|
||||
<div t-if="tax" class="subentry fs-5 text-muted">
|
||||
Taxes:
|
||||
<span class="value">
|
||||
<t t-esc="tax" />
|
||||
|
||||
+9
-9
@@ -2,14 +2,14 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.OrderlineDetails" owl="1">
|
||||
<li class="orderline" t-on-click="() => this.props.onClickOrderline(props.line)" t-att-class="{ selected: props.isSelected }">
|
||||
<span class="product-name">
|
||||
<li class="orderline w-100 m-0 py-2 px-3 cursor-pointer" t-on-click="() => this.props.onClickOrderline(props.line)" t-att-class="{ selected: props.isSelected }">
|
||||
<span class="product-name d-inline-block flex-grow-1 fw-bolder text-truncate">
|
||||
<t t-esc="productName" />
|
||||
</span>
|
||||
<span class="price">
|
||||
<span class="price fw-bold float-end">
|
||||
<t t-esc="totalPrice" />
|
||||
</span>
|
||||
<ul class="info-list">
|
||||
<ul class="info-list ms-2">
|
||||
<li class="info">
|
||||
<strong>
|
||||
<t t-esc="quantity" />
|
||||
@@ -17,13 +17,13 @@
|
||||
<span><t t-esc="pricePerUnit" /></span>
|
||||
</li>
|
||||
<t t-if="customerNote">
|
||||
<li class="info orderline-note">
|
||||
<i class="fa fa-sticky-note" role="img" aria-label="Customer Note" title="Customer Note"/>
|
||||
<li class="info orderline-note me-2 text-break">
|
||||
<i class="fa fa-sticky-note me-1 text-muted" role="img" aria-label="Customer Note" title="Customer Note"/>
|
||||
<t t-esc="customerNote" />
|
||||
</li>
|
||||
</t>
|
||||
<t t-if="hasRefundedQty()">
|
||||
<li class="info refund-note">
|
||||
<li class="info refund-note mt-1">
|
||||
<strong>
|
||||
<t t-esc="getFormattedRefundedQty()" />
|
||||
</strong>
|
||||
@@ -31,11 +31,11 @@
|
||||
</li>
|
||||
</t>
|
||||
<t t-if="hasToRefundQty()">
|
||||
<li class="info to-refund-highlight refund-note">
|
||||
<li class="info to-refund-highlight refund-note mt-1 fw-bold text-primary">
|
||||
<t t-set="_destinationOrderUid" t-value="getToRefundDetail().destinationOrderUid"/>
|
||||
<t t-if="_destinationOrderUid">
|
||||
<t t-esc="getRefundingMessage()" />
|
||||
<span t-esc="_destinationOrderUid" class="order-link" t-on-click.stop="() => this.props.onClickRefundOrderUid(_destinationOrderUid)" />
|
||||
<span t-esc="_destinationOrderUid" class="order-link text-decoration-underline cursor-pointer" t-on-click.stop="() => this.props.onClickRefundOrderUid(_destinationOrderUid)" />
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-esc="getToRefundMessage()" />
|
||||
|
||||
+3
-3
@@ -2,11 +2,11 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.ReprintReceiptButton" owl="1">
|
||||
<div class="control-button" t-on-click="() => this.click()">
|
||||
<i class="fa fa-print"></i>
|
||||
<button class="control-button btn btn-light rounded-0 fw-bolder" t-on-click="() => this.click()">
|
||||
<i class="fa fa-print me-1"></i>
|
||||
<span> </span>
|
||||
<span>Print Receipt</span>
|
||||
</div>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.SearchBar" owl="1">
|
||||
<div class="pos-search-bar">
|
||||
<div class="search">
|
||||
<span class="search-icon" t-if="!ui.isSmall"><i class="fa fa-search"></i></span>
|
||||
<div class="pos-search-bar d-flex align-items-center flex-grow-1 h-100 ms-3 rounded">
|
||||
<div class="search position-relative h-100 d-flex flex-grow-1">
|
||||
<span class="search-icon" t-if="!ui.isSmall"><i class="oi oi-search"></i></span>
|
||||
<input class="radius-left" t-ref="autofocus" t-att-class="{ 'radius-right': !props.config.filter.show }"
|
||||
t-model="state.searchInput" t-on-keydown="onSearchInputKeydown" t-on-keyup="onSearchInputKeyup" type="text" t-att-placeholder="props.placeholder" />
|
||||
<div t-if="state.showSearchFields and state.searchInput" class="fields">
|
||||
@@ -24,7 +24,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="props.config.filter.show" class="filter radius-right"
|
||||
<div t-if="props.config.filter.show" class="filter radius-right h-100"
|
||||
t-on-click.stop="() => { state.showFilterOptions = !state.showFilterOptions }">
|
||||
<span class="down-icon">
|
||||
<i class="oi oi-chevron-down" aria-hidden="true"></i>
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
.left-pane {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
.screen-full-width {
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
min-height: 100%;
|
||||
}
|
||||
.controls {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: $gray-300;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.ticket-screen .order,
|
||||
.ticket-screen .leftpane {
|
||||
max-width: inherit;
|
||||
}
|
||||
|
||||
.ticket-screen .rightpane {
|
||||
width: auto;
|
||||
}
|
||||
.pos .orders {
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
|
||||
.orders .col {
|
||||
flex: 1;
|
||||
|
||||
&.very-narrow {
|
||||
flex: 0.2;
|
||||
}
|
||||
|
||||
&.narrow {
|
||||
flex: 0.5;
|
||||
}
|
||||
|
||||
&.wide {
|
||||
flex: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.order-row:hover {
|
||||
color: white;
|
||||
background-color: $primary !important;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.order-row {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.order-row:nth-child(odd) {
|
||||
background: $gray-200;
|
||||
}
|
||||
|
||||
.order-row:nth-child(even) {
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.order-row {
|
||||
margin: 5px;
|
||||
border: 1px solid #C9CCD2; /* $border-color */
|
||||
background: white; /* $o-view-background-color */
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.pos .orders .col.end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.pos .orders .order-row > .col > div:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ticket-screen .order-row .delete-button {
|
||||
margin-top: 5px;
|
||||
justify-content: center;
|
||||
background: #d23f3a /* o-text-color('danger') */ ;
|
||||
color: white;
|
||||
}
|
||||
.ticket-screen .order-row .delete-button .fa-trash {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search bar ticket screen */
|
||||
|
||||
|
||||
.ticket-screen .pos-search-bar .search input {
|
||||
width: 0;
|
||||
color: #63717f;
|
||||
padding-left: 40px;
|
||||
border: solid 1px rgb(209, 209, 209);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .radius-right {
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .radius-left {
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .fa {
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search .search-icon {
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 10px;
|
||||
z-index: 1;
|
||||
color: #4f5b66;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search .fields {
|
||||
position: absolute;
|
||||
top: calc(100% + 5px);
|
||||
right: 2px;
|
||||
left: 2px;
|
||||
box-shadow: 1px 1px 3px grey;
|
||||
overflow: auto;
|
||||
}
|
||||
.ticket-screen .pos-search-bar .search ul {
|
||||
background: white;
|
||||
font-size: small;
|
||||
display: inline-block;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search li {
|
||||
margin: 0.2em 0;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
padding-left: 35px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search li .term {
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search li:hover {
|
||||
background: #DDD;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search li .field {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search li .term {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .search li.highlight {
|
||||
background: #DDD;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .filter .down-icon {
|
||||
position: absolute;
|
||||
right: 13px;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .filter {
|
||||
background: white;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
padding-left: 15px;
|
||||
padding-right: 40px;
|
||||
border: solid 1px rgb(209, 209, 209);
|
||||
border-left: none;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .filter:hover {
|
||||
color: #868686;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .filter .options {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: calc(100% + 5px);
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
box-shadow: 1px 1px 5px grey;
|
||||
padding: 0.5em 0;
|
||||
background: white;
|
||||
color: $gray-700;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .filter ul.options li {
|
||||
padding: 0.2em 1.2em;
|
||||
border-top: none;
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ticket-screen .filter ul.options li.indented {
|
||||
text-indent: 1em;
|
||||
}
|
||||
|
||||
.ticket-screen .pos-search-bar .filter ul.options li:hover {
|
||||
background-color: #DDD;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.ticket-screen .pos-search-bar .search input {
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
<t t-name="point_of_sale.TicketScreen" owl="1">
|
||||
<div class="ticket-screen screen" t-att-class="{ oe_hidden: !props.isShown }">
|
||||
<div class="screen-full-width">
|
||||
<div class="rightpane pane-border">
|
||||
<div class="controls">
|
||||
<div class="screen-full-width d-flex w-100 h-100">
|
||||
<div class="rightpane pane-border d-flex flex-column flex-grow-1 w-100 h-50 h-md-100 bg-300 overflow-y-auto">
|
||||
<div class="controls d-flex align-items-center justify-content-between p-3">
|
||||
<t t-if="!ui.isSmall || !state.showSearchBar">
|
||||
<div class="buttons">
|
||||
<button class="discard" t-on-click="() => this.pos.closeScreen()">
|
||||
<div class="buttons d-flex gap-2">
|
||||
<button class="discard btn btn-lg btn-light" t-on-click="() => this.pos.closeScreen()">
|
||||
<span class="search-icon">
|
||||
<i class="fa fa-angle-double-left"/>
|
||||
</span>
|
||||
@@ -16,19 +16,19 @@
|
||||
Back
|
||||
</t>
|
||||
</button>
|
||||
<button t-if="allowNewOrders" class="highlight" t-on-click="() => this.onCreateNewOrder()">New Order</button>
|
||||
<button t-if="allowNewOrders" class="highlight btn btn-lg btn-primary" t-on-click="() => this.onCreateNewOrder()">New Order</button>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="ui.isSmall">
|
||||
<t t-if="state.showSearchBar">
|
||||
<button class="arrow-left" t-on-click="() => { state.showSearchBar = !state.showSearchBar }">
|
||||
<button class="arrow-left btn btn-lg btn-light" t-on-click="() => { state.showSearchBar = !state.showSearchBar }">
|
||||
<span class="search-icon">
|
||||
<i class="fa fa-angle-double-left"/>
|
||||
</span>
|
||||
</button>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<button class="search" t-on-click="() => { state.showSearchBar = !state.showSearchBar }">
|
||||
<button class="search btn btn-lg btn-light" t-on-click="() => { state.showSearchBar = !state.showSearchBar }">
|
||||
<span class="search-icon">
|
||||
<i class="fa fa-search"/>
|
||||
</span>
|
||||
@@ -55,61 +55,61 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="orders">
|
||||
<div class="orders overflow-y-auto">
|
||||
<t t-set="_filteredOrderList" t-value="getFilteredOrderList()" />
|
||||
<t t-if="_filteredOrderList.length !== 0">
|
||||
<div class="header-row" t-att-class="{ oe_hidden: ui.isSmall }">
|
||||
<div class="col wide">Date</div>
|
||||
<div class="col wide">Receipt Number</div>
|
||||
<div class="col">Customer</div>
|
||||
<div class="col wide" t-if="showCardholderName()">Cardholder Name</div>
|
||||
<div class="col">Cashier</div>
|
||||
<div class="col end">Total</div>
|
||||
<div class="col narrow">Status</div>
|
||||
<div class="col very-narrow" name="delete"></div>
|
||||
<div class="header-row d-flex text-bg-700 fw-bolder" t-att-class="{ oe_hidden: ui.isSmall }">
|
||||
<div class="col wide p-2">Date</div>
|
||||
<div class="col wide p-2">Receipt Number</div>
|
||||
<div class="col p-2">Customer</div>
|
||||
<div class="col wide p-2" t-if="showCardholderName()">Cardholder Name</div>
|
||||
<div class="col p-2">Cashier</div>
|
||||
<div class="col end p-2">Total</div>
|
||||
<div class="col narrow p-2">Status</div>
|
||||
<div class="col very-narrow p-2" name="delete"></div>
|
||||
</div>
|
||||
<t t-foreach="_filteredOrderList" t-as="order" t-key="order.cid">
|
||||
<div class="order-row" t-att-class="{ highlight: isHighlighted(order) }" t-on-click="() => this.onClickOrder(order)">
|
||||
<div class="col wide">
|
||||
<div class="order-row" t-att-class="{ 'highlight text-bg-primary': isHighlighted(order) }" t-on-click="() => this.onClickOrder(order)">
|
||||
<div class="col wide p-2 ">
|
||||
<div><t t-esc="getDate(order)"></t></div>
|
||||
<div t-if="ui.isSmall"><t t-esc="getTotal(order)"></t></div>
|
||||
</div>
|
||||
<div class="col wide">
|
||||
<div class="col wide p-2">
|
||||
<div><t t-esc="order.name"></t></div>
|
||||
<div t-if="ui.isSmall"><t t-esc="getStatus(order)"></t></div>
|
||||
</div>
|
||||
<div class="col" t-if="!ui.isSmall">
|
||||
<div class="col p-2" t-if="!ui.isSmall">
|
||||
<div><t t-esc="getPartner(order)"></t></div>
|
||||
</div>
|
||||
<div t-if="showCardholderName() and !ui.isSmall" class="col">
|
||||
<div t-if="showCardholderName() and !ui.isSmall" class="col p-2">
|
||||
<div><t t-esc="getCardholderName(order)"></t></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="col p-2">
|
||||
<div t-if="ui.isSmall"><t t-esc="getPartner(order)"></t></div>
|
||||
<div t-att-class = "ui.isSmall ? 'cashier':''"><t t-esc="getCashier(order)"></t></div>
|
||||
</div>
|
||||
<div class="col end" t-if="!ui.isSmall">
|
||||
<div class="col end p-2" t-if="!ui.isSmall">
|
||||
<div><t t-esc="getTotal(order)"></t></div>
|
||||
</div>
|
||||
<div class="col narrow" t-if="!ui.isSmall">
|
||||
<div class="col narrow p-2" t-if="!ui.isSmall">
|
||||
<div><t t-esc="getStatus(order)"></t></div>
|
||||
</div>
|
||||
<div t-if="!shouldHideDeleteButton(order)" class="col very-narrow delete-button" name="delete" t-on-click.stop="() => this.onDeleteOrder(order)">
|
||||
<div t-if="!shouldHideDeleteButton(order)" class="col very-narrow delete-button p-2" name="delete" t-on-click.stop="() => this.onDeleteOrder(order)">
|
||||
<i class="fa fa-trash" aria-hidden="true"/><t t-if="ui.isSmall"> Delete</t>
|
||||
</div>
|
||||
<div t-else="" class="col very-narrow"></div>
|
||||
<div t-else="" class="col very-narrow p-2"></div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="empty-order-list">
|
||||
<i role="img" aria-label="Shopping cart" title="Shopping cart" class="fa fa-shopping-cart"></i>
|
||||
<h1>No orders found</h1>
|
||||
<div class="empty-order-list m-5 text-center text-muted">
|
||||
<i role="img" aria-label="Shopping cart" title="Shopping cart" class="fa fa-4x fa-shopping-cart"></i>
|
||||
<h3 class="mt-2">No orders found</h1>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="leftpane">
|
||||
<div class="leftpane d-flex flex-column flex-grow-1 w-100 h-50 h-md-100 bg-200">
|
||||
<t t-set="_selectedSyncedOrder" t-value="getSelectedSyncedOrder()" />
|
||||
<t t-set="_selectedOrderlineId" t-value="getSelectedOrderlineId()" />
|
||||
<OrderDetails
|
||||
@@ -118,14 +118,14 @@
|
||||
order="_selectedSyncedOrder"
|
||||
selectedOrderlineId="_selectedOrderlineId"
|
||||
highlightHeaderNote="_state.ui.highlightHeaderNote" />
|
||||
<div class="pads">
|
||||
<div class="control-buttons">
|
||||
<div class="pads border-top">
|
||||
<div class="control-buttons d-flex flex-wrap border-bottom overflow-hidden">
|
||||
<InvoiceButton
|
||||
onInvoiceOrder.bind="onInvoiceOrder"
|
||||
order="_selectedSyncedOrder" />
|
||||
<ReprintReceiptButton order="_selectedSyncedOrder" />
|
||||
</div>
|
||||
<div class="subpads">
|
||||
<div class="subpads d-flex">
|
||||
<ActionpadWidget
|
||||
partner="getSelectedPartner()"
|
||||
actionName="constructor.numpadActionName"
|
||||
|
||||
+18
-15
@@ -2,25 +2,28 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="point_of_sale.CashOpeningPopup" owl="1">
|
||||
<div class="popup opening-cash-control">
|
||||
<header class="title drag-handle">
|
||||
OPENING CASH CONTROL
|
||||
</header>
|
||||
<main class="body">
|
||||
<div class="opening-cash-section">
|
||||
<span class="info-title">Opening cash</span>
|
||||
<div class="cash-input-sub-section" t-on-input="handleInputChange">
|
||||
<input class="pos-input" t-ref="cash-input" t-on-focus="ev=>ev.target.select()"/>
|
||||
<div class="button icon" t-on-click="openDetailsPopup">
|
||||
<i class="fa fa-money" role="img" title="Open the money details popup"/>
|
||||
<div class="modal-header drag-handle">
|
||||
<h4 class="modal-title">Opening Cash Control</h4>
|
||||
</div>
|
||||
<main class="modal-body">
|
||||
<div class="opening-cash-section mb-3">
|
||||
<span class="info-title d-flex flex-grow-1 align-items-start">Opening cash</span>
|
||||
<div class="cash-input-sub-section input-group" t-on-input="handleInputChange">
|
||||
<input class="pos-input form-control" type="number" t-model.number="state.openingCash" t-ref="cash-input" t-on-focus="ev=>ev.target.select()"/>
|
||||
<div class="button icon btn btn-secondary" t-on-click="openDetailsPopup">
|
||||
<i class="fa fa-money fa-2x" role="img" title="Open the money details popup"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<textarea placeholder="Add an opening note..." class="opening-cash-notes" t-model="state.notes"/>
|
||||
</main>
|
||||
<footer class="footer">
|
||||
<div class="button dynamic-size" t-on-click="confirm">
|
||||
Open session <span t-esc="env.utils.formatCurrency(state.openingCash)"/>
|
||||
<div class="opening-notes-container d-flex flex-column align-items-start">
|
||||
<label class="form-label" for="openingNotes">Opening note</label>
|
||||
<textarea class="opening-notes form-control" id="openingNotes" rows="4" t-model="state.notes" placeholder="Add an opening note...">
|
||||
<t t-esc="openingNotes"/>
|
||||
</textarea>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="footer modal-footer">
|
||||
<div class="button btn btn-lg btn-primary" t-on-click="confirm">Open session <span t-esc="env.utils.formatCurrency(state.openingCash)"/></div>
|
||||
</footer>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -70,7 +70,6 @@ const getProductImage = memoize(function getProductImage(productId, writeDate) {
|
||||
});
|
||||
|
||||
export class PosStore extends Reactive {
|
||||
hasBigScrollBars = false;
|
||||
loadingSkipButtonIsShown = false;
|
||||
mainScreen = { name: null, component: null };
|
||||
tempScreen = null;
|
||||
@@ -205,7 +204,6 @@ export class PosStore extends Reactive {
|
||||
);
|
||||
const { start_category, iface_start_categ_id } = this.config;
|
||||
this.selectedCategoryId = (start_category && iface_start_categ_id?.[0]) || 0;
|
||||
this.hasBigScrollBars = this.config.iface_big_scrollbars;
|
||||
// Push orders in background, do not await
|
||||
this.push_orders();
|
||||
this.markReady();
|
||||
|
||||
+50
-52
@@ -3,21 +3,22 @@
|
||||
|
||||
<t t-name="point_of_sale.RadioProductAttribute" owl="1">
|
||||
<div class="configurator_radio" t-ref="root">
|
||||
<div class="table">
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<t t-foreach="values" t-as="value" t-key="value.id">
|
||||
<div class="attribute-name-cell">
|
||||
<input type="radio" t-model="state.selected_value" t-att-name="attribute.id"
|
||||
<div class="attribute-name-cell form-check">
|
||||
<input class="form-check-input" type="radio" t-model="state.selected_value" t-att-name="attribute.id"
|
||||
t-attf-id="{{ attribute.id }}_{{ value.id }}" t-att-value="value.id"/>
|
||||
<span t-esc="value.name"/>
|
||||
<label t-att-name="value.name" t-attf-for="{{ attribute.id }}_{{ value.id }}"/>
|
||||
</div>
|
||||
<div t-if="value.price_extra" class="price-extra-cell">
|
||||
<span class="price_extra">
|
||||
+ <t t-esc="env.utils.formatCurrency(value.price_extra)"/>
|
||||
</span>
|
||||
<label class="form-check-label" t-att-name="value.name" t-attf-for="{{ attribute.id }}_{{ value.id }}">
|
||||
<span t-esc="value.name"/>
|
||||
</label>
|
||||
<div t-if="value.price_extra" class="price-extra-cell d-inline-block ms-3">
|
||||
<span class="price_extra px-2 py-1 rounded-pill text-bg-info">
|
||||
+ <t t-esc="env.utils.formatCurrency(value.price_extra)"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="value.id == state.selected_value && value.is_custom" class="custom-value-cell">
|
||||
<input class="custom_value" type="text" t-model="state.custom_value"/>
|
||||
<input class="custom_value form-control form-control-lg mt-2" type="text" t-model="state.custom_value"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
@@ -28,7 +29,7 @@
|
||||
<div>
|
||||
<t t-set="is_custom" t-value="false"/>
|
||||
|
||||
<select class="configurator_select" t-model="state.selected_value">
|
||||
<select class="configurator_select form-select form-select-lg" t-model="state.selected_value">
|
||||
<option t-foreach="values" t-as="value" t-key="value.id" t-att-value="value.id">
|
||||
<t t-set="is_custom" t-value="is_custom || (value.is_custom && value.id == state.selected_value)"/>
|
||||
<t t-esc="value.name"/>
|
||||
@@ -38,7 +39,7 @@
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<input class="custom_value" t-if="is_custom" type="text" t-model="state.custom_value"/>
|
||||
<input class="custom_value form-control form-control-lg mt-2" t-if="is_custom" type="text" t-model="state.custom_value"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -46,82 +47,79 @@
|
||||
<div>
|
||||
<t t-set="is_custom" t-value="false"/>
|
||||
|
||||
<ul class="color_attribute_list">
|
||||
<ul class="color_attribute_list d-flex gap-3">
|
||||
<li t-foreach="values" t-as="value" t-key="value.id" class="color_attribute_list_item">
|
||||
<t t-set="is_custom" t-value="is_custom || (value.is_custom && value.id == state.selected_value)"/>
|
||||
<label t-attf-class="configurator_color {{ value.id == state.selected_value ? 'active' : '' }}"
|
||||
<label t-attf-class="configurator_color rounded border {{ value.id == state.selected_value ? 'active border-3 border-primary' : 'border-3 border-secondary' }}"
|
||||
t-attf-style="background-color: {{ value.html_color }};" t-att-data-color="value.name">
|
||||
<input type="radio" t-model="state.selected_value" t-att-value="value.id" t-att-name="attribute.id"/>
|
||||
<input class="m-4 opacity-0" type="radio" t-model="state.selected_value" t-att-value="value.id" t-att-name="attribute.id"/>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<input class="custom_value" t-if="is_custom" type="text" t-model="state.custom_value"/>
|
||||
<input class="custom_value form-control form-control-lg mt-2" t-if="is_custom" type="text" t-model="state.custom_value"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="point_of_sale.ProductConfiguratorPopup" owl="1">
|
||||
<t t-if="!ui.isSmall">
|
||||
<div class="popup popup-text popup-med product-configurator-popup">
|
||||
<header class="title">
|
||||
<t t-esc="props.product.display_name" />
|
||||
</header>
|
||||
<div class="modal-header drag-handle">
|
||||
<h4 class="modal-title"><t t-esc="props.product.display_name" /></h4>
|
||||
</div>
|
||||
|
||||
<main class="body product_configurator_attributes col-lg-4 col-md-6 col-sm-12">
|
||||
<div t-foreach="props.attributes" t-as="attribute" t-key="attribute.id" class="attribute">
|
||||
<div class="attribute_name" t-esc="attribute.name"/>
|
||||
<main class="body modal-body product_configurator_attributes m-0 text-start">
|
||||
<div t-foreach="props.attributes" t-as="attribute" t-key="attribute.id" class="attribute mb-3">
|
||||
<div class="attribute_name mb-2 fw-bolder" t-esc="attribute.name"/>
|
||||
<RadioProductAttribute t-if="attribute.display_type === 'radio' or attribute.display_type === 'pills'" attribute="attribute"/>
|
||||
<SelectProductAttribute t-elif="attribute.display_type === 'select'" attribute="attribute"/>
|
||||
<ColorProductAttribute t-elif="attribute.display_type === 'color'" attribute="attribute"/>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="footer footer-flex">
|
||||
<div class="button highlight confirm" t-on-click="confirm">
|
||||
Add
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<footer class="footer footer-flex modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-secondary" t-on-click="cancel">
|
||||
Cancel
|
||||
</div>
|
||||
<div class="button highlight confirm btn btn-lg btn-primary" t-on-click="confirm">
|
||||
Add
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="popup mobile popup-text popup-med product-configurator-popup">
|
||||
<main class="body mobile product_configurator_attributes col-lg-4 col-md-6 col-sm-12">
|
||||
<div class="product-img">
|
||||
<img t-att-src="imageUrl" t-att-alt="props.product.display_name" />
|
||||
<div class="product-info">
|
||||
<span><t t-esc="props.product.display_name" ></t></span>
|
||||
<span><t t-esc="unitPrice" ></t></span>
|
||||
</div>
|
||||
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"><t t-esc="props.product.display_name" /></h4>
|
||||
<span><t t-esc="unitPrice" ></t></span>
|
||||
</div>
|
||||
<main class="body modal-body mobile product_configurator_attributes d-flex flex-column text-start">
|
||||
<div class="product-img d-flex justify-content-center h-50 p-2" >
|
||||
<img class="h-100" t-att-src="imageUrl" t-att-alt="props.product.display_name" />
|
||||
</div>
|
||||
<div t-foreach="props.attributes" t-as="attribute" t-key="attribute.id" class="attribute">
|
||||
<div class="attribute_name" t-esc="attribute.name"/>
|
||||
<div t-foreach="props.attributes" t-as="attribute" t-key="attribute.id" class="attribute mb-3">
|
||||
<div class="attribute_name mb-2 fw-bolder" t-esc="attribute.name"/>
|
||||
<RadioProductAttribute t-if="attribute.display_type === 'radio' or attribute.display_type === 'pills'" attribute="attribute"/>
|
||||
<SelectProductAttribute t-elif="attribute.display_type === 'select'" attribute="attribute"/>
|
||||
<ColorProductAttribute t-elif="attribute.display_type === 'color'" attribute="attribute"/>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="footer footer-flex mobile">
|
||||
<div class="quantity-selector">
|
||||
<button t-on-click="addOneQuantity">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||
</button>
|
||||
<span class="quantity"><t t-esc="state.quantity"></t></span>
|
||||
<button t-on-click="removeOneQuantity">
|
||||
<footer class="footer footer-flex mobile modal-footer">
|
||||
<div class="quantity-selector d-flex align-items-center justify-content-center w-100 py-2 fw-bolder">
|
||||
<button class="btn btn-lg btn-secondary" t-on-click="removeOneQuantity">
|
||||
<i class="fa fa-minus" aria-hidden="true"></i>
|
||||
</button>
|
||||
<span class="quantity mx-3"><t t-esc="state.quantity"></t></span>
|
||||
<button class="btn btn-lg btn-secondary" t-on-click="addOneQuantity">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="confirm-line">
|
||||
<div class="button highlight confirm" t-on-click="confirm">
|
||||
Add
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
Cancel
|
||||
</div>
|
||||
<div class="button highlight confirm btn btn-lg btn-primary" t-on-click="confirm">
|
||||
Add
|
||||
</div>
|
||||
<div class="button cancel btn btn-lg btn-secondary" t-on-click="cancel">
|
||||
Cancel
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
+4
-6
@@ -2,12 +2,10 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.EditListInput" owl="1">
|
||||
<div>
|
||||
<input type="text" t-att-value="props.item.text" t-on-input="onInput" class="popup-input list-line-input"
|
||||
placeholder="Serial/Lot Number" t-on-keyup="onKeyup" />
|
||||
<i t-if="props.deletable" class="oe_link_icon fa fa-trash-o" role="img" aria-label="Remove" title="Remove"
|
||||
t-on-click="props.removeItem"></i>
|
||||
</div>
|
||||
<input type="text" t-att-value="props.item.text" t-on-input="onInput" class="popup-input list-line-input form-control form-control-lg w-75 mx-auto"
|
||||
placeholder="Serial/Lot Number" t-on-keyup="onKeyup" />
|
||||
<i t-if="props.deletable" class="oe_link_icon fa fa-trash-o" role="img" aria-label="Remove" title="Remove"
|
||||
t-on-click="props.removeItem"></i>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -3,25 +3,25 @@
|
||||
|
||||
<t t-name="point_of_sale.EditListPopup" owl="1">
|
||||
<div class="popup popup-text edit-list-popup" t-ref="root">
|
||||
<header class="title">
|
||||
<t t-esc="props.title" />
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title title">
|
||||
<t t-esc="props.title" />
|
||||
</h4>
|
||||
<span class="sub-title" t-esc="props.name"/>
|
||||
</header>
|
||||
<main>
|
||||
<div class="list-lines">
|
||||
<t t-foreach="state.array" t-as="item" t-key="item._id">
|
||||
<EditListInput item="item" createNewItem.bind="createNewItem" removeItem="() => this.removeItem(item._id)"
|
||||
deletable="_hasMoreThanOneItem()" onInputChange.bind="onInputChange" />
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<main class="modal-body">
|
||||
<t t-foreach="state.array" t-as="item" t-key="item._id">
|
||||
<EditListInput item="item" createNewItem.bind="createNewItem" removeItem="() => this.removeItem(item._id)"
|
||||
deletable="_hasMoreThanOneItem()" onInputChange.bind="onInputChange" />
|
||||
</t>
|
||||
</main>
|
||||
<footer class="footer footer-flex">
|
||||
<div class="button confirm highlight" t-on-click="confirm">
|
||||
Ok
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<footer class="footer footer-flex modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-secondary" t-on-click="cancel">
|
||||
Cancel
|
||||
</div>
|
||||
<div class="button confirm highlight btn btn-lg btn-primary" t-on-click="confirm">
|
||||
Ok
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -3,17 +3,19 @@
|
||||
|
||||
<t t-name="point_of_sale.ConfirmPopup" owl="1">
|
||||
<div class="popup popup-confirm">
|
||||
<header class="title drag-handle">
|
||||
<t t-esc="props.title" />
|
||||
</header>
|
||||
<main class="body">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title title drag-handle">
|
||||
<t t-esc="props.title" />
|
||||
</h4>
|
||||
</div>
|
||||
<main class="modal-body">
|
||||
<t t-esc=" props.body" />
|
||||
</main>
|
||||
<footer class="footer">
|
||||
<div class="button confirm" t-on-click="confirm">
|
||||
<footer class="footer modal-footer">
|
||||
<div class="button confirm btn btn-lg btn-primary" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<div class="button cancel btn btn-lg btn-secondary" t-on-click="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -3,19 +3,21 @@
|
||||
|
||||
<t t-name="point_of_sale.DatePickerPopup" owl="1">
|
||||
<div class="popup">
|
||||
<header class="title">
|
||||
<t t-esc="props.title" />
|
||||
</header>
|
||||
<main>
|
||||
<input type="date" t-model="state.shippingDate" t-ref="input" t-att-min="_today()"/>
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title title">
|
||||
<t t-esc="props.title" />
|
||||
</h4>
|
||||
</div>
|
||||
<main class="modal-body">
|
||||
<input class="form-control form-control-lg w-75 mx-auto" type="date" t-model="state.shippingDate" t-ref="input" t-att-min="_today()"/>
|
||||
</main>
|
||||
<div class="footer footer-flex">
|
||||
<div class="button confirm highlight" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<div class="footer footer-flex modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-secondary" t-on-click="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
<div class="button confirm highlight btn btn-lg btn-primary" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.popup-numpad .input-button,
|
||||
.popup-numpad .mode-button {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
@@ -2,67 +2,65 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.NumberPopup" owl="1">
|
||||
<div class="popup popup-number" t-att-class="{ 'popup-password': props.isPassword }" t-if="!isMobile()">
|
||||
<header class="title drag-handle">
|
||||
<span><t t-esc="props.title"/></span>
|
||||
<span t-if="props.subtitle" class="subtitle"><t t-esc="props.subtitle"/></span>
|
||||
</header>
|
||||
<div class="input-symbol">
|
||||
<div class="popup-input value active">
|
||||
<div class="popup popup-number w-auto" t-att-class="{ 'popup-password': props.isPassword }" t-if="!isMobile()">
|
||||
<div class="modal-header drag-handle">
|
||||
<h4 class="modal-title title"><t t-esc="props.title" /></h4>
|
||||
<span t-if="props.subtitle" class="subtitle p-1"><t t-esc="props.subtitle"/></span>
|
||||
</div>
|
||||
<div class="input-symbol pt-3">
|
||||
<div class="popup-input value active form-control form-control-lg w-75 mx-auto">
|
||||
<span class="input-value" t-att-class="{ 'highlight': state.toStartOver }"><t t-esc="inputBuffer"/></span>
|
||||
<span t-if="props.inputSuffix"><t t-esc="props.inputSuffix" /></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popup-numpad">
|
||||
<div class="popup-numpad px-5 my-3">
|
||||
<!-- FIXME POSREF do we really need to hardcode all of these? -->
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('1')">1</button>
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('2')">2</button>
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('3')">3</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('1')">1</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('2')">2</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('3')">3</button>
|
||||
<t t-if="props.cheap">
|
||||
<button class="mode-button add" t-on-mousedown.prevent="() => this.sendInput('+1')">+1</button>
|
||||
<button class="mode-button add btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('+1')">+1</button>
|
||||
</t>
|
||||
<t t-if="!props.cheap">
|
||||
<button class="mode-button add" t-on-mousedown.prevent="() => this.sendInput('+10')">+10</button>
|
||||
<button class="mode-button add btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('+10')">+10</button>
|
||||
</t>
|
||||
<br />
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('4')">4</button>
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('5')">5</button>
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('6')">6</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('4')">4</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('5')">5</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('6')">6</button>
|
||||
<t t-if="props.cheap">
|
||||
<button class="mode-button add" t-on-mousedown.prevent="() => this.sendInput('+2')">+2</button>
|
||||
<button class="mode-button add btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('+2')">+2</button>
|
||||
</t>
|
||||
<t t-if="!props.cheap">
|
||||
<button class="mode-button add" t-on-mousedown.prevent="() => this.sendInput('+20')">+20</button>
|
||||
<button class="mode-button add btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('+20')">+20</button>
|
||||
</t>
|
||||
<br />
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('7')">7</button>
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('8')">8</button>
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('9')">9</button>
|
||||
<button t-if="!props.isPassword" class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('-')">-</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('7')">7</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('8')">8</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('9')">9</button>
|
||||
<button t-if="!props.isPassword" class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('-')">-</button>
|
||||
<br />
|
||||
<button class="input-button numpad-char" t-on-mousedown.prevent="() => this.sendInput('Delete')">C</button>
|
||||
<button class="input-button number-char" t-on-mousedown.prevent="() => this.sendInput('0')">0</button>
|
||||
<button class="input-button number-char dot" t-on-mousedown.prevent="() => this.sendInput(decimalSeparator)">
|
||||
<button class="input-button numpad-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('Delete')">C</button>
|
||||
<button class="input-button number-char btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('0')">0</button>
|
||||
<button class="input-button number-char dot btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput(decimalSeparator)">
|
||||
<t t-esc="decimalSeparator" /></button>
|
||||
<button class="input-button numpad-backspace" t-on-mousedown.prevent="() => this.sendInput('Backspace')">
|
||||
<button class="input-button numpad-backspace btn btn-secondary p-0 rounded-circle m-1" t-on-mousedown.prevent="() => this.sendInput('Backspace')">
|
||||
<img style="pointer-events: none;"
|
||||
src="/point_of_sale/static/src/img/backspace.png" width="24"
|
||||
height="21" alt="Backspace" />
|
||||
</button>
|
||||
<br />
|
||||
</div>
|
||||
<footer class="footer centered">
|
||||
<div class="button confirm highlight" t-on-mousedown.prevent="confirm">
|
||||
<div class="flex-column">
|
||||
<footer class="footer centered modal-footer">
|
||||
<button class="button confirm highlight btn btn-lg btn-primary" t-on-mousedown.prevent="confirm">
|
||||
<span><t t-esc="props.confirmText" /></span>
|
||||
<span t-if="props.getInputBufferReminder(state.buffer)" class="input-buffer-reminder">
|
||||
<span t-if="props.getInputBufferReminder(state.buffer)" class="input-buffer-reminder small">
|
||||
(<t t-esc="props.getInputBufferReminder(state.buffer)" />)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button cancel" t-on-mousedown.prevent="cancel">
|
||||
</button>
|
||||
<button class="button cancel btn btn-lg btn-secondary" t-on-mousedown.prevent="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="popup" t-att-class="{ 'popup-password': props.isPassword }" t-else="">
|
||||
@@ -72,13 +70,13 @@
|
||||
<main>
|
||||
<input type="text" t-model="state.payload" t-ref="input" class="value payment-input-number" inputmode="decimal">
|
||||
</main>
|
||||
<footer class="footer centered">
|
||||
<div class="button confirm highlight" t-on-mousedown.prevent="confirm">
|
||||
<footer class="footer centered modal-footer">
|
||||
<button class="button confirm highlight btn btn-lg btn-primary" t-on-mousedown.prevent="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
<div class="button cancel" t-on-mousedown.prevent="cancel">
|
||||
</button>
|
||||
<button class="button cancel btn btn-lg btn-secondary" t-on-mousedown.prevent="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.popup-selection .selection {
|
||||
max-height: 300px;
|
||||
}
|
||||
@@ -3,20 +3,23 @@
|
||||
|
||||
<t t-name="point_of_sale.SelectionPopup" owl="1">
|
||||
<div class="popup popup-selection">
|
||||
<header class="title drag-handle">
|
||||
<t t-esc="props.title" />
|
||||
</header>
|
||||
<div class="selection scrollable-y">
|
||||
<div class="modal-header drag-handle">
|
||||
<h4 class="modal-title"><t t-esc="props.title" /></h4>
|
||||
</div>
|
||||
<div class="selection btn-group-vertical justify-content-start w-100 p-3 overflow-y-auto">
|
||||
<t t-foreach="props.list" t-as="item" t-key="item.id">
|
||||
<div class="selection-item" t-att-class="{ selected: item.isSelected }"
|
||||
<button type="button" class="selection-item d-flex align-items-center justify-content-between btn btn-lg btn-outline-secondary w-100 p-3 text-start" t-att-class="{ 'selected text-bg-primary': item.isSelected }"
|
||||
t-on-click="() => this.selectItem(item.id)">
|
||||
<span t-esc="item.label" />
|
||||
<span t-esc="item.description" t-if="item.description" />
|
||||
</div>
|
||||
<div class="d-flex flex-column">
|
||||
<span t-esc="item.label" />
|
||||
<span t-esc="item.description" t-if="item.description" />
|
||||
</div>
|
||||
<i class="oi oi-chevron-right"/>
|
||||
</button>
|
||||
</t>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<footer class="footer modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-primary" t-on-click="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -3,20 +3,19 @@
|
||||
|
||||
<t t-name="point_of_sale.TextInputPopup" owl="1">
|
||||
<div class="popup popup-textinput">
|
||||
<header class="title">
|
||||
<t t-esc="props.title" />
|
||||
</header>
|
||||
<main>
|
||||
<p t-esc="props.body" />
|
||||
<input type="text" t-model="state.inputValue" t-ref="input" t-att-placeholder="props.placeholder"/>
|
||||
</main>
|
||||
<div class="footer footer-flex">
|
||||
<div class="button confirm highlight" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"><t t-esc="props.title" /></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input class="form-control form-control-lg w-75 mx-auto" type="text" t-model="state.inputValue" t-ref="input" t-att-placeholder="props.placeholder"/>
|
||||
</div>
|
||||
<div class="footer footer-flex modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-secondary" t-on-click="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
<div class="button confirm highlight btn btn-lg btn-primary" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -3,17 +3,22 @@
|
||||
|
||||
<t t-name="point_of_sale.TextAreaPopup" owl="1">
|
||||
<div class="popup popup-textarea">
|
||||
<header class="title drag-handle">
|
||||
<t t-esc="props.title" />
|
||||
</header>
|
||||
<textarea t-model="state.inputValue" t-ref="input"></textarea>
|
||||
<footer class="footer footer-flex">
|
||||
<div class="button confirm highlight" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"><t t-esc="props.title" /></h4>
|
||||
<!-- when modal fixed <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>-->
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<textarea class="form-control" t-ref="input" placeholder="Add a note..." t-model="state.inputValue" rows="4" />
|
||||
</div>
|
||||
|
||||
<footer class="footer footer-flex modal-footer">
|
||||
<div class="button cancel btn btn-lg btn-secondary" t-on-click="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
<div class="button confirm highlight btn btn-lg btn-primary" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.money-details-value label {
|
||||
width: 50px;
|
||||
}
|
||||
+15
-15
@@ -2,16 +2,16 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="point_of_sale.MoneyDetailsPopup" owl="1">
|
||||
<div class="popup money-details">
|
||||
<main class="body">
|
||||
<div class="money-details-title">
|
||||
Coins/Bills
|
||||
</div>
|
||||
<div class="money-details-info">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Coins/Bills</h4>
|
||||
</div>
|
||||
<main class="modal-body">
|
||||
<div class="money-details-info d-flex justify-content-between mb-2 oveflow-auto">
|
||||
<div t-foreach="[firstHalfMoneyDetails, lastHalfMoneyDetails]" t-as="moneyDetailsList" t-key="moneyDetailsList_index">
|
||||
<t t-foreach="moneyDetailsList" t-as="moneyValue" t-key="moneyValue">
|
||||
<div class="money-details-value" t-on-input="updateMoneyDetailsAmount">
|
||||
<input class="pos-input" t-att-id="moneyValue" type="number" t-model.number="state.moneyDetails[moneyValue]" t-on-focus="ev=>ev.target.select()"/>
|
||||
<label class="oe_link_icon" t-att-for="moneyValue">
|
||||
<div class="money-details-value d-flex align-items-center w-100 my-1" t-on-input="updateMoneyDetailsAmount">
|
||||
<input class="pos-input form-control w-75" t-att-id="moneyValue" type="number" t-model.number="state.moneyDetails[moneyValue]" t-on-focus="ev=>ev.target.select()"/>
|
||||
<label class="oe_link_icon w-25 text-end" t-att-for="moneyValue">
|
||||
<t t-if="currency.position === 'before'"><t t-esc="currency.symbol"/> </t>
|
||||
<t t-esc="moneyValue"/>
|
||||
<t t-if="currency.position === 'after'"> <t t-esc="currency.symbol"/></t>
|
||||
@@ -20,14 +20,14 @@
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="total-section">
|
||||
<span>Total </span>
|
||||
<label t-esc="env.utils.formatCurrency(state.total)"/>
|
||||
</div>
|
||||
<h4 class="total-section rounded py-2">
|
||||
Total
|
||||
<t t-esc="env.utils.formatCurrency(state.total)"/>
|
||||
</h4>
|
||||
</main>
|
||||
<footer class="footer footer-flex">
|
||||
<div class="button highlight" t-on-click="confirm">Confirm</div>
|
||||
<div class="button" t-on-click="cancel">Discard</div>
|
||||
<footer class="footer footer-flex modal-footer">
|
||||
<div class="button btn btn-lg btn-secondary" t-on-click="cancel">Discard</div>
|
||||
<div class="button highlight btn btn-lg btn-primary" t-on-click="confirm">Confirm</div>
|
||||
</footer>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user