2023-07-22 14:15:41 +02:00
|
|
|
document.addEventListener("DOMContentLoaded",function () {
|
|
|
|
const displayFontSize = 64;
|
|
|
|
new Vue({
|
2023-11-21 10:13:26 +01:00
|
|
|
el: '#app',
|
2023-07-22 14:15:41 +02:00
|
|
|
mixins: [posCommon],
|
|
|
|
data () {
|
|
|
|
return {
|
2023-11-02 20:03:34 +01:00
|
|
|
mode: 'amounts',
|
2023-07-22 14:15:41 +02:00
|
|
|
fontSize: displayFontSize,
|
|
|
|
defaultFontSize: displayFontSize,
|
2023-11-02 20:03:34 +01:00
|
|
|
keys: ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'C', '0', '+'],
|
2023-11-30 10:19:03 +01:00
|
|
|
amounts: [null],
|
|
|
|
recentTransactions: [],
|
|
|
|
recentTransactionsLoading: false,
|
|
|
|
dateFormatter: new Intl.DateTimeFormat('default', { dateStyle: 'short', timeStyle: 'short' })
|
2023-07-22 14:15:41 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
modes () {
|
2023-11-02 20:03:34 +01:00
|
|
|
const modes = [{ title: 'Amount', type: 'amounts' }]
|
2023-07-22 14:15:41 +02:00
|
|
|
if (this.showDiscount) modes.push({ title: 'Discount', type: 'discount' })
|
|
|
|
if (this.enableTips) modes.push({ title: 'Tip', type: 'tip'})
|
|
|
|
return modes
|
|
|
|
},
|
|
|
|
keypadTarget () {
|
|
|
|
switch (this.mode) {
|
2023-11-02 20:03:34 +01:00
|
|
|
case 'amounts':
|
|
|
|
return 'amounts';
|
2023-07-22 14:15:41 +02:00
|
|
|
case 'discount':
|
|
|
|
return 'discountPercent';
|
|
|
|
case 'tip':
|
|
|
|
return 'tip';
|
|
|
|
}
|
2023-11-02 20:03:34 +01:00
|
|
|
},
|
|
|
|
calculation () {
|
|
|
|
if (!this.tipNumeric && !(this.discountNumeric > 0 || this.discountPercentNumeric > 0) && this.amounts.length < 2) return null
|
|
|
|
let calc = this.amounts.map(amt => this.formatCurrency(amt, true)).join(' + ')
|
|
|
|
if (this.discountNumeric > 0 || this.discountPercentNumeric > 0) calc += ` - ${this.formatCurrency(this.discountNumeric, true)} (${this.discountPercent}%)`
|
|
|
|
if (this.tipNumeric > 0) calc += ` + ${this.formatCurrency(this.tipNumeric, true)}`
|
|
|
|
if (this.tipPercent) calc += ` (${this.tipPercent}%)`
|
|
|
|
return calc
|
2023-07-22 14:15:41 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
total () {
|
|
|
|
// This must be timed out because the updated width is not available yet
|
|
|
|
this.$nextTick(function () {
|
|
|
|
const displayWidth = this.getWidth(this.$refs.display),
|
|
|
|
amountWidth = this.getWidth(this.$refs.amount),
|
|
|
|
gamma = displayWidth / amountWidth || 0,
|
|
|
|
isAmountWider = displayWidth < amountWidth;
|
|
|
|
|
|
|
|
if (isAmountWider) {
|
|
|
|
// Font size will get smaller
|
|
|
|
this.fontSize = Math.floor(this.fontSize * gamma);
|
|
|
|
} else if (!isAmountWider && this.fontSize < this.defaultFontSize) {
|
|
|
|
// Font size will get larger up to the max size
|
|
|
|
this.fontSize = Math.min(this.fontSize * gamma, this.defaultFontSize);
|
|
|
|
}
|
|
|
|
});
|
2023-11-02 20:03:34 +01:00
|
|
|
},
|
|
|
|
amounts (values) {
|
|
|
|
this.amount = values.reduce((total, current) => total + parseFloat(current || '0'), 0);
|
2023-07-22 14:15:41 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
2023-11-02 20:03:34 +01:00
|
|
|
getWidth(el) {
|
2023-07-22 14:15:41 +02:00
|
|
|
const styles = window.getComputedStyle(el),
|
|
|
|
width = parseFloat(el.clientWidth),
|
|
|
|
padL = parseFloat(styles.paddingLeft),
|
|
|
|
padR = parseFloat(styles.paddingRight);
|
|
|
|
return width - padL - padR;
|
|
|
|
},
|
2023-11-02 20:03:34 +01:00
|
|
|
clear() {
|
|
|
|
this.amounts = [null];
|
|
|
|
this.tip = this.discount = this.tipPercent = this.discountPercent = null;
|
|
|
|
this.mode = 'amounts';
|
2023-07-22 14:15:41 +02:00
|
|
|
},
|
2023-11-02 20:03:34 +01:00
|
|
|
applyKeyToValue(key, value, divisibility) {
|
|
|
|
if (!value || value === '0') value = '';
|
|
|
|
value = (value + key)
|
|
|
|
.replace('.', '')
|
|
|
|
.padStart(divisibility, '0')
|
|
|
|
.replace(new RegExp(`(\\d*)(\\d{${divisibility}})`), '$1.$2');
|
|
|
|
return parseFloat(value).toFixed(divisibility);
|
|
|
|
},
|
|
|
|
keyPressed (key) {
|
|
|
|
if (this.keypadTarget === 'amounts') {
|
|
|
|
const lastIndex = this.amounts.length - 1;
|
|
|
|
const lastAmount = this.amounts[lastIndex];
|
|
|
|
if (key === 'C') {
|
|
|
|
if (!lastAmount && lastIndex === 0) {
|
|
|
|
// clear completely
|
|
|
|
this.clear();
|
|
|
|
} else if (!lastAmount) {
|
|
|
|
// remove latest value
|
|
|
|
this.amounts.pop();
|
|
|
|
} else {
|
|
|
|
// clear latest value
|
|
|
|
Vue.set(this.amounts, lastIndex, null);
|
|
|
|
}
|
|
|
|
} else if (key === '+' && parseFloat(lastAmount || '0')) {
|
|
|
|
this.amounts.push(null);
|
|
|
|
} else { // Is a digit
|
|
|
|
const { divisibility } = this.currencyInfo;
|
|
|
|
const value = this.applyKeyToValue(key, lastAmount, divisibility);
|
|
|
|
Vue.set(this.amounts, lastIndex, value);
|
2023-07-22 14:15:41 +02:00
|
|
|
}
|
2023-11-02 20:03:34 +01:00
|
|
|
} else {
|
|
|
|
if (key === 'C') {
|
|
|
|
this[this.keypadTarget] = null;
|
|
|
|
} else {
|
|
|
|
const divisibility = this.keypadTarget === 'tip' ? this.currencyInfo.divisibility : 0;
|
|
|
|
this[this.keypadTarget] = this.applyKeyToValue(key, this[this.keypadTarget], divisibility);
|
2023-07-22 14:15:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2023-11-02 20:03:34 +01:00
|
|
|
doubleClick (key) {
|
|
|
|
if (key === 'C') {
|
|
|
|
// clear completely
|
|
|
|
this.clear();
|
|
|
|
}
|
2023-11-30 10:19:03 +01:00
|
|
|
},
|
|
|
|
closeModal() {
|
|
|
|
bootstrap.Modal.getInstance(this.$refs.RecentTransactions).hide();
|
|
|
|
},
|
|
|
|
displayDate(val) {
|
|
|
|
const date = new Date(val);
|
|
|
|
return this.dateFormatter.format(date);
|
|
|
|
},
|
|
|
|
async loadRecentTransactions() {
|
|
|
|
this.recentTransactionsLoading = true;
|
|
|
|
const { url } = this.$refs.RecentTransactions.dataset;
|
2023-12-04 14:14:37 +01:00
|
|
|
try {
|
|
|
|
const response = await fetch(url);
|
|
|
|
if (response.ok) {
|
|
|
|
this.recentTransactions = await response.json();
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
} finally {
|
|
|
|
this.recentTransactionsLoading = false;
|
2023-11-30 10:19:03 +01:00
|
|
|
}
|
2023-07-22 14:15:41 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
created() {
|
2023-11-30 10:19:03 +01:00
|
|
|
// We need to unset state in case user clicks the browser back button
|
|
|
|
window.addEventListener('pagehide', () => { this.payButtonLoading = false })
|
2023-07-22 14:15:41 +02:00
|
|
|
},
|
2023-11-30 10:19:03 +01:00
|
|
|
mounted() {
|
|
|
|
this.$refs.RecentTransactions.addEventListener('show.bs.modal', this.loadRecentTransactions);
|
|
|
|
}
|
2023-07-22 14:15:41 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|