831 lines
34 KiB
Vue
831 lines
34 KiB
Vue
<script setup>
|
|
import { useAppAbility } from '@/plugins/casl/useAppAbility';
|
|
import axios from '@axios';
|
|
import {
|
|
emailValidator,
|
|
requiredAddress,
|
|
requiredCity,
|
|
requiredEmail,
|
|
requiredFirstName,
|
|
requiredGender,
|
|
requiredLastName,
|
|
requiredLicenseNumber,
|
|
requiredPassword,
|
|
requiredPhone,
|
|
requiredSpecialty,
|
|
requiredState,
|
|
requiredYearsofExperience,
|
|
requiredZip,
|
|
validUSAPhone
|
|
} from '@validators';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
const seetingPlanLogo = ref();
|
|
const currentStep = ref(1)
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const ability = useAppAbility()
|
|
const errors = ref({
|
|
name: undefined,
|
|
email: undefined,
|
|
})
|
|
const inavlid = ref(false);
|
|
const InvalidCredential = ref()
|
|
const isLoadingVisible = ref(false)
|
|
const isPasswordVisible = ref(false)
|
|
const isPolicy = ref(false)
|
|
const isDisabled = ref(true)
|
|
const isDialogVisible = ref(false)
|
|
const refVForm = ref()
|
|
const verfyEmail = ref(false)
|
|
const first_name = ref(null)
|
|
const last_name = ref(null)
|
|
const email = ref(null)
|
|
const phone = ref(null)
|
|
const city = ref(null)
|
|
const stateAddress = ref('AL')
|
|
const zip = ref(null)
|
|
const password = ref(null)
|
|
const home_address = ref(null)
|
|
const medical_license_number = ref(null)
|
|
const years_of_experience = ref(null)
|
|
const gender = ref(null)
|
|
const specialty = ref(null)
|
|
const getIsTonalSnackbarVisible = ref(false);
|
|
const getIsTonalSnackbarVisibleError = ref(false);
|
|
const verificationCode = ref(['', '', '', '']);
|
|
const state = ref([])
|
|
const availabilityFrom = ref(null)
|
|
const availabilityTo = ref(null)
|
|
const medicalLicenseNumbers = ref({})
|
|
const currentUserRegister = ref(null)
|
|
const successMessage = ref(null)
|
|
const errorMessage = ref(null)
|
|
const user = ref()
|
|
const genders = [
|
|
{ value: 'male', title: 'Male' },
|
|
{ value: 'female', title: 'Female' },
|
|
{ value: 'other', title: 'Other' }
|
|
]
|
|
const requiredAvailability = (value) =>
|
|
!!value || 'Availability is required';
|
|
const specialties = ['General Practice', 'Cardiology', 'Dermatology', 'Pediatrics', /* add more options */]
|
|
const validateTimeRange = (value) => {
|
|
if (availabilityFrom.value && availabilityTo.value) {
|
|
const [fromTime, fromPeriod] = availabilityFrom.value.split(' ');
|
|
const [toTime, toPeriod] = availabilityTo.value.split(' ');
|
|
const fromHour = parseInt(fromTime.split(':')[0]);
|
|
const toHour = parseInt(toTime.split(':')[0]);
|
|
const fromMinute = parseInt(fromTime.split(':')[1]);
|
|
const toMinute = parseInt(toTime.split(':')[1]);
|
|
|
|
const fromValue = fromPeriod === 'PM' ? fromHour + 12 : fromHour;
|
|
const toValue = toPeriod === 'PM' ? toHour + 12 : toHour;
|
|
|
|
const timeDiff =
|
|
(toValue * 60 + toMinute) - (fromValue * 60 + fromMinute);
|
|
//return timeDiff >= 15 || 'Minimum time difference should be 15 minutes';
|
|
}
|
|
return true;
|
|
};
|
|
|
|
// const timeOptions = computed(() => {
|
|
// const options = [];
|
|
// for (let hour = 0; hour < 24; hour++) {
|
|
// for (let minute = 0; minute < 60; minute += 30) {
|
|
// let period = 'AM';
|
|
// let displayHour = hour;
|
|
|
|
// if (hour === 0) {
|
|
// displayHour = 12; // Convert 0 to 12 for 12:00 AM
|
|
// } else if (hour === 12) {
|
|
// period = 'PM'; // 12:00 PM
|
|
// } else if (hour > 12) {
|
|
// displayHour = hour - 12; // Convert to 12-hour format
|
|
// period = 'PM';
|
|
// }
|
|
|
|
// const timeString = `${displayHour.toString().padStart(2, '0')}:${minute
|
|
// .toString()
|
|
// .padStart(2, '0')} ${period}`;
|
|
// options.push(timeString);
|
|
// }
|
|
// }
|
|
// return options;
|
|
// });
|
|
const timeOptions = computed(() => {
|
|
const options = [];
|
|
|
|
// Loop through the hours from 12 to 23 (for 12:00 PM to 11:00 PM)
|
|
for (let hour = 12; hour < 24; hour++) {
|
|
// Loop through the minutes (0 and 30)
|
|
for (let minute of [0, 30]) {
|
|
// Construct the time string
|
|
const timeString = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
|
|
options.push(timeString);
|
|
}
|
|
}
|
|
|
|
// Add the time option for 24:00 (midnight)
|
|
options.push('24:00');
|
|
|
|
return options;
|
|
});
|
|
|
|
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: '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 selectedStateName = (abbreviation) => {
|
|
const selectedState = states.value.find(
|
|
(s) => s.abbreviation === abbreviation
|
|
);
|
|
return selectedState ? selectedState.name : abbreviation;
|
|
};
|
|
const onSubmit = () => {
|
|
inavlid.value = false;
|
|
InvalidCredential.value = '';
|
|
refVForm.value?.validate().then(({ valid: isValid }) => {
|
|
if (isValid)
|
|
saveInformation()
|
|
})
|
|
}
|
|
const formatPhoneNumber = () => {
|
|
// Remove non-numeric characters from the input
|
|
const numericValue = phone.value.replace(/\D/g, '');
|
|
|
|
// Apply formatting logic
|
|
if (numericValue.length <= 10) {
|
|
phone.value = numericValue.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
|
|
} else {
|
|
// Limit the input to a maximum of 14 characters
|
|
const truncatedValue = numericValue.slice(0, 10);
|
|
phone.value = truncatedValue.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
|
|
}
|
|
};
|
|
const validateAndProceed = async (nextStep, stepText) => {
|
|
console.log("availabilityTo", availabilityTo.value);
|
|
const { valid } = await refVForm.value.validate()
|
|
localStorage.setItem('step-register', nextStep)
|
|
let formData = {
|
|
home_address: home_address.value,
|
|
city: city.value,
|
|
state: stateAddress.value,
|
|
zip_code: zip.value,
|
|
medical_license_number: medicalLicenseNumbers.value,
|
|
years_of_experience: years_of_experience.value,
|
|
specialty: specialty.value,
|
|
gender: gender.value,
|
|
practice_state: state.value,
|
|
phone: phone.value,
|
|
availabilityFrom: '08:00:00',
|
|
availabilityTo: '10:00:00'
|
|
}
|
|
localStorage.setItem('register-form-data', JSON.stringify(formData))
|
|
if (valid) {
|
|
|
|
if (stepText == 'verification') {
|
|
let userAgent = await registerAgent()
|
|
console.log('userAgent', verfyEmail.value)
|
|
if (verfyEmail.value) {
|
|
errorMessage.value = null
|
|
InvalidCredential.value = '';
|
|
currentStep.value = nextStep
|
|
}
|
|
|
|
}
|
|
if (stepText == 'Personal Information') {
|
|
errorMessage.value = null
|
|
InvalidCredential.value = '';
|
|
currentStep.value = nextStep
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
//currentStep.value = nextStep
|
|
}
|
|
onMounted(async () => {
|
|
const layoutWrapper = document.querySelector('.layout-wrapper');
|
|
|
|
// Check if the element exists
|
|
if (layoutWrapper) {
|
|
// Add the class you want
|
|
layoutWrapper.classList.add('regbg');
|
|
}
|
|
let setting = await axios.post('/api/settings', {})
|
|
console.log(setting.data)
|
|
seetingPlanLogo.value = '/assets/logo/' + setting.data.logo
|
|
|
|
|
|
const storedStep = localStorage.getItem('step-register');
|
|
if (storedStep) {
|
|
currentStep.value = parseInt(storedStep, 10);
|
|
}
|
|
|
|
currentUserRegister.value = localStorage.getItem('register_provider_id')
|
|
let formData = localStorage.getItem('register-form-data')
|
|
let storeFormdata = JSON.parse(formData)
|
|
if (storeFormdata) {
|
|
home_address.value = storeFormdata.home_address
|
|
city.value = storeFormdata.city
|
|
stateAddress.value = storeFormdata.state
|
|
zip.value = storeFormdata.zip_code
|
|
medicalLicenseNumbers.value = storeFormdata.medical_license_number
|
|
years_of_experience.value = storeFormdata.years_of_experience
|
|
specialty.value = storeFormdata.specialty
|
|
gender.value = storeFormdata.gender
|
|
state.value = storeFormdata.practice_state
|
|
phone.value = storeFormdata.phone
|
|
availabilityFrom.value = storeFormdata.availabilityFrom
|
|
availabilityTo.value = storeFormdata.availabilityTo
|
|
console.log(JSON.parse(formData))
|
|
}
|
|
localStorage.setItem('thank-you-page', 'no')
|
|
});
|
|
onUnmounted(() => {
|
|
// Select the element by class name
|
|
const layoutWrapper = document.querySelector('.layout-wrapper');
|
|
|
|
// Check if the element exists
|
|
if (layoutWrapper) {
|
|
// Remove the class
|
|
layoutWrapper.classList.remove('regbg');
|
|
}
|
|
});
|
|
const verifyCode = async (step, text) => {
|
|
const code = verificationCode.value.join('');
|
|
console.log('Verifying code:', code);
|
|
console.log(currentUserRegister.value)
|
|
let user_id = localStorage.getItem('register_provider_id')
|
|
let codeVerify = await axios.post(`/agent/verify-email/${user_id}`, {
|
|
token: Number(code),
|
|
|
|
}).then(r => {
|
|
if (r.data.message == "Account verified") {
|
|
localStorage.setItem('step-register', step)
|
|
currentStep.value = step
|
|
}
|
|
}).catch(error => {
|
|
if (error.response && error.response.data.message == 'already verified') {
|
|
getIsTonalSnackbarVisibleError.value = true;
|
|
errorMessage.value = 'Otp not match';
|
|
}
|
|
})
|
|
|
|
|
|
|
|
};
|
|
|
|
const registerAgent = async () => {
|
|
isLoadingVisible.value = true;
|
|
await axios.post('/agent/registerPost', {
|
|
|
|
first_name: first_name.value,
|
|
last_name: last_name.value,
|
|
email: email.value,
|
|
password: password.value,
|
|
|
|
|
|
}).then(r => {
|
|
console.log(r.data);
|
|
verfyEmail.value = true
|
|
isLoadingVisible.value = false;
|
|
user.value = r.data.user
|
|
localStorage.setItem('register_provider_id', r.data.user.id)
|
|
// getIsTonalSnackbarVisible.value = true;
|
|
//successMessage.value = r.data.message
|
|
// email.value = null
|
|
// phone.value = null
|
|
// password.value = null
|
|
//name.value = null
|
|
// home_address.value = null
|
|
// medical_license_number.value = null
|
|
// years_of_experience.value = null
|
|
// gender.value = null
|
|
// specialty.value = null
|
|
// gender.value = null
|
|
//router.push('/provider/thank-you')
|
|
// localStorage.setItem('access_token', r.data.access_token)
|
|
// localStorage.setItem('agent_id', r.data.data.id)
|
|
// localStorage.setItem('user_role', 'agent')
|
|
// localStorage.setItem('userAbilities', '[{"action":"manage","subject":"all"}]')
|
|
// const userAbilities = [{ "action": "manage", "subject": "all" }];
|
|
// ability.update(userAbilities)
|
|
// router.replace(route.query.to && route.query.to != '/agent/login' ? String(route.query.to) : '/agent/dashboard')
|
|
}).catch(error => {
|
|
inavlid.value = true;
|
|
verfyEmail.value = false
|
|
console.error("Invalid Credentials", error.response.data.message);
|
|
localStorage.setItem('step-register', 1)
|
|
if (error.response && error.response.data.message) {
|
|
const isDuplicateEntryError = /1062 Duplicate entry/.test(error.response.data.message);
|
|
if (isDuplicateEntryError) {
|
|
getIsTonalSnackbarVisibleError.value = true;
|
|
errorMessage.value = 'Email already taken!';
|
|
}
|
|
}
|
|
|
|
isLoadingVisible.value = false;
|
|
let errors = error.response.data.errors
|
|
for (let data in errors) {
|
|
InvalidCredential.value = data + ": " + errors[data];
|
|
isLoadingVisible.value = false;
|
|
getIsTonalSnackbarVisibleError.value = true;
|
|
errorMessage.value = data + ": " + errors[data];
|
|
}
|
|
|
|
|
|
});
|
|
|
|
}
|
|
const saveInformation = async () => {
|
|
let formData = {
|
|
home_address: home_address.value,
|
|
city: city.value,
|
|
state: stateAddress.value,
|
|
zip_code: zip.value,
|
|
medical_license_number: medicalLicenseNumbers.value,
|
|
years_of_experience: years_of_experience.value,
|
|
specialty: specialty.value,
|
|
gender: gender.value,
|
|
practice_state: state.value,
|
|
phone: phone.value,
|
|
availabilityFrom: availabilityFrom.value,
|
|
availabilityTo: availabilityTo.value
|
|
|
|
}
|
|
console.log(currentUserRegister.value)
|
|
|
|
isLoadingVisible.value = true;
|
|
let user_id = localStorage.getItem('register_provider_id')
|
|
await axios.post(`/agent/save-profile/${user_id}`, {
|
|
|
|
home_address: home_address.value,
|
|
city: city.value,
|
|
state: stateAddress.value,
|
|
zip_code: zip.value,
|
|
medical_license_number: medicalLicenseNumbers.value,
|
|
years_of_experience: years_of_experience.value,
|
|
specialty: specialty.value,
|
|
gender: gender.value,
|
|
practice_state: state.value,
|
|
phone: phone.value,
|
|
availabilityFrom: availabilityFrom.value,
|
|
availabilityTo: availabilityTo.value
|
|
|
|
|
|
}).then(r => {
|
|
console.log(r.data);
|
|
verfyEmail.value = true
|
|
isLoadingVisible.value = false;
|
|
localStorage.setItem('register-form-data', null)
|
|
localStorage.setItem('register_provider_id', null)
|
|
localStorage.setItem('step-register', 1)
|
|
localStorage.setItem('thank-you-page', 'yes')
|
|
// getIsTonalSnackbarVisible.value = true;
|
|
//successMessage.value = r.data.message
|
|
// email.value = null
|
|
// phone.value = null
|
|
// password.value = null
|
|
//name.value = null
|
|
// home_address.value = null
|
|
// medical_license_number.value = null
|
|
// years_of_experience.value = null
|
|
// gender.value = null
|
|
// specialty.value = null
|
|
// gender.value = null
|
|
router.push('/provider/thank-you')
|
|
// localStorage.setItem('access_token', r.data.access_token)
|
|
// localStorage.setItem('agent_id', r.data.data.id)
|
|
// localStorage.setItem('user_role', 'agent')
|
|
// localStorage.setItem('userAbilities', '[{"action":"manage","subject":"all"}]')
|
|
// const userAbilities = [{ "action": "manage", "subject": "all" }];
|
|
// ability.update(userAbilities)
|
|
// router.replace(route.query.to && route.query.to != '/agent/login' ? String(route.query.to) : '/agent/dashboard')
|
|
}).catch(error => {
|
|
inavlid.value = true;
|
|
verfyEmail.value = false
|
|
console.error("Invalid Credentials", error.response.data.message);
|
|
if (error.response && error.response.data.message) {
|
|
const isDuplicateEntryError = /1062 Duplicate entry/.test(error.response.data.message);
|
|
if (isDuplicateEntryError) {
|
|
getIsTonalSnackbarVisibleError.value = true;
|
|
errorMessage.value = 'Email already taken!';
|
|
}
|
|
}
|
|
|
|
isLoadingVisible.value = false;
|
|
let errors = error.response.data.errors
|
|
for (let data in errors) {
|
|
InvalidCredential.value = data + ": " + errors[data];
|
|
isLoadingVisible.value = false;
|
|
getIsTonalSnackbarVisibleError.value = true;
|
|
errorMessage.value = data + ": " + errors[data];
|
|
}
|
|
|
|
|
|
});
|
|
|
|
}
|
|
const reSendCode = async () => {
|
|
isLoadingVisible.value = true;
|
|
let user_id = localStorage.getItem('register_provider_id')
|
|
let codeVerify = await axios.post(`/agent/resend-code/${user_id}`, {}).then(r => {
|
|
console.log(r.data)
|
|
isLoadingVisible.value = false;
|
|
getIsTonalSnackbarVisible.value = true
|
|
successMessage.value = r.data.message
|
|
}).catch(error => {
|
|
console.log(error)
|
|
isLoadingVisible.value = false;
|
|
})
|
|
}
|
|
|
|
const verificationFields = ref([])
|
|
const handleInput = (index, event) => {
|
|
const inputValue = event.target.value.replace(/\D/g, '')
|
|
const sanitizedValue = inputValue.slice(0, 1)
|
|
|
|
verificationCode.value[index] = sanitizedValue
|
|
|
|
if (sanitizedValue && index < verificationCode.value.length - 1) {
|
|
const nextField = verificationFields.value[index + 1].$el.querySelector('input')
|
|
nextField.focus()
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<VSnackbar v-model="getIsTonalSnackbarVisibleError" :timeout="15000" location="top end" variant="flat" color="red">
|
|
{{ errorMessage }}
|
|
</VSnackbar>
|
|
<VSnackbar v-model="getIsTonalSnackbarVisible" :timeout="5000" location="top end" variant="flat" color="green">
|
|
{{ successMessage }}
|
|
</VSnackbar>
|
|
<div class="auth-wrapper d-flex align-center justify-center pa-4">
|
|
<VCard class="auth-card pa-2 rounded-5 regbx" max-width="600">
|
|
<VCardItem class="justify-center">
|
|
<VCardTitle class="text-2xl font-weight-bold text-primary">
|
|
<VImg :src='seetingPlanLogo' width="250" height="50" class="logo-img" />
|
|
</VCardTitle>
|
|
<VDialog v-model="isLoadingVisible" 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>
|
|
</VCardItem>
|
|
<VCardText>
|
|
|
|
|
|
<VForm ref="refVForm" @submit.prevent="onSubmit">
|
|
<VRow>
|
|
<VCol cols="12">
|
|
<!-- <v-alert v-if="inavlid" :text=InvalidCredential type="error"></v-alert> -->
|
|
</VCol>
|
|
<VRow class="bg-white" v-if="currentStep === 1">
|
|
<VCol cols="12" class="d-flex align-center text-center">
|
|
<VIcon icon="mdi-lock" size="30" class="mr-2" />
|
|
<h4 class="section-title">Basic Information</h4>
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="first_name" label="First Name" type="name"
|
|
:rules="[requiredFirstName]" :error-messages="errors.first_name"
|
|
density="comfortable" />
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="last_name" label="Last Name" type="name"
|
|
:rules="[requiredLastName]" :error-messages="errors.last_name"
|
|
density="comfortable" />
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="email" label="Email" type="email"
|
|
:rules="[requiredEmail, emailValidator]" :error-messages="errors.email"
|
|
density="comfortable" />
|
|
</VCol>
|
|
|
|
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="password" label="Password" placeholder="············"
|
|
:rules="[requiredPassword]" :type="isPasswordVisible ? 'text' : 'password'"
|
|
:append-inner-icon="isPasswordVisible ? 'bx-show' : 'bx-hide'"
|
|
@click:append-inner="isPasswordVisible = !isPasswordVisible"
|
|
density="comfortable" />
|
|
</VCol>
|
|
|
|
<VCol class="text-center" cols="12">
|
|
|
|
<VBtn color="rgb(var(--v-theme-yellow-theme-button))"
|
|
class="text-center text-white px-5" @click="validateAndProceed(2, 'verification')">
|
|
Next</VBtn>
|
|
</VCol>
|
|
|
|
</VRow>
|
|
<VRow v-if="currentStep === 2" class=" text-center bg-white">
|
|
<VCol>
|
|
<VRow class="verfication_row">
|
|
<h3>Kindly input the four-digit verification code that was sent to you via email.
|
|
</h3>
|
|
|
|
<v-col cols="3" v-for="(digit, index) in verificationCode" :key="index">
|
|
<v-text-field v-model="verificationCode[index]" maxlength="1" type="number"
|
|
min="0" max="9" outlined dense required class="verification-field"
|
|
@input="handleInput(index, $event)" ref="verificationFields"></v-text-field>
|
|
</v-col>
|
|
<VCol cols="12">
|
|
<VBtn @click="verifyCode(3, 'verfication')"
|
|
color="rgb(var(--v-theme-yellow-theme-button))" class="text-white">
|
|
Verify
|
|
</VBtn>
|
|
</VCol>
|
|
</VRow>
|
|
</VCol>
|
|
</VRow>
|
|
<VRow class="bg-white" v-if="currentStep === 3">
|
|
<VCol cols="12" class="d-flex align-center text-center">
|
|
<VIcon icon="mdi-account-circle" size="32" class="mr-2" />
|
|
<h4 class="section-title">Personal Information</h4>
|
|
</VCol>
|
|
<VCol cols="12" md="12">
|
|
<VTextField v-model="home_address" label="Home Address" :rules="[requiredAddress]"
|
|
:error-messages="errors.home_address" density="comfortable" />
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="city" label="City" density="comfortable" :rules="[requiredCity]"
|
|
:error-messages="errors.city" />
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
|
|
<v-autocomplete clearable v-model="stateAddress" label="State" density="comfortable"
|
|
:items="sortedStates" item-title="name" item-value="abbreviation"
|
|
:rules="[requiredState]" :error-messages="errors.stateAddress">
|
|
</v-autocomplete>
|
|
</VCol>
|
|
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="zip" label="Zip" density="comfortable" :rules="[requiredZip]"
|
|
:error-messages="errors.zip" />
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="phone" label="Phone Number" pattern="^\(\d{3}\) \d{3}-\d{4}$"
|
|
:rules="[requiredPhone, validUSAPhone]" :error-messages="errors.phone"
|
|
placeholder="i.e. (000) 000-0000" @input="formatPhoneNumber" max="14"
|
|
density="comfortable" />
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<VSelect v-model="gender" label="Gender" :items="genders" :rules="[requiredGender]"
|
|
:error-messages="errors.gender" item-title="title" item-value="value"
|
|
density="comfortable" />
|
|
</VCol>
|
|
<VCol class="text-center" cols="12">
|
|
<VBtn color="rgb(var(--v-theme-yellow-theme-button))"
|
|
class="text-center text-white px-5"
|
|
@click="validateAndProceed(4, 'Personal Information')" block>
|
|
Next</VBtn>
|
|
</VCol>
|
|
</VRow>
|
|
<VRow class="bg-white" v-if="currentStep === 4">
|
|
<VCol cols="12" class="d-flex align-center text-center">
|
|
<VIcon icon="mdi-briefcase" size="32" class="mr-2" />
|
|
<h4 class="section-title">Professional Information</h4>
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="years_of_experience" label="Years of Experience" type="number"
|
|
:rules="[requiredYearsofExperience]" :error-messages="errors.years_of_experience"
|
|
density="comfortable" />
|
|
</VCol>
|
|
|
|
|
|
<VCol cols="12" md="6">
|
|
<VTextField v-model="specialty" label="Practice or Provider's Specialty" type="text"
|
|
:rules="[requiredSpecialty]" :error-messages="errors.specialty"
|
|
density="comfortable" />
|
|
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
|
|
<VSelect v-model="availabilityFrom" label="Availability From" :items="timeOptions"
|
|
density="comfortable" :rules="[requiredAvailability]"
|
|
:error-messages="errors.availabilityFrom" />
|
|
</VCol>
|
|
<VCol cols="12" md="6">
|
|
<!-- timeOptions.filter((time) => time > availabilityFrom) -->
|
|
<VSelect v-model="availabilityTo" label="Availability To" :items="timeOptions"
|
|
density="comfortable" :rules="[requiredAvailability]"
|
|
:error-messages="errors.availabilityTo" />
|
|
|
|
</VCol>
|
|
<VCol cols="12">
|
|
<v-select v-model="state" label="Region Currently Practicing" :items="sortedStates"
|
|
item-title="name" item-value="abbreviation" multiple :rules="[requiredState]"
|
|
:error-messages="errors.state" density="comfortable">
|
|
</v-select>
|
|
</VCol>
|
|
<!-- <VCol cols="12" md="6">
|
|
<VTextField v-model="medical_license_number"
|
|
:label="`Medical License Number for ${selectedStatesString}`" :rules="[requiredLicenseNumber]"
|
|
:error-messages="errors.medical_license_number" />
|
|
</VCol> -->
|
|
<VCol cols="12" v-if="state.length > 0">
|
|
<div class="d-flex align-center mb-4">
|
|
<VIcon icon="mdi-certificate" size="32" class="mr-2" />
|
|
<h4 class="section-title">Medical License Number</h4>
|
|
</div>
|
|
<div v-for="(stat, index) in state" :key="index">
|
|
<VTextField v-model="medicalLicenseNumbers[stat]"
|
|
:label="`${selectedStateName(stat)}`" :rules="[requiredLicenseNumber]"
|
|
density="comfortable"
|
|
:error-messages="errors[`medicalLicenseNumber_${selectedStateName(stat)}`]"
|
|
class="mb-2" />
|
|
</div>
|
|
</VCol>
|
|
|
|
<!-- email -->
|
|
|
|
<VCol class="text-center px-5" cols="12">
|
|
<!-- <VBtn color="rgb(var(--v-theme-yellow))" @click="currentStep = 3" class="mb-3" style="background-color: rgb(var(--v-theme-yellow)) !important"
|
|
block>Back</VBtn> -->
|
|
|
|
<VBtn type=" submit" style="background-color: rgb(var(--v-theme-yellow-theme-button)) !important;"
|
|
block>
|
|
Register
|
|
</VBtn>
|
|
</VCol>
|
|
|
|
|
|
|
|
</VRow>
|
|
<VCol cols="12" class="text-center text-base px-0 py-0 mb-0 mt-7 text-yellow-theme-button"
|
|
v-if="currentStep === 1">
|
|
<span> Already have an account? </span>
|
|
<RouterLink class="text-yellow-theme-button" to="/provider/login"
|
|
style="text-decoration: underline;">
|
|
Login
|
|
</RouterLink>
|
|
</VCol>
|
|
<VCol cols="12" class="text-center text-base px-0 py-0 mb-0 mt-7 text-yellow-theme-button"
|
|
v-if="currentStep === 2">
|
|
<span> Didn't received code </span>
|
|
<RouterLink class="text-yellow-theme-button" @click.prevent="reSendCode" to="#"
|
|
style="text-decoration: underline;">
|
|
Send Again
|
|
</RouterLink>
|
|
</VCol>
|
|
</VRow>
|
|
</VForm>
|
|
|
|
</VCardText>
|
|
</VCard>
|
|
|
|
</div>
|
|
</template>
|
|
<style lang="scss">
|
|
@use "@core/scss/template/pages/page-auth.scss";
|
|
|
|
.regbg {
|
|
background-image: url('/assets/images/reg_bg.png');
|
|
background-size: cover;
|
|
background-repeat: no-repeat;
|
|
}
|
|
|
|
.regbx {
|
|
background-color: rgb(var(--v-theme-yellow));
|
|
box-shadow: 0px 0px 10px #ccc;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.error-message {
|
|
color: #ff2f2f;
|
|
font-size: 15px;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.verification-field[type="number"]::-webkit-inner-spin-button,
|
|
.verification-field[type="number"]::-webkit-outer-spin-button {
|
|
-webkit-appearance: none;
|
|
margin: 0;
|
|
}
|
|
|
|
input::-webkit-outer-spin-button,
|
|
input::-webkit-inner-spin-button {
|
|
-webkit-appearance: none;
|
|
margin: 0;
|
|
}
|
|
|
|
|
|
|
|
.verfication_row {
|
|
max-width: 400px;
|
|
margin: 0 auto !important;
|
|
|
|
input {
|
|
|
|
text-align: center;
|
|
line-height: 80px;
|
|
font-size: 50px;
|
|
border: solid 1px #ccc;
|
|
box-shadow: 0 0 5px #ccc inset;
|
|
outline: none;
|
|
width: 20%;
|
|
transition: all .2s ease-in-out;
|
|
border-radius: 3px;
|
|
|
|
&:focus {
|
|
border-color: purple;
|
|
box-shadow: 0 0 5px purple inset;
|
|
}
|
|
|
|
&::selection {
|
|
background: transparent;
|
|
}
|
|
}
|
|
|
|
button {
|
|
margin: 30px 0 50px;
|
|
width: 100%;
|
|
padding: 6px;
|
|
background-color: #B85FC6;
|
|
border: none;
|
|
text-transform: uppercase;
|
|
}
|
|
}
|
|
</style>
|