728 lines
30 KiB
Vue
728 lines
30 KiB
Vue
<script setup>
|
|
import StartOverPupup from '@/views/pages/home/StartOverPupup.vue';
|
|
import axios from '@axios';
|
|
import {
|
|
cardNumberValidator,
|
|
cvvValidator,
|
|
expiryValidator,
|
|
requiredValidator,
|
|
} from '@validators';
|
|
import { onBeforeMount, onMounted } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { useStore } from 'vuex';
|
|
import Cart from '../layouts/components/cart.vue';
|
|
import CustomNav from '../layouts/components/navbar-custom.vue';
|
|
const store = useStore()
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const isMobile = ref(window.innerWidth <= 768); // Assuming mobile width is less than or equal to 768px
|
|
const patient_id = localStorage.getItem('patient_id')
|
|
const access_token = localStorage.getItem('access_token');
|
|
|
|
const isTonalSnackbarVisible = ref(false)
|
|
const patientResponse = ref(false)
|
|
const isLoadingVisible = ref(false)
|
|
const paymentForm = ref()
|
|
const cardNumber = ref('')
|
|
const expiry = ref('')
|
|
const cvv = ref('')
|
|
const firstName = ref('')
|
|
const lastName = ref('')
|
|
const email = ref('')
|
|
const phone = ref('')
|
|
const address = ref('')
|
|
const apt = ref('')
|
|
const city = ref('')
|
|
const state = ref('')
|
|
const zipcode = ref('')
|
|
const billingaddress = ref('')
|
|
const billingapt = ref('')
|
|
const billingcity = ref('')
|
|
const billingstate = ref('')
|
|
const billingzipcode = ref('')
|
|
const termAndCondtiton = ref(true)
|
|
const billingSection = ref(false)
|
|
const schedule_consultant = ref(true)
|
|
const order_complete = ref(false);
|
|
const planName = ref(null)
|
|
const planAmount = ref(null)
|
|
const list_one_title = ref(null)
|
|
const list_sub_title = ref(null)
|
|
const list_two_title = ref(null)
|
|
const prescription_required = ref(null)
|
|
const shipping_price = ref(null)
|
|
const confirmPopup = ref(false)
|
|
const verifiedAddress = ref(null);
|
|
const suggestedStreet = ref(null);
|
|
const suggestedCity = ref(null);
|
|
const suggestedState = ref(null);
|
|
const suggestedZip = ref(null);
|
|
const suggestedAddress = ref(null);
|
|
const selectedAddress = ref('notsuggested')
|
|
const typedAddress = ref(null)
|
|
const seetingPlanLogo = ref();
|
|
const products = JSON.parse(localStorage.getItem('cart_products'));
|
|
const labKits = JSON.parse(localStorage.getItem('labkits'));
|
|
const totalShipping = ref(0)
|
|
const totalAmount = ref(0)
|
|
const grandTotal = ref(0)
|
|
const prescreptionRequired = ref(false)
|
|
const paymentPopup = ref(false)
|
|
const paymentPopupText = "Your payment for $"+labKits[0].amount+".00 was successful"
|
|
const states = ref([
|
|
{ name: 'Alabama', abbreviation: 'AL' },
|
|
{ name: 'Alaska', abbreviation: 'AK' },
|
|
{ name: 'Arizona', abbreviation: 'AZ' },
|
|
{ name: 'Arkansas', abbreviation: 'AR' },
|
|
{ name: 'Howland Island', abbreviation: 'UM-84' },
|
|
{ name: 'Delaware', abbreviation: 'DE' },
|
|
{ name: 'Maryland', abbreviation: 'MD' },
|
|
{ name: 'Baker Island', abbreviation: 'UM-81' },
|
|
{ name: 'Kingman Reef', abbreviation: 'UM-89' },
|
|
{ name: 'New Hampshire', abbreviation: 'NH' },
|
|
{ name: 'Wake Island', abbreviation: 'UM-79' },
|
|
{ name: 'Kansas', abbreviation: 'KS' },
|
|
{ name: 'Texas', abbreviation: 'TX' },
|
|
{ name: 'Nebraska', abbreviation: 'NE' },
|
|
{ name: 'Vermont', abbreviation: 'VT' },
|
|
{ name: 'Jarvis Island', abbreviation: 'UM-86' },
|
|
{ name: 'Hawaii', abbreviation: 'HI' },
|
|
{ name: 'Guam', abbreviation: 'GU' },
|
|
{ name: 'United States Virgin Islands', abbreviation: 'VI' },
|
|
{ name: 'Utah', abbreviation: 'UT' },
|
|
{ name: 'Oregon', abbreviation: 'OR' },
|
|
{ name: 'California', abbreviation: 'CA' },
|
|
{ name: 'New Jersey', abbreviation: 'NJ' },
|
|
{ name: 'North Dakota', abbreviation: 'ND' },
|
|
{ name: 'Kentucky', abbreviation: 'KY' },
|
|
{ name: 'Minnesota', abbreviation: 'MN' },
|
|
{ name: 'Oklahoma', abbreviation: 'OK' },
|
|
{ name: 'Pennsylvania', abbreviation: 'PA' },
|
|
{ name: 'New Mexico', abbreviation: 'NM' },
|
|
{ name: 'American Samoa', abbreviation: 'AS' },
|
|
{ name: 'Illinois', abbreviation: 'IL' },
|
|
{ name: 'Michigan', abbreviation: 'MI' },
|
|
{ name: 'Virginia', abbreviation: 'VA' },
|
|
{ name: 'Johnston Atoll', abbreviation: 'UM-67' },
|
|
{ name: 'West Virginia', abbreviation: 'WV' },
|
|
{ name: 'Mississippi', abbreviation: 'MS' },
|
|
{ name: 'Northern Mariana Islands', abbreviation: 'MP' },
|
|
{ name: 'United States Minor Outlying Islands', abbreviation: 'UM' },
|
|
{ name: 'Massachusetts', abbreviation: 'MA' },
|
|
{ name: 'Connecticut', abbreviation: 'CT' },
|
|
{ name: 'Florida', abbreviation: 'FL' },
|
|
{ name: 'District of Columbia', abbreviation: 'DC' },
|
|
{ name: 'Midway Atoll', abbreviation: 'UM-71' },
|
|
{ name: 'Navassa Island', abbreviation: 'UM-76' },
|
|
{ name: 'Indiana', abbreviation: 'IN' },
|
|
{ name: 'Wisconsin', abbreviation: 'WI' },
|
|
{ name: 'Wyoming', abbreviation: 'WY' },
|
|
{ name: 'South Carolina', abbreviation: 'SC' },
|
|
{ name: 'Arkansas', abbreviation: 'AR' },
|
|
{ name: 'South Dakota', abbreviation: 'SD' },
|
|
{ name: 'Montana', abbreviation: 'MT' },
|
|
{ name: 'North Carolina', abbreviation: 'NC' },
|
|
{ name: 'Palmyra Atoll', abbreviation: 'UM-95' },
|
|
{ name: 'Puerto Rico', abbreviation: 'PR' },
|
|
{ name: 'Colorado', abbreviation: 'CO' },
|
|
{ name: 'Missouri', abbreviation: 'MO' },
|
|
{ name: 'New York', abbreviation: 'NY' },
|
|
{ name: 'Maine', abbreviation: 'ME' },
|
|
{ name: 'Tennessee', abbreviation: 'TN' },
|
|
{ name: 'Georgia', abbreviation: 'GA' },
|
|
{ name: 'Louisiana', abbreviation: 'LA' },
|
|
{ name: 'Nevada', abbreviation: 'NV' },
|
|
{ name: 'Iowa', abbreviation: 'IA' },
|
|
{ name: 'Idaho', abbreviation: 'ID' },
|
|
{ name: 'Rhode Island', abbreviation: 'RI' },
|
|
{ name: 'Washington', abbreviation: 'WA' },
|
|
{ name: 'Ohio', abbreviation: 'OH' },
|
|
// ... (add the rest of the states)
|
|
]);
|
|
const sortedStates = computed(() => {
|
|
return states.value.slice().sort((a, b) => {
|
|
return a.name.localeCompare(b.name);
|
|
});
|
|
});
|
|
const errors = ref({
|
|
address: undefined,
|
|
city: undefined,
|
|
state: undefined,
|
|
zipcode: undefined,
|
|
country: undefined,
|
|
|
|
})
|
|
onBeforeMount(async () => {
|
|
products.forEach(product => {
|
|
var price = 0
|
|
if (product.is_prescription_required == 1) {
|
|
|
|
prescreptionRequired.value = true
|
|
if (labKits[0].amount)
|
|
price = labKits[0].amount
|
|
product.title = 'LabKit For ' + product.title
|
|
product.price = productTotalPreReq(price)
|
|
totalAmount.value += price;
|
|
console.log('Prescreption Req Price', price)
|
|
} else {
|
|
|
|
prescreptionRequired.value = false
|
|
price = parseFloat(product.price);
|
|
product.price = productTotal(product)
|
|
totalAmount.value += product.qty * price;
|
|
console.log('Not Req Price', price)
|
|
}
|
|
const shippingPrice = parseFloat(product.shipping_cost);
|
|
totalShipping.value += product.qty * shippingPrice;
|
|
|
|
});
|
|
let options = { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2 };
|
|
grandTotal.value = new Intl.NumberFormat('en-US', options).format(parseFloat(totalAmount.value) + parseFloat(totalShipping.value));
|
|
totalAmount.value = new Intl.NumberFormat('en-US', options).format(totalAmount.value);
|
|
totalShipping.value = new Intl.NumberFormat('en-US', options).format(totalShipping.value);
|
|
// grandTotal.value = parseFloat(totalAmount.value) + parseFloat(totalShipping.value)
|
|
store.dispatch('updateIsLoading', true)
|
|
store.dispatch('updateCurrentPage', 'checkout')
|
|
localStorage.setItem('currentPage', 'checkout')
|
|
await store.dispatch('getPatientInfo')
|
|
await store.dispatch('getPlanInfo')
|
|
// await store.dispatch('getPatientAppointment')
|
|
await store.dispatch('getAdditionalInformation')
|
|
//Plan Information
|
|
planName.value = store.getters.getPatientPlan.plan_name
|
|
planAmount.value = store.getters.getPatientPlan.plan_amount
|
|
list_one_title.value = store.getters.getPatientPlan.list_one_title
|
|
list_sub_title.value = store.getters.getPatientPlan.list_sub_title
|
|
list_two_title.value = store.getters.getPatientPlan.list_two_title
|
|
prescription_required.value = store.getters.getPatientPlan.prescription_required
|
|
shipping_price.value = store.getters.getPatientPlan.shipping_price
|
|
|
|
firstName.value = store.getters.getPatient.first_name
|
|
lastName.value = store.getters.getPatient.last_name
|
|
email.value = store.getters.getPatient.email
|
|
phone.value = store.getters.getPatient.phone_no
|
|
address.value = store.getters.getShippingInformation.address
|
|
apt.value = store.getters.getShippingInformation.shipping_address2
|
|
city.value = store.getters.getShippingInformation.shipping_city
|
|
state.value = store.getters.getShippingInformation.shipping_state
|
|
zipcode.value = store.getters.getShippingInformation.shipping_zipcode
|
|
billingaddress.value = store.getters.getShippingInformation.billing_address1
|
|
billingapt.value = store.getters.getShippingInformation.billing_address2
|
|
billingcity.value = store.getters.getShippingInformation.billing_city
|
|
billingstate.value = store.getters.getShippingInformation.billing_state
|
|
billingzipcode.value = store.getters.getShippingInformation.billing_zipcode
|
|
store.dispatch('updateIsLoading', false)
|
|
|
|
})
|
|
onMounted(async () => {
|
|
window.addEventListener('resize', checkIfMobile);
|
|
let setting = await axios.post('/api/settings', {})
|
|
console.log(setting.data)
|
|
seetingPlanLogo.value = '/assets/logo/' + setting.data.logo
|
|
})
|
|
// Detach event listener on component unmount
|
|
onUnmounted(() => {
|
|
window.removeEventListener('resize', checkIfMobile);
|
|
});
|
|
const productTotalPreReq = (price) => {
|
|
let options = { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2 };
|
|
return new Intl.NumberFormat('en-US', options).format(parseFloat(price));
|
|
};
|
|
const productTotal = (product) => {
|
|
let options = { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2 };
|
|
return new Intl.NumberFormat('en-US', options).format(product.qty * parseFloat(product.price));
|
|
};
|
|
const checkIfMobile = () => {
|
|
isMobile.value = window.innerWidth <= 768;
|
|
};
|
|
|
|
|
|
const billingAddressShow = () => {
|
|
if (billingSection.value == false) {
|
|
billingSection.value = true;
|
|
} else {
|
|
billingSection.value = false;
|
|
}
|
|
|
|
}
|
|
const corfirmFun = async () => {
|
|
confirmPopup.value = true;
|
|
if (address.value && city.value && state.value && zipcode.value)
|
|
typedAddress.value = address.value + ' ' + city.value + ' ' + state.value + ' ' + zipcode.value
|
|
if (address.value)
|
|
await verfiFyAddress(address.value);
|
|
}
|
|
const validatePayment = async () => {
|
|
const { valid: isValid } = await paymentForm.value?.validate();
|
|
console.log('isValid ', isValid);
|
|
if (isValid) {
|
|
await saveOrderInfo()
|
|
await processPayment()
|
|
// await updatePatientAddress()
|
|
// if (prescreptionRequired.value)
|
|
if (!store.getters.getErrorMessage) {
|
|
if (store.getters.getPaymentProcessed) {
|
|
paymentPopup.value = store.getters.getPaymentProcessed
|
|
setTimeout(() => {
|
|
router.replace(route.query.to && route.query.to !== '/checkout' ? String(route.query.to) : '/book-appointment')
|
|
}, 5000)
|
|
}
|
|
}
|
|
// else
|
|
// router.replace(route.query.to && route.query.to != '/checkout' ? String(route.query.to) : '/thankyou')
|
|
}
|
|
};
|
|
|
|
// const processPayment = async () => {
|
|
// isLoadingVisible.value = true;
|
|
// await axios.post('/api/process-payment')
|
|
// .then(response => {
|
|
// console.log(response.data)
|
|
// isLoadingVisible.value = false;
|
|
// })
|
|
// .catch(error => {
|
|
// isLoadingVisible.value = false;
|
|
// console.error(error);
|
|
// });
|
|
// }
|
|
const updatePatientAddress = async () => {
|
|
console.log('updatePatientAddress');
|
|
await store.dispatch('updatePatientAddress', {
|
|
address: address.value,
|
|
city: city.value,
|
|
state: state.value,
|
|
zip_code: zipcode.value,
|
|
country: 'United States',
|
|
})
|
|
}
|
|
const saveOrderInfo = async () => {
|
|
const productIds = products.map(product => ({ plans_id: product.id, quantity: product.qty, subscription: product.subscription, onetime: product.onetime }));
|
|
console.log('saveOrderInfo');
|
|
isLoadingVisible.value = true;
|
|
let addressVal = null
|
|
let cityVal = null
|
|
let stateVal = null
|
|
let zipcodeVal = null
|
|
if (selectedAddress.value == 'suggested') {
|
|
addressVal = suggestedAddress.value
|
|
cityVal = suggestedCity.value
|
|
stateVal = suggestedState.value
|
|
zipcodeVal = suggestedZip.value
|
|
} else {
|
|
addressVal = address.value
|
|
cityVal = city.value
|
|
stateVal = state.value
|
|
zipcodeVal = zipcode.value
|
|
}
|
|
|
|
await store.dispatch('saveShippingInformation', {
|
|
first_name: firstName.value,
|
|
last_name: lastName.value,
|
|
email: email.value,
|
|
phone: phone.value,
|
|
patient_id: patient_id,
|
|
shipping_address1: addressVal,
|
|
shipping_address2: apt.value,
|
|
shipping_city: cityVal,
|
|
shipping_state: stateVal,
|
|
shipping_zipcode: zipcodeVal,
|
|
shipping_country: 'United States',
|
|
billing_address1: billingaddress.value,
|
|
billing_address2: billingapt.value,
|
|
billing_city: billingcity.value,
|
|
billing_state: billingstate.value,
|
|
billing_zipcode: billingzipcode.value,
|
|
billing_country: "",
|
|
shipping_amount: parseFloat(totalShipping.value.replace(/[^0-9.-]+/g, "")),
|
|
total_amount: parseFloat(totalAmount.value.replace(/[^0-9.-]+/g, "")),
|
|
items: productIds
|
|
})
|
|
|
|
}
|
|
const verfiFyAddress = async (address) => {
|
|
isLoadingVisible.value = true;
|
|
suggestedAddress.value = null
|
|
let addressT = address
|
|
// let addressT = '11 pinewood Pi'
|
|
let cityt = 'BOWLING GREEN'
|
|
let statet = 'KY'
|
|
let zipt = '42101'
|
|
const geocoder = new google.maps.Geocoder();
|
|
geocoder.geocode({ address: addressT }, (results, status) => {
|
|
if (status === 'OK' && results.length > 0) {
|
|
verifiedAddress.value = results[0];
|
|
} else {
|
|
console.error('Geocode was not successful for the following reason:', status);
|
|
verifiedAddress.value = null;
|
|
}
|
|
console.log(verifiedAddress.value)
|
|
suggestedStreet.value = getStreetAddress()
|
|
suggestedCity.value = getAddressComponent('locality')
|
|
suggestedState.value = getAddressComponent('administrative_area_level_1', true)
|
|
suggestedZip.value = getAddressComponent('postal_code')
|
|
if (suggestedStreet.value && suggestedCity.value && suggestedState.value && suggestedZip.value)
|
|
suggestedAddress.value = `${suggestedStreet.value}, ${suggestedCity.value}, ${suggestedState.value} ${suggestedZip.value}`;
|
|
console.log(suggestedAddress.value)
|
|
console.log('street : ', getStreetAddress())
|
|
console.log('city : ', getAddressComponent('locality'))
|
|
console.log('state : ', getAddressComponent('administrative_area_level_1'))
|
|
console.log('zip : ', getAddressComponent('postal_code'))
|
|
// const response = await axios.get('http://production.shippingapis.com/ShippingAPI.dll', {
|
|
// params: {
|
|
// API: 'Verify',
|
|
// XML: `<AddressValidateRequest USERID="201CBSUR1218"><Address>${addressT}</Address><City>${cityt}</City><State>${statet}</State><Zip5>${zipt}</Zip5></AddressValidateRequest>`
|
|
// }
|
|
// });
|
|
isLoadingVisible.value = false;
|
|
})
|
|
}
|
|
const getStreetAddress = () => {
|
|
if (!verifiedAddress.value) return '';
|
|
return verifiedAddress.value.formatted_address.split(',')[0];
|
|
};
|
|
const getAddressComponent = (type, shortname) => {
|
|
if (!verifiedAddress.value) return '';
|
|
for (const component of verifiedAddress.value.address_components) {
|
|
if (component.types.includes(type)) {
|
|
if (shortname) {
|
|
return component.short_name
|
|
} else {
|
|
return component.long_name;
|
|
}
|
|
|
|
}
|
|
}
|
|
return '';
|
|
};
|
|
const processPayment = async () => {
|
|
|
|
// Split the string by "/"
|
|
let [month, year] = expiry.value.split("/");
|
|
|
|
year = year.length === 2 ? (year >= "50" ? "19" + year : "20" + year) : year;
|
|
console.log('year',expiry.value,year)
|
|
await store.dispatch('processPayment',{
|
|
card_number: cardNumber.value,
|
|
cvv: cvv.value,
|
|
expiration_month: month,
|
|
expiration_year: year
|
|
})
|
|
}
|
|
const cardNumberFormat = () => {
|
|
cardNumber.value = cardNumber.value.replace(/\D/g, '').substring(0, 16);
|
|
|
|
};
|
|
const formatExpiry = () => {
|
|
// Automatically format the input to MM/YY format
|
|
expiry.value = expiry.value.replace(/\D/g, '').slice(0, 4).replace(/(\d{2})(\d{2})/, '$1/$2');
|
|
};
|
|
const handleCVVInput = () => {
|
|
// Remove non-digit characters from input
|
|
cvv.value = cvv.value.replace(/\D/g, '');
|
|
};
|
|
watch(selectedAddress, (newValue) => {
|
|
console.log('selectedAddress.value',selectedAddress.value)
|
|
if (newValue === 'suggested') {
|
|
address.value = suggestedStreet.value;
|
|
apt.value = suggestedStreet.value;
|
|
city.value = suggestedCity.value;
|
|
state.value = suggestedState.value;
|
|
zipcode.value = suggestedZip.value;
|
|
} else if (newValue === 'notsuggested') {
|
|
// Split the typedAddress into its components
|
|
const addressParts = typedAddress.value.split(' ');
|
|
address.value = addressParts.slice(0, -3).join(' ');
|
|
apt.value = addressParts.slice(0, -3).join(' ');
|
|
city.value = addressParts[addressParts.length - 3];
|
|
state.value = addressParts[addressParts.length - 2];
|
|
zipcode.value = addressParts[addressParts.length - 1];
|
|
}
|
|
});
|
|
const backFun = () => {
|
|
store.dispatch('updateIsLoading', true)
|
|
router.replace(route.query.to && route.query.to != '/checkout' ? String(route.query.to) : '/additional-information')
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<!-- <StartOverPupup :showPopup="store.getters.getShowStartOverPupup"></StartOverPupup> -->
|
|
<VDialog v-model="store.getters.getIsLoading" width="110" height="150" color="yellow-theme-button">
|
|
<VCardText class="" style="color: white !important;">
|
|
<div class="demo-space-x">
|
|
<VProgressCircular :size="40" color="yellow-theme-button" indeterminate />
|
|
</div>
|
|
</VCardText>
|
|
</VDialog>
|
|
<VSnackbar
|
|
v-model="store.getters.getIsTonalSnackbarVisible"
|
|
:timeout="5000"
|
|
location="top end"
|
|
variant="flat"
|
|
color="red"
|
|
>
|
|
{{ store.getters.getErrorMessage }}
|
|
</VSnackbar>
|
|
<v-dialog
|
|
v-model="paymentPopup"
|
|
width="auto"
|
|
>
|
|
<v-card
|
|
max-width="400"
|
|
prepend-icon="mdi-checkbox-marked-circle"
|
|
:text=paymentPopupText
|
|
title="Payment Success"
|
|
>
|
|
</v-card>
|
|
</v-dialog>
|
|
<VRow><CustomNav :logo='seetingPlanLogo'></CustomNav></VRow>
|
|
<VRow
|
|
style="min-height: 100dvh; margin: 0px;"
|
|
:style="isMobile ? { marginTop: '90px' } : { marginTop: '80px' }"
|
|
>
|
|
<VCol cols="12" md="6" class="bg-custom col-order-1"
|
|
:class="isMobile ? '' : ' d-flex align-center justify-center pa-4'">
|
|
<Cart></Cart>
|
|
</VCol>
|
|
<VCol cols="12" md="6" class="bg-custom-color col-order-2"
|
|
:class="isMobile ? '' : 'auth-wrapper d-flex align-center justify-center pa-4'">
|
|
<VCard class="auth-card pa-2 rounded-5" style="" :class="isMobile ? '' : 'card-wid'">
|
|
|
|
<VRow class=" mx-0 gy-3">
|
|
<!-- <VCol cols="12" lg="12" md="12">
|
|
<router-link to="/" class="text-center mb-2 mt-2"
|
|
style="width: 100%;position: relative;display: block;padding-top: 20px;">
|
|
<span class="text-center">
|
|
<VImg :src="seetingPlanLogo" width="250" height="50" class="logo-img" />
|
|
</span>
|
|
</router-link>
|
|
</VCol> -->
|
|
<VCol cols="12" md="12">
|
|
<v-card class="px-0" flat>
|
|
<VForm ref="paymentForm" @submit.prevent="() => { }">
|
|
|
|
<!-- <v-card class="" flat> -->
|
|
<div class="mb-3">
|
|
<h5 class="text-h5 mb-1 text-left mb-4">Shipping Information</h5>
|
|
<small>Please provide your shipping details below so that we can
|
|
promptly send you
|
|
the
|
|
product:</small>
|
|
</div>
|
|
<VRow>
|
|
<VCol cols="12" md="12">
|
|
<VTextField v-model="address" label="Address" :rules="[requiredValidator]"
|
|
density="comfortable" />
|
|
</VCol>
|
|
<VCol cols="12" md="12">
|
|
<VTextField v-model="apt" label="APT/Suite #" density="comfortable" />
|
|
</VCol>
|
|
</VRow>
|
|
<VRow>
|
|
<VCol cols="12" md="4">
|
|
<VTextField v-model="city" label="City" :rules="[requiredValidator]"
|
|
density="comfortable" />
|
|
</VCol>
|
|
<VCol cols="12" md="5">
|
|
<v-autocomplete clearable v-model="state" label="Select State"
|
|
:items="sortedStates" item-title="name" item-value="abbreviation"
|
|
:rules="[requiredValidator]" :error-messages="errors.state"
|
|
density="comfortable">
|
|
</v-autocomplete>
|
|
</VCol>
|
|
<VCol cols="12" md="3">
|
|
<VTextField type="number" v-model="zipcode" :rules="[requiredValidator]"
|
|
label="ZipCode" density="comfortable" />
|
|
</VCol>
|
|
</VRow>
|
|
<div class="mb-3">
|
|
<h4 class="mb-2 mt-4">
|
|
Card Information <VIcon>mdi-credit-card</VIcon>
|
|
</h4>
|
|
</div>
|
|
<VRow>
|
|
<VCol cols="12" lg="12" md="12">
|
|
<VTextField v-model="cardNumber" label="Credit Card Number*"
|
|
:rules="[requiredValidator, cardNumberValidator]"
|
|
placeholder="xxxxxxxxxxxxxxxx" @input="cardNumberFormat"
|
|
density="comfortable" />
|
|
</VCol>
|
|
<!-- <VCol cols="12" lg="4" md="4">
|
|
<VTextField v-model="zipcode" label="Zipcode*" type="number"
|
|
:rules="[requiredValidator]" placeholder="zipcode" density="comfortable"/>
|
|
</VCol> -->
|
|
<VCol cols="12" lg="6" md="6">
|
|
<VTextField v-model="expiry" label="Expiration Date*"
|
|
:rules="[requiredValidator, expiryValidator]" placeholder="MM/YY"
|
|
@input="formatExpiry" density="comfortable" />
|
|
</VCol>
|
|
<VCol cols="12" lg="6" md="6">
|
|
<VTextField v-model="cvv" :rules="[requiredValidator, cvvValidator]"
|
|
label="CVV*" maxlength="3" @input="handleCVVInput" density="comfortable" />
|
|
</VCol>
|
|
</VRow>
|
|
<!-- <VRow>
|
|
<VCol cols="12" md="12" class="px-4 mt-3">
|
|
<VCheckbox v-model="termAndCondtiton" @click=billingAddressShow
|
|
label="Billing Address same as shipping." />
|
|
</VCol>
|
|
</VRow> -->
|
|
<!-- </v-card> -->
|
|
<v-card class="px-2 mt-2 mb-2" flat v-if="billingSection">
|
|
<h3 class="mb-3">Billing Information</h3>
|
|
<VRow>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="billingaddress" label="Address"
|
|
:rules="[requiredValidator]" density="comfortable" />
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="billingapt" label="APT/Suite #"
|
|
density="comfortable" />
|
|
</VCol>
|
|
</VRow>
|
|
<VRow>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="billingcity" label="City" :rules="[requiredValidator]"
|
|
density="comfortable" />
|
|
</VCol>
|
|
</VRow>
|
|
</v-card>
|
|
<div class="text-center mb-2 mt-4">
|
|
<VBtn class="px-4 mb-2" color="primary" variant="flat" block @click="corfirmFun"
|
|
style="background-color: rgb(var(--v-theme-yellow-theme-button)) !important;">
|
|
Checkout</VBtn>
|
|
<!-- <VBtn class="px-4" color="grey" variant="flat" @click="backFun"
|
|
:class="isMobile ? '' : 'mr-2'" block>
|
|
Back</VBtn> -->
|
|
|
|
</div>
|
|
<VDialog v-model="confirmPopup" refs="myDialog" persistent width="500">
|
|
|
|
<!-- <template v-slot:default="{ isActive }"> -->
|
|
<v-card>
|
|
<v-card-text>
|
|
<div class="mt-2 mb-2">
|
|
<small>Select the correct address that match your current
|
|
address</small>
|
|
</div>
|
|
|
|
<v-radio-group v-model="selectedAddress" :rules="[requiredValidator]"
|
|
v-if="typedAddress || suggestedAddress">
|
|
<v-radio :label="suggestedAddress" v-if="suggestedAddress"
|
|
value="suggested"></v-radio>
|
|
<v-radio :label="typedAddress" value="notsuggested"
|
|
v-if="typedAddress"></v-radio>
|
|
</v-radio-group>
|
|
</v-card-text>
|
|
|
|
<v-card-actions>
|
|
<v-spacer></v-spacer>
|
|
<v-btn type="submit" text="Confirm" @click="validatePayment"></v-btn>
|
|
<v-btn text="Close" @click="confirmPopup = false"></v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
<!-- </template> -->
|
|
</VDialog>
|
|
</VForm>
|
|
</v-card>
|
|
</VCol>
|
|
</VRow>
|
|
</VCard>
|
|
</VCol>
|
|
</VRow>
|
|
|
|
</template>
|
|
<style scoped>
|
|
@media only screen and (max-width: 768px) {
|
|
.card-wid {
|
|
max-width: 600px !important;
|
|
min-width: auto !important;
|
|
}
|
|
|
|
.col-order-1 {
|
|
order: 2;
|
|
}
|
|
|
|
.col-order-2 {
|
|
order: 1;
|
|
}
|
|
}
|
|
|
|
@media only screen and (min-width: 769px) {
|
|
.col-order-1 {
|
|
order: 1;
|
|
}
|
|
|
|
.col-order-2 {
|
|
order: 2;
|
|
}
|
|
}
|
|
|
|
.total-font {
|
|
font-size: 20px;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.bg-custom {
|
|
background: #f5fafd;
|
|
}
|
|
|
|
.bg-custom-color {
|
|
background: #D8EBF6;
|
|
}
|
|
|
|
.bg-white bg-change-bk .current-plan {
|
|
border: 2px solid rgb(var(--v-theme-primary));
|
|
}
|
|
|
|
.cut-text {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
text-decoration: line-through;
|
|
text-decoration-color: red;
|
|
text-decoration-thickness: 1px;
|
|
}
|
|
|
|
.plan-card {
|
|
margin: 0rem;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.card-wid {
|
|
max-width: 600px;
|
|
}
|
|
|
|
.layout-wrapper {
|
|
justify-content: center;
|
|
}
|
|
|
|
.error-message {
|
|
color: #ff2f2f;
|
|
font-size: 15px;
|
|
}
|
|
</style>
|
|
<style lang="scss">
|
|
.bg-custom {
|
|
background: #f5fafd;
|
|
}
|
|
|
|
.bg-custom-color {
|
|
background: #D8EBF6;
|
|
}
|
|
|
|
.total-font {
|
|
font-size: 20px;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.card-title {
|
|
font-family: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
|
}
|
|
|
|
.logo-img {
|
|
display: block;
|
|
position: relative;
|
|
margin: 0 auto;
|
|
}
|
|
</style>
|