%PDF- %PDF-
Direktori : /home/forge/takeaseat.eco-n-tech.co.uk/components/blocks/Booking/ |
Current File : //home/forge/takeaseat.eco-n-tech.co.uk/components/blocks/Booking/PaymentStep.vue |
<template> <div> <span class="block text-center text-3xl font-bold mb-6">Payment</span> <div class="grid grid-cols-1 sm:grid-cols-2 gap-y-3 mb-6"> <div class="leading-6 text-center sm:text-left">{{ Object.keys(selected_slots).length }} x Sessions with {{ therapist.user.full_name }}</div> <div class="flex items-center justify-center sm:justify-end text-2xl font-bold">{{ totals.formatted }}</div> </div> <div v-show="isPaymentRequestAllowed" id="payment-request-wrapper"> <div class="w-full flex items-center justify-center mb-8"> <div class="w-full" id="payment-request-button"></div> </div> <div class="relative text-center my-6"> <span class="absolute z-10 top-1/2 left-0 transform -translate-y-1/2 block w-full h-0.5 bg-gray"></span> <span class="relative z-20 inline-block px-6 bg-white uppercase">Or Pay with Card</span> </div> </div> <div v-if="isPaymentRequestAllowed == false" class="relative text-center my-6"> <span class="absolute z-10 top-1/2 left-0 transform -translate-y-1/2 block w-full h-0.5 bg-gray"></span> <span class="relative z-20 inline-block px-6 bg-white uppercase">Pay with Card</span> </div> <div class="grid grid-cols-1 gap-y-2 mb-6" v-if="payment_methods.length > 0"> <label v-for="(payment_method, key) in payment_methods" v-bind:key="key" :for="'payment_method-'+key" :class="selected_payment_method == payment_method.id ? 'bg-gray' : ''" class="relative grid grid-cols-2 bg-white border border-black border-opacity-10 py-2 px-3 pl-12 rounded-lg transition cursor-pointer"> <input class="hidden" v-model="selected_payment_method" type="radio" name="payment_methods" :id="'payment_method-'+key" :value="payment_method.id" /> <div :class="'card-icon-'+payment_method.card.brand" class="absolute top-0 left-0.5 w-10 h-full bg-center bg-contain"></div> <span class="text-sm">{{ payment_method.billing_details.name }}</span> <div class="text-sm flex items-center justify-end"> <span class="mx-2">****{{ payment_method.card.last4 }}</span> <span class="mx-2">{{ payment_method.card.exp_month }}/{{ payment_method.card.exp_year }}</span> </div> </label> </div> <div v-show="selected_payment_method == null"> <ValidationObserver ref="paymentForm"> <form @submit.prevent="submitForm" role="form" method="POST"> <ValidationProvider rules="required" v-slot="{ errors }"> <t-input-group label="Name on Card"> <t-input type="text" v-model="card_name" placeholder="Name on Card" /> <span class="field-invalid" v-if="errors[0]">{{ errors[0] }}</span> </t-input-group> </ValidationProvider> <t-input-group label="Card Information"> <div class="px-4 py-4 bg-white border border-black border-opacity-20 rounded-xl" id="card-element"></div> </t-input-group> <div class="flex flex-col items-center justify-center sm:px-10"> <button :disabled="working == true" class="btn btn-primary btn-small rounded-full w-full sm:w-auto" type="submit"> <span v-if="working == false">Pay Now</span> <span class="flex items-center justify-center" v-else> <svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-current" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> <span>Processing</span> </span> </button> <button @click="goBack" class="mt-6 uppercase text-blue-light text-sm" type="button">Go Back</button> </div> </form> </ValidationObserver> </div> <div class="flex flex-col items-center justify-center sm:px-10" v-if="selected_payment_method"> <button @click="selected_payment_method = null" class="mb-2 uppercase text-blue-light text-sm">Use New Card</button> <button @click="createPayment(selected_payment_method)" :disabled="working == true" class="btn btn-primary btn-small rounded-full w-full sm:w-auto" type="button"> <span v-if="working == false">Pay Now</span> <span class="flex items-center justify-center" v-else> <svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-current" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> <span>Processing</span> </span> </button> <button @click="goBack" class="mt-6 uppercase text-blue-light text-sm" type="button">Go Back</button> </div> <p class="text-sm text-center mt-6 text-black text-opacity-75">By subscribing to Take a Seat you are agreeing to all site <NuxtLink class="text-blue-light hover:underline" to="/terms-conditions" target="_blank">Terms and Conditions</NuxtLink>. Please read carefully before continuing.</p> </div> </template> <script> export default { props: { value: { required: true }, selected_slots: { type: Object, required: true } }, data() { return { error: null, working: false, stripe: null, card: {}, selected_payment_method: null, isPaymentRequestAllowed: false, paymentRequest: {}, card_name: null } }, computed: { totals() { return this.$store.state.booking.summary.totals }, therapist() { return this.$store.state.booking.therapist }, payment_methods() { return this.$store.state.account.billing.paymentMethods }, setup_intent() { return this.$store.state.account.billing.setupIntent }, connect_id() { return this.$store.state.booking.payment.connect_id } }, async mounted() { await this.$store.dispatch('account/billing/setupIntent') await this.$store.dispatch('account/billing/getPaymentMethods') this.mountCard(); }, methods: { mountCard() { const elements = this.$stripe.elements(); this.card = elements.create('card', { style: { base: { fontSize: '15px', fontFamily: 'Poppins, sans-serif' } } }); this.getPaymentRequest(); this.card.mount('#card-element'); }, submitForm() { this.$refs.paymentForm.validate().then(success => { if (!success) { return; } this.confirmCardSetup(); }); }, async getPaymentRequest() { this.paymentRequest = await this.$stripe.paymentRequest({ country: 'GB', currency: 'gbp', total: { amount: parseInt(this.totals.amount), label: 'Takeaseat Booking with '+this.therapist.user.full_name, }, requestPayerName: true, requestPayerEmail: true }); this.mountPaymentButton(); }, async mountPaymentButton() { const elements = this.$stripe.elements(); let prButton = elements.create('paymentRequestButton', { paymentRequest: this.paymentRequest, }); // Check the availability of the Payment Request API first. this.paymentRequest.canMakePayment().then(function(result) { if (result) { this.isPaymentRequestAllowed = true; prButton.mount('#payment-request-button'); } else { this.isPaymentRequestAllowed = false; } }.bind(this)); this.paymentRequest.on('paymentmethod', function(event) { event.complete('success'); this.createPayment(event.paymentMethod.id); }.bind(this)); }, async confirmCardSetup() { this.working = true; const { setupIntent, error } = await this.$stripe.confirmCardSetup( this.setup_intent, { payment_method: { card: this.card, billing_details: { name: this.card_name } } } ); if (error) { this.$toast.error(error.message).goAway(3000); await this.$store.dispatch('account/billing/setupIntent') this.working = false; } else { this.createPayment(setupIntent.payment_method) } }, async createPayment(payment_method) { this.working = true; await this.$axios.post('/booking/payment/'+this.therapist.user.id, { grand_total: this.totals.amount, sessions: this.selected_slots, sessions_count: Object.keys(this.selected_slots).length, payment_method: payment_method }).then((response) => { if(response.status == 200) { this.createBooking(response.data); } }).catch((error) => { this.working = false; this.$toast.error(error.response.data.message).goAway(3000); }) }, async createBooking(data) { this.working = true; await this.$axios.post('/booking/create', { sessions: this.selected_slots, amount: this.totals.amount, therapist_id: this.therapist.id, charges: data.charges, transfer: data.transfer }).then((response) => { if(response.status == 200) { this.$store.commit('booking/success/setBookings', response.data) this.$router.push({ path: '/booking/success' }) } }).catch((error) => { this.$toast.error(error.response.message).goAway(1000); this.working = false; }) }, goBack() { this.$emit("input", 2); } } } </script>