490 lines
22 KiB
Vue
490 lines
22 KiB
Vue
<script setup>
|
|
import StartOverPupup from '@/views/pages/home/StartOverPupup.vue';
|
|
import axios from '@axios';
|
|
import {
|
|
requiredValidator
|
|
} from '@validators';
|
|
import { onBeforeMount, onMounted } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { useStore } from 'vuex';
|
|
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('')
|
|
const planAmount = ref('')
|
|
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 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 () => {
|
|
store.dispatch('updateIsLoading', true)
|
|
store.dispatch('updateCurrentPage', 'shipping-information')
|
|
localStorage.setItem('currentPage', 'shipping-information')
|
|
await store.dispatch('getPatientInfo')
|
|
await store.dispatch('getPlanInfo')
|
|
await store.dispatch('getPatientAppointment')
|
|
await store.dispatch('getAdditionalInformation')
|
|
firstName.value = store.getters.getShippingInformation.first_name
|
|
lastName.value = store.getters.getShippingInformation.last_name
|
|
email.value = store.getters.getShippingInformation.email
|
|
phone.value = store.getters.getShippingInformation.phone
|
|
address.value = store.getters.getShippingInformation.shipping_address1
|
|
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 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 + ' United States'
|
|
if (address.value)
|
|
await verfiFyAddress(address.value)
|
|
}
|
|
const validatePayment = async () => {
|
|
const { valid: isValid } = await paymentForm.value?.validate();
|
|
console.log('isValid ', isValid);
|
|
if (isValid) {
|
|
// await processPayment()
|
|
await saveOrderInfo()
|
|
await updatePatientAddress()
|
|
router.replace(route.query.to && route.query.to != '/shipping-information' ? String(route.query.to) : '/process-payment')
|
|
}
|
|
};
|
|
|
|
// 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 () => {
|
|
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: 0,
|
|
total_amount: 92.50
|
|
})
|
|
|
|
}
|
|
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 + ' United States'
|
|
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 backFun = () => {
|
|
store.dispatch('updateIsLoading', true)
|
|
router.replace(route.query.to && route.query.to != '/shipping-information' ? 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="primary">
|
|
<VCardText class="" style="color: white !important;">
|
|
<div class="demo-space-x">
|
|
<VProgressCircular :size="40" color="primary" indeterminate />
|
|
</div>
|
|
</VCardText>
|
|
</VDialog>
|
|
<div class="pb-sm-5 pb-2 rounded-top">
|
|
<!-- <VContainer> -->
|
|
<div class="auth-wrapper d-flex align-center justify-center pa-4">
|
|
<VCard class="auth-card pa-2 rounded-3 mt-4 pb-4" style="max-width: 600px;">
|
|
|
|
<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">
|
|
<!-- 👉 Title and subtitle -->
|
|
<div class="text-left">
|
|
<h5 class="text-h5 pricing-title mb-0">
|
|
Lab Request
|
|
</h5>
|
|
|
|
</div>
|
|
<p class="mb-0">During your recent telehealth appointment, your doctor determined that a
|
|
blood
|
|
spot test is required to proceed with your treatment plan. This test is
|
|
essential for accurately assessing your hormone levels and ensuring the best
|
|
possible course of treatment.</p>
|
|
<p class="mb-0">We need to send you a blood spot test kit from our affiliated laboratory to
|
|
facilitate this process. This kit contains everything you need to collect a
|
|
small blood sample at home, which you can then mail back to the lab for
|
|
analysis.
|
|
</p>
|
|
</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=" mt-0">Shipping Information</h5>
|
|
<small>Please provide your shipping details below so that we can
|
|
promptly send you
|
|
the
|
|
blood spot test kit:</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="4">
|
|
<v-select v-model="state" label="Select State" :items="sortedStates"
|
|
item-title="name" item-value="abbreviation" :rules="[requiredValidator]"
|
|
:error-messages="errors.state" density="comfortable">
|
|
</v-select>
|
|
</VCol>
|
|
<VCol cols="12" md="4">
|
|
<VTextField type="number" v-model="zipcode" :rules="[requiredValidator]"
|
|
label="ZipCode" 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)) !important;">
|
|
Order Blood Lab Test</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>
|
|
</div>
|
|
<!-- </VContainer> -->
|
|
</div>
|
|
|
|
</template>
|
|
<style lang="scss">
|
|
.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>
|