Changeset View
Changeset View
Standalone View
Standalone View
src/resources/vue/Wallet.vue
Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | <div class="container" dusk="wallet-component"> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="wallet-payments" role="tabpanel" aria-labelledby="tab-payments"> | <div class="tab-pane" id="wallet-payments" role="tabpanel" aria-labelledby="tab-payments"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<payment-log v-if="walletId && loadPayments" class="card-text" :wallet-id="walletId"></payment-log> | <payment-log v-if="walletId && loadPayments" class="card-text" :wallet-id="walletId"></payment-log> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div id="payment-dialog" class="modal" tabindex="-1" role="dialog"> | <modal-dialog id="payment-dialog" ref="paymentDialog" :title="paymentDialogTitle" @click="payment" :buttons="dialogButtons"> | ||||
<div class="modal-dialog" role="document"> | |||||
<div class="modal-content"> | |||||
<div class="modal-header"> | |||||
<h5 class="modal-title">{{ paymentDialogTitle }}</h5> | |||||
<btn class="btn-close" data-bs-dismiss="modal" :aria-label="$t('btn.close')"></btn> | |||||
</div> | |||||
<div class="modal-body"> | |||||
<div id="payment-method" v-if="paymentForm == 'method'"> | <div id="payment-method" v-if="paymentForm == 'method'"> | ||||
<form data-validation-prefix="mandate_"> | <form data-validation-prefix="mandate_"> | ||||
<div id="payment-method-selection"> | <div id="payment-method-selection"> | ||||
<a v-for="method in paymentMethods" :key="method.id" @click="selectPaymentMethod(method)" href="#" :class="'card link-' + method.id"> | <a v-for="method in paymentMethods" :key="method.id" @click="selectPaymentMethod(method)" href="#" :class="'card link-' + method.id"> | ||||
<svg-icon v-if="method.icon" :icon="[method.icon.prefix, method.icon.name]" /> | <svg-icon v-if="method.icon" :icon="[method.icon.prefix, method.icon.name]" /> | ||||
<img v-if="method.image" :src="method.image" /> | <img v-if="method.image" :src="method.image" /> | ||||
<span class="name">{{ method.name }}</span> | <span class="name">{{ method.name }}</span> | ||||
</a> | </a> | ||||
</div> | </div> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
<div id="manual-payment" v-if="paymentForm == 'manual'"> | <div id="manual-payment" v-if="paymentForm == 'manual'"> | ||||
<p v-if="wallet.currency != selectedPaymentMethod.currency"> | <p v-if="wallet.currency != selectedPaymentMethod.currency"> | ||||
{{ $t('wallet.currency-conv', { wc: wallet.currency, pc: selectedPaymentMethod.currency }) }} | {{ $t('wallet.currency-conv', { wc: wallet.currency, pc: selectedPaymentMethod.currency }) }} | ||||
</p> | </p> | ||||
<p v-if="selectedPaymentMethod.id == 'banktransfer'"> | <p v-if="selectedPaymentMethod.id == 'banktransfer'"> | ||||
{{ $t('wallet.banktransfer-hint') }} | {{ $t('wallet.banktransfer-hint') }} | ||||
</p> | </p> | ||||
<p> | <p> | ||||
{{ $t('wallet.payment-amount-hint') }} | {{ $t('wallet.payment-amount-hint') }} | ||||
</p> | </p> | ||||
<form id="payment-form" @submit.prevent="payment"> | <form id="payment-form" @submit.prevent="payment"> | ||||
<div class="input-group"> | <div class="input-group"> | ||||
<input type="text" class="form-control" id="amount" v-model="amount" required> | <input type="text" class="form-control" id="amount" v-model="amount" required> | ||||
<span class="input-group-text">{{ wallet.currency }}</span> | <span class="input-group-text">{{ wallet.currency }}</span> | ||||
</div> | </div> | ||||
<div v-if="wallet.currency != selectedPaymentMethod.currency && !isNaN(amount)" class="alert alert-warning m-0 mt-3"> | <div v-if="wallet.currency != selectedPaymentMethod.currency && !isNaN(amount)" class="alert alert-warning m-0 mt-3"> | ||||
{{ $t('wallet.payment-warning', { price: $root.price(amount * selectedPaymentMethod.exchangeRate * 100, selectedPaymentMethod.currency) }) }} | {{ $t('wallet.payment-warning', { price: $root.price(amount * selectedPaymentMethod.exchangeRate * 100, selectedPaymentMethod.currency) }) }} | ||||
</div> | </div> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
<div id="auto-payment" v-if="paymentForm == 'auto'"> | <div id="auto-payment" v-if="paymentForm == 'auto'"> | ||||
<form data-validation-prefix="mandate_"> | <form data-validation-prefix="mandate_"> | ||||
<p> | <p> | ||||
{{ $t('wallet.auto-payment-hint') }} | {{ $t('wallet.auto-payment-hint') }} | ||||
</p> | </p> | ||||
<div class="row mb-3"> | <div class="row mb-3"> | ||||
<label for="mandate_amount" class="col-sm-6 col-form-label">{{ $t('wallet.fill-up') }}</label> | <label for="mandate_amount" class="col-sm-6 col-form-label">{{ $t('wallet.fill-up') }}</label> | ||||
<div class="col-sm-6"> | <div class="col-sm-6"> | ||||
<div class="input-group"> | <div class="input-group"> | ||||
<input type="text" class="form-control" id="mandate_amount" v-model="mandate.amount" required> | <input type="text" class="form-control" id="mandate_amount" v-model="mandate.amount" required> | ||||
<span class="input-group-text">{{ wallet.currency }}</span> | <span class="input-group-text">{{ wallet.currency }}</span> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="row mb-3"> | <div class="row mb-3"> | ||||
<label for="mandate_balance" class="col-sm-6 col-form-label">{{ $t('wallet.when-below') }}</label> | <label for="mandate_balance" class="col-sm-6 col-form-label">{{ $t('wallet.when-below') }}</label> | ||||
<div class="col-sm-6"> | <div class="col-sm-6"> | ||||
<div class="input-group"> | <div class="input-group"> | ||||
<input type="text" class="form-control" id="mandate_balance" v-model="mandate.balance" required> | <input type="text" class="form-control" id="mandate_balance" v-model="mandate.balance" required> | ||||
<span class="input-group-text">{{ wallet.currency }}</span> | <span class="input-group-text">{{ wallet.currency }}</span> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<p v-if="!mandate.isValid"> | <p v-if="!mandate.isValid"> | ||||
{{ $t('wallet.auto-payment-next') }} | {{ $t('wallet.auto-payment-next') }} | ||||
</p> | </p> | ||||
<div v-if="mandate.isValid && mandate.isDisabled" class="disabled-mandate alert alert-danger m-0"> | <div v-if="mandate.isValid && mandate.isDisabled" class="disabled-mandate alert alert-danger m-0"> | ||||
{{ $t('wallet.auto-payment-disabled-next') }} | {{ $t('wallet.auto-payment-disabled-next') }} | ||||
</div> | </div> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
</div> | </modal-dialog> | ||||
<div class="modal-footer"> | |||||
<btn class="btn-secondary modal-cancel" data-bs-dismiss="modal">{{ $t('btn.cancel') }}</btn> | |||||
<btn class="btn-primary modal-action" icon="check" @click="autoPayment" | |||||
v-if="paymentForm == 'auto' && (mandate.isValid || mandate.isPending)" | |||||
> | |||||
{{ $t('btn.submit') }} | |||||
</btn> | |||||
<btn class="btn btn-primary modal-action" icon="check" @click="autoPayment" | |||||
v-if="paymentForm == 'auto' && !mandate.isValid && !mandate.isPending" | |||||
> | |||||
{{ $t('btn.continue') }} | |||||
</btn> | |||||
<btn class="btn-primary modal-action" icon="check" @click="payment" | |||||
v-if="paymentForm == 'manual'" | |||||
> | |||||
{{ $t('btn.continue') }} | |||||
</btn> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import { Modal } from 'bootstrap' | import ModalDialog from './Widgets/ModalDialog' | ||||
import TransactionLog from './Widgets/TransactionLog' | import TransactionLog from './Widgets/TransactionLog' | ||||
import PaymentLog from './Widgets/PaymentLog' | import PaymentLog from './Widgets/PaymentLog' | ||||
import { downloadFile } from '../js/utils' | import { downloadFile } from '../js/utils' | ||||
import { library } from '@fortawesome/fontawesome-svg-core' | import { library } from '@fortawesome/fontawesome-svg-core' | ||||
library.add( | library.add( | ||||
require('@fortawesome/free-brands-svg-icons/faPaypal').definition, | require('@fortawesome/free-brands-svg-icons/faPaypal').definition, | ||||
require('@fortawesome/free-regular-svg-icons/faCreditCard').definition, | require('@fortawesome/free-regular-svg-icons/faCreditCard').definition, | ||||
require('@fortawesome/free-solid-svg-icons/faBuildingColumns').definition, | require('@fortawesome/free-solid-svg-icons/faBuildingColumns').definition, | ||||
) | ) | ||||
export default { | export default { | ||||
components: { | components: { | ||||
ModalDialog, | |||||
TransactionLog, | TransactionLog, | ||||
PaymentLog | PaymentLog | ||||
}, | }, | ||||
data() { | data() { | ||||
return { | return { | ||||
amount: '', | amount: '', | ||||
mandate: { amount: 10, balance: 0, method: null }, | mandate: { amount: 10, balance: 0, method: null }, | ||||
paymentDialogTitle: null, | paymentDialogTitle: null, | ||||
paymentForm: null, | paymentForm: null, | ||||
nextForm: null, | nextForm: null, | ||||
receipts: [], | receipts: [], | ||||
stripe: null, | stripe: null, | ||||
loadTransactions: false, | loadTransactions: false, | ||||
loadPayments: false, | loadPayments: false, | ||||
showPendingPayments: false, | showPendingPayments: false, | ||||
wallet: {}, | wallet: {}, | ||||
walletId: null, | walletId: null, | ||||
paymentMethods: [], | paymentMethods: [], | ||||
selectedPaymentMethod: null | selectedPaymentMethod: null | ||||
} | } | ||||
}, | }, | ||||
computed: { | |||||
dialogButtons() { | |||||
if (this.paymentForm == 'method') { | |||||
return [] | |||||
} | |||||
const button = { | |||||
className: 'btn-primary modal-action', | |||||
icon: 'check', | |||||
label: 'btn.submit' | |||||
} | |||||
if (this.paymentForm == 'manual' | |||||
|| (this.paymentForm == 'auto' && !this.mandate.isValid && !this.mandate.isPending) | |||||
) { | |||||
button.label = 'btn.continue' | |||||
} | |||||
return [ button ] | |||||
} | |||||
}, | |||||
mounted() { | mounted() { | ||||
$('#wallet button').focus() | $('#wallet button').focus() | ||||
this.walletId = this.$root.authInfo.wallets[0].id | this.walletId = this.$root.authInfo.wallets[0].id | ||||
axios.get('/api/v4/wallets/' + this.walletId, { loader: true }) | axios.get('/api/v4/wallets/' + this.walletId, { loader: true }) | ||||
.then(response => { | .then(response => { | ||||
this.wallet = response.data | this.wallet = response.data | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | export default { | ||||
selectPaymentMethod(method) { | selectPaymentMethod(method) { | ||||
this.formLock = false | this.formLock = false | ||||
this.selectedPaymentMethod = method | this.selectedPaymentMethod = method | ||||
this.paymentForm = this.nextForm | this.paymentForm = this.nextForm | ||||
setTimeout(() => { $('#payment-dialog').find('#amount,#mandate_amount').focus() }, 10) | setTimeout(() => { $('#payment-dialog').find('#amount,#mandate_amount').focus() }, 10) | ||||
}, | }, | ||||
payment() { | payment() { | ||||
if (this.paymentForm == 'auto') { | |||||
mollekopf: This looks like a change in behaviour. Please separate refactorings from changes in behaviour… | |||||
return this.autoPayment() | |||||
} | |||||
if (this.formLock) { | if (this.formLock) { | ||||
return | return | ||||
} | } | ||||
// Lock the form to prevent from double submission | // Lock the form to prevent from double submission | ||||
this.formLock = true | this.formLock = true | ||||
let onFinish = () => { this.formLock = false } | let onFinish = () => { this.formLock = false } | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | export default { | ||||
if (response.data.redirectUrl) { | if (response.data.redirectUrl) { | ||||
location.href = response.data.redirectUrl | location.href = response.data.redirectUrl | ||||
} else if (response.data.id) { | } else if (response.data.id) { | ||||
this.stripeCheckout(response.data) | this.stripeCheckout(response.data) | ||||
} | } | ||||
} else { | } else { | ||||
// an update | // an update | ||||
if (response.data.status == 'success') { | if (response.data.status == 'success') { | ||||
this.dialog.hide(); | this.$refs.paymentDialog.hide(); | ||||
this.mandate = response.data | this.mandate = response.data | ||||
this.$toast.success(response.data.message) | this.$toast.success(response.data.message) | ||||
} | } | ||||
} | } | ||||
}) | }) | ||||
}, | }, | ||||
autoPaymentChange(event) { | autoPaymentChange(event) { | ||||
this.autoPaymentForm(event, this.$t('wallet.auto-payment-update')) | this.autoPaymentForm(event, this.$t('wallet.auto-payment-update')) | ||||
Show All 9 Lines | export default { | ||||
}, | }, | ||||
paymentMethodForm(nextForm) { | paymentMethodForm(nextForm) { | ||||
this.formLock = false | this.formLock = false | ||||
this.paymentMethods = [] | this.paymentMethods = [] | ||||
this.paymentForm = 'method' | this.paymentForm = 'method' | ||||
this.nextForm = nextForm | this.nextForm = nextForm | ||||
this.paymentDialogTitle = this.$t(nextForm == 'auto' ? 'wallet.auto-payment-setup' : 'wallet.top-up') | this.paymentDialogTitle = this.$t(nextForm == 'auto' ? 'wallet.auto-payment-setup' : 'wallet.top-up') | ||||
this.dialog = new Modal('#payment-dialog') | this.$refs.paymentDialog.show() | ||||
this.dialog.show() | |||||
this.$nextTick().then(() => { | this.$nextTick().then(() => { | ||||
const type = nextForm == 'manual' ? 'oneoff' : 'recurring' | const type = nextForm == 'manual' ? 'oneoff' : 'recurring' | ||||
const loader = ['#payment-method', { 'min-height': '10em', small: false }] | const loader = ['#payment-method', { 'min-height': '10em', small: false }] | ||||
axios.get('/api/v4/payments/methods', { params: { type }, loader }) | axios.get('/api/v4/payments/methods', { params: { type }, loader }) | ||||
.then(response => { | .then(response => { | ||||
this.paymentMethods = response.data | this.paymentMethods = response.data | ||||
}) | }) | ||||
}) | }) | ||||
}, | }, | ||||
autoPaymentForm(event, title) { | autoPaymentForm(event, title) { | ||||
this.paymentForm = 'auto' | this.paymentForm = 'auto' | ||||
this.paymentDialogTitle = title | this.paymentDialogTitle = title | ||||
this.formLock = false | this.formLock = false | ||||
this.dialog = new Modal('#payment-dialog') | this.$refs.paymentDialog.show() | ||||
this.dialog.show() | |||||
}, | }, | ||||
receiptDownload() { | receiptDownload() { | ||||
const receipt = $('#receipt-id').val() | const receipt = $('#receipt-id').val() | ||||
downloadFile('/api/v4/wallets/' + this.walletId + '/receipts/' + receipt) | downloadFile('/api/v4/wallets/' + this.walletId + '/receipts/' + receipt) | ||||
}, | }, | ||||
stripeInit() { | stripeInit() { | ||||
let script = $('#stripe-script') | let script = $('#stripe-script') | ||||
Show All 33 Lines |
This looks like a change in behaviour. Please separate refactorings from changes in behaviour, because this way the change is pretty much invisible to anyone reviewing the git commits or the diff here.