2022-07-21 13:47:31 +02:00
|
|
|
document.addEventListener("DOMContentLoaded",function () {
|
2023-02-10 16:26:38 +01:00
|
|
|
const displayFontSize = 64;
|
|
|
|
new Vue({
|
2020-09-21 14:06:31 +08:00
|
|
|
el: '#app',
|
2023-02-10 16:26:38 +01:00
|
|
|
data () {
|
2020-09-21 14:06:31 +08:00
|
|
|
return {
|
|
|
|
srvModel: window.srvModel,
|
2023-02-10 16:26:38 +01:00
|
|
|
mode: 'amount',
|
|
|
|
amount: null,
|
|
|
|
tip: null,
|
|
|
|
tipPercent: null,
|
|
|
|
discount: null,
|
2022-07-20 22:29:31 -07:00
|
|
|
discountPercent: null,
|
2020-09-21 14:06:31 +08:00
|
|
|
fontSize: displayFontSize,
|
|
|
|
defaultFontSize: displayFontSize,
|
2023-02-10 16:26:38 +01:00
|
|
|
keys: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '0', 'del'],
|
|
|
|
payButtonLoading: false
|
2020-09-21 14:06:31 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
computed: {
|
2023-02-10 16:26:38 +01:00
|
|
|
modes () {
|
|
|
|
const modes = [{ title: 'Amount', type: 'amount' }]
|
|
|
|
if (this.srvModel.showDiscount) modes.push({ title: 'Discount', type: 'discount' })
|
|
|
|
if (this.srvModel.enableTips) modes.push({ title: 'Tip', type: 'tip'})
|
|
|
|
return modes
|
|
|
|
},
|
|
|
|
keypadTarget () {
|
|
|
|
switch (this.mode) {
|
|
|
|
case 'amount':
|
|
|
|
return 'amount';
|
|
|
|
case 'discount':
|
|
|
|
return 'discountPercent';
|
|
|
|
case 'tip':
|
|
|
|
return 'tip';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
calculation () {
|
|
|
|
if (!this.tipNumeric && !this.discountNumeric) return null
|
|
|
|
let calc = this.formatCurrency(this.amountNumeric, true)
|
|
|
|
if (this.discountNumeric > 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
|
2020-09-21 14:06:31 +08:00
|
|
|
},
|
2023-02-10 16:26:38 +01:00
|
|
|
amountNumeric () {
|
|
|
|
const value = parseFloat(this.amount)
|
|
|
|
return isNaN(value) ? 0.0 : value
|
|
|
|
},
|
|
|
|
discountPercentNumeric () {
|
|
|
|
const value = parseFloat(this.discountPercent)
|
|
|
|
return isNaN(value) ? 0.0 : value;
|
|
|
|
},
|
|
|
|
discountNumeric () {
|
|
|
|
return this.amountNumeric && this.discountPercentNumeric
|
|
|
|
? this.amountNumeric * (this.discountPercentNumeric / 100)
|
|
|
|
: 0.0;
|
|
|
|
},
|
|
|
|
amountMinusDiscountNumeric () {
|
|
|
|
return this.amountNumeric - this.discountNumeric;
|
|
|
|
},
|
|
|
|
tipNumeric () {
|
|
|
|
if (this.tipPercent) {
|
|
|
|
return this.amountMinusDiscountNumeric * (this.tipPercent / 100);
|
|
|
|
} else {
|
|
|
|
const value = parseFloat(this.tip)
|
|
|
|
return isNaN(value) ? 0.0 : value;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
total () {
|
|
|
|
return (this.amountNumeric - this.discountNumeric + this.tipNumeric);
|
|
|
|
},
|
|
|
|
totalNumeric () {
|
|
|
|
return parseFloat(this.total);
|
|
|
|
}
|
2020-09-21 14:06:31 +08:00
|
|
|
},
|
|
|
|
watch: {
|
2023-02-10 16:26:38 +01:00
|
|
|
discountPercent (val) {
|
|
|
|
const value = parseFloat(val)
|
|
|
|
if (isNaN(value)) this.discountPercent = null
|
|
|
|
else if (value > 100) this.discountPercent = '100'
|
|
|
|
else this.discountPercent = value.toString();
|
|
|
|
},
|
|
|
|
tip (val) {
|
|
|
|
this.tipPercent = null;
|
|
|
|
},
|
|
|
|
total () {
|
|
|
|
// This must be timed out because the updated width is not available yet
|
|
|
|
this.$nextTick(function () {
|
2022-07-21 13:47:31 +02:00
|
|
|
const displayWidth = this.getWidth(this.$refs.display),
|
2020-09-21 14:06:31 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
2023-02-10 16:26:38 +01:00
|
|
|
getWidth (el) {
|
2022-07-21 13:47:31 +02:00
|
|
|
const styles = window.getComputedStyle(el),
|
2020-09-21 14:06:31 +08:00
|
|
|
width = parseFloat(el.clientWidth),
|
|
|
|
padL = parseFloat(styles.paddingLeft),
|
|
|
|
padR = parseFloat(styles.paddingRight);
|
|
|
|
return width - padL - padR;
|
|
|
|
},
|
2023-02-10 16:26:38 +01:00
|
|
|
clear () {
|
|
|
|
this.amount = this.tip = this.discount = this.tipPercent = this.discountPercent = null;
|
|
|
|
this.mode = 'amount';
|
2020-09-21 14:06:31 +08:00
|
|
|
},
|
2023-02-10 16:26:38 +01:00
|
|
|
handleFormSubmit () {
|
2022-01-26 17:58:25 -08:00
|
|
|
this.payButtonLoading = true;
|
|
|
|
},
|
2023-02-10 16:26:38 +01:00
|
|
|
unsetPayButtonLoading () {
|
2022-01-26 17:58:25 -08:00
|
|
|
this.payButtonLoading = false;
|
|
|
|
},
|
2023-02-10 16:26:38 +01:00
|
|
|
formatCrypto (value, withSymbol) {
|
|
|
|
const symbol = withSymbol ? ` ${this.srvModel.currencySymbol || this.srvModel.currencyCode}` : '';
|
|
|
|
const divisibility = this.srvModel.currencyInfo.divisibility;
|
|
|
|
return parseFloat(value).toFixed(divisibility) + symbol;
|
|
|
|
},
|
|
|
|
formatCurrency (value, withSymbol) {
|
|
|
|
const currency = this.srvModel.currencyCode;
|
|
|
|
if (currency === 'BTC' || currency === 'SATS') return this.formatCrypto(value, withSymbol);
|
|
|
|
const divisibility = this.srvModel.currencyInfo.divisibility;
|
|
|
|
const locale = currency === 'USD' ? 'en-US' : navigator.language;
|
|
|
|
const style = withSymbol ? 'currency' : 'decimal';
|
|
|
|
const opts = { currency, style, maximumFractionDigits: divisibility, minimumFractionDigits: divisibility };
|
|
|
|
try {
|
|
|
|
return new Intl.NumberFormat(locale, opts).format(value);
|
|
|
|
} catch (err) {
|
|
|
|
return this.formatCrypto(value, withSymbol);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
applyKeyToValue (key, value) {
|
|
|
|
if (!value) value = '';
|
|
|
|
if (key === 'del') {
|
|
|
|
value = value.substring(0, value.length - 1);
|
|
|
|
value = value === '' ? '0' : value;
|
2020-09-21 14:06:31 +08:00
|
|
|
} else if (key === '.') {
|
|
|
|
// Only add decimal point if it doesn't exist yet
|
2023-02-10 16:26:38 +01:00
|
|
|
if (value.indexOf('.') === -1) {
|
|
|
|
value += key;
|
2020-09-21 14:06:31 +08:00
|
|
|
}
|
|
|
|
} else { // Is a digit
|
2023-02-10 16:26:38 +01:00
|
|
|
if (!value || value === '0') {
|
|
|
|
value = '';
|
2020-09-21 14:06:31 +08:00
|
|
|
}
|
2023-02-10 16:26:38 +01:00
|
|
|
value += key;
|
2022-07-21 13:47:31 +02:00
|
|
|
const { divisibility } = this.srvModel.currencyInfo;
|
2023-02-10 16:26:38 +01:00
|
|
|
const decimalIndex = value.indexOf('.')
|
|
|
|
if (decimalIndex !== -1 && (value.length - decimalIndex - 1 > divisibility)) {
|
|
|
|
value = value.replace('.', '');
|
|
|
|
value = value.substr(0, value.length - divisibility) + '.' +
|
|
|
|
value.substr(value.length - divisibility);
|
2020-09-21 14:06:31 +08:00
|
|
|
}
|
|
|
|
}
|
2023-02-10 16:26:38 +01:00
|
|
|
return value;
|
2022-07-20 22:29:31 -07:00
|
|
|
},
|
2023-02-10 16:26:38 +01:00
|
|
|
keyPressed (key) {
|
|
|
|
this[this.keypadTarget] = this.applyKeyToValue(key, this[this.keypadTarget]);
|
2022-07-20 22:29:31 -07:00
|
|
|
},
|
2023-02-10 16:26:38 +01:00
|
|
|
tipPercentage (percentage) {
|
|
|
|
this.tipPercent = this.tipPercent !== percentage
|
|
|
|
? percentage
|
|
|
|
: null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
created () {
|
|
|
|
/** We need to unset state in case user clicks the browser back button */
|
|
|
|
window.addEventListener('pagehide', this.unsetPayButtonLoading);
|
|
|
|
},
|
|
|
|
destroyed () {
|
|
|
|
window.removeEventListener('pagehide', this.unsetPayButtonLoading);
|
2020-09-21 14:06:31 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|