Changeset View
Changeset View
Standalone View
Standalone View
src/resources/vue/Wallet.vue
Show All 16 Lines | <div class="container" dusk="wallet-component"> | ||||
<a class="nav-link active" id="tab-history" href="#wallet-history" role="tab" aria-controls="wallet-history" aria-selected="true"> | <a class="nav-link active" id="tab-history" href="#wallet-history" role="tab" aria-controls="wallet-history" aria-selected="true"> | ||||
History | History | ||||
</a> | </a> | ||||
</li> | </li> | ||||
</ul> | </ul> | ||||
<div class="tab-content"> | <div class="tab-content"> | ||||
<div class="tab-pane show active" id="wallet-history" role="tabpanel" aria-labelledby="tab-history"> | <div class="tab-pane show active" id="wallet-history" role="tabpanel" aria-labelledby="tab-history"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <transaction-log v-if="walletId" class="card-text" :wallet-id="walletId"></transaction-log> | ||||
<table class="table table-sm m-0"> | |||||
<thead class="thead-light"> | |||||
<tr> | |||||
<th scope="col">Date</th> | |||||
<th scope="col"></th> | |||||
<th scope="col">Description</th> | |||||
<th scope="col" class="price">Amount</th> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr v-for="transaction in transactions" :id="'log' + transaction.id" :key="transaction.id"> | |||||
<td class="datetime">{{ transaction.createdAt }}</td> | |||||
<td class="selection"> | |||||
<button class="btn btn-lg btn-link btn-action" title="Details" | |||||
v-if="transaction.hasDetails" | |||||
@click="loadTransaction(transaction.id)" | |||||
> | |||||
<svg-icon icon="info-circle"></svg-icon> | |||||
</button> | |||||
</td> | |||||
<td class="description">{{ transactionDescription(transaction) }}</td> | |||||
<td :class="'price ' + transactionClass(transaction)">{{ transactionAmount(transaction) }}</td> | |||||
</tr> | |||||
</tbody> | |||||
<tfoot class="table-fake-body"> | |||||
<tr> | |||||
<td colspan="4">There are no transactions for this account.</td> | |||||
</tr> | |||||
</tfoot> | |||||
</table> | |||||
<div class="text-center p-3" id="transactions-loader"> | |||||
<button class="btn btn-secondary" v-if="transactions_more" @click="loadTransactions(true)">Load more</button> | |||||
</div> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div id="payment-dialog" class="modal" tabindex="-1" role="dialog"> | <div id="payment-dialog" class="modal" tabindex="-1" role="dialog"> | ||||
<div class="modal-dialog" role="document"> | <div class="modal-dialog" role="document"> | ||||
<div class="modal-content"> | <div class="modal-content"> | ||||
<div class="modal-header"> | <div class="modal-header"> | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | <div class="container" dusk="wallet-component"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import TransactionLog from './Widgets/TransactionLog' | |||||
export default { | export default { | ||||
components: { | |||||
TransactionLog | |||||
}, | |||||
data() { | data() { | ||||
return { | return { | ||||
amount: '', | amount: '', | ||||
balance: 0, | balance: 0, | ||||
mandate: { amount: 10, balance: 0 }, | mandate: { amount: 10, balance: 0 }, | ||||
paymentDialogTitle: null, | paymentDialogTitle: null, | ||||
paymentForm: 'init', | paymentForm: 'init', | ||||
provider: window.config.paymentProvider, | provider: window.config.paymentProvider, | ||||
stripe: null, | stripe: null, | ||||
transactions: [], | transactions: [], | ||||
transactions_more: false, | transactions_more: false, | ||||
transactions_page: 1, | transactions_page: 1, | ||||
walletId: null, | |||||
wallet_currency: 'CHF' | wallet_currency: 'CHF' | ||||
} | } | ||||
}, | }, | ||||
mounted() { | mounted() { | ||||
this.balance = 0 | this.balance = 0 | ||||
// TODO: currencies, multi-wallets, accounts | // TODO: currencies, multi-wallets, accounts | ||||
this.$store.state.authInfo.wallets.forEach(wallet => { | this.$store.state.authInfo.wallets.forEach(wallet => { | ||||
this.balance += wallet.balance | this.balance += wallet.balance | ||||
this.provider = wallet.provider | this.provider = wallet.provider | ||||
}) | }) | ||||
this.loadTransactions() | this.walletId = this.$store.state.authInfo.wallets[0].id | ||||
if (this.provider == 'stripe') { | if (this.provider == 'stripe') { | ||||
this.stripeInit() | this.stripeInit() | ||||
} | } | ||||
}, | }, | ||||
methods: { | methods: { | ||||
loadTransactions(more) { | |||||
let loader = $('#wallet-history') | |||||
let walletId = this.$store.state.authInfo.wallets[0].id | |||||
let param = '' | |||||
if (more) { | |||||
param = '?page=' + (this.transactions_page + 1) | |||||
loader = $('#transactions-loader') | |||||
} | |||||
this.$root.addLoader(loader) | |||||
axios.get('/api/v4/wallets/' + walletId + '/transactions' + param) | |||||
.then(response => { | |||||
this.$root.removeLoader(loader) | |||||
// Note: In Vue we can't just use .concat() | |||||
for (let i in response.data.list) { | |||||
this.$set(this.transactions, this.transactions.length, response.data.list[i]) | |||||
} | |||||
this.transactions_more = response.data.hasMore | |||||
this.transactions_page = response.data.page || 1 | |||||
}) | |||||
.catch(error => { | |||||
this.$root.removeLoader(loader) | |||||
}) | |||||
}, | |||||
loadTransaction(id) { | |||||
let walletId = this.$store.state.authInfo.wallets[0].id | |||||
let record = $('#log' + id) | |||||
let cell = record.find('td.description') | |||||
let details = $('<div class="list-details"><ul></ul><div>').appendTo(cell) | |||||
this.$root.addLoader(cell) | |||||
axios.get('/api/v4/wallets/' + walletId + '/transactions' + '?transaction=' + id) | |||||
.then(response => { | |||||
this.$root.removeLoader(cell) | |||||
record.find('button').remove() | |||||
let list = details.find('ul') | |||||
response.data.list.forEach(elem => { | |||||
list.append($('<li>').text(this.transactionDescription(elem))) | |||||
}) | |||||
}) | |||||
.catch(error => { | |||||
this.$root.removeLoader(cell) | |||||
}) | |||||
}, | |||||
paymentDialog() { | paymentDialog() { | ||||
const dialog = $('#payment-dialog') | const dialog = $('#payment-dialog') | ||||
const mandate_form = $('#mandate-form') | const mandate_form = $('#mandate-form') | ||||
this.$root.removeLoader(mandate_form) | this.$root.removeLoader(mandate_form) | ||||
if (!this.mandate.id) { | if (!this.mandate.id) { | ||||
this.$root.addLoader(mandate_form) | this.$root.addLoader(mandate_form) | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | export default { | ||||
sessionId: data.id | sessionId: data.id | ||||
}).then(result => { | }).then(result => { | ||||
// If it fails due to a browser or network error, | // If it fails due to a browser or network error, | ||||
// display the localized error message to the user | // display the localized error message to the user | ||||
if (result.error) { | if (result.error) { | ||||
this.$toast.error(result.error.message) | this.$toast.error(result.error.message) | ||||
} | } | ||||
}) | }) | ||||
}, | |||||
transactionAmount(transaction) { | |||||
return this.$root.price(transaction.amount) | |||||
}, | |||||
transactionClass(transaction) { | |||||
return transaction.amount < 0 ? 'text-danger' : 'text-success'; | |||||
}, | |||||
transactionDescription(transaction) { | |||||
let desc = transaction.description | |||||
if (/^(billed|created|deleted)$/.test(transaction.type)) { | |||||
desc += ' (' + this.$root.price(transaction.amount) + ')' | |||||
} | |||||
return desc | |||||
} | } | ||||
} | } | ||||
} | } | ||||
</script> | </script> |