mirror of
https://github.com/crater-invoice/crater.git
synced 2026-02-09 20:32:40 -05:00
init crater
This commit is contained in:
311
resources/assets/js/views/wizard/CompanyInfo.vue
Normal file
311
resources/assets/js/views/wizard/CompanyInfo.vue
Normal file
@@ -0,0 +1,311 @@
|
||||
<template>
|
||||
<div class="card-body">
|
||||
<form action="" @submit.prevent="next()">
|
||||
<!-- <div v-if="previewLogo" class="upload-logo">
|
||||
<label class="form-label">{{ $t('wizard.logo_preview') }}</label><br>
|
||||
<img v-if="previewLogo" :src="previewLogo" class="preview-logo">
|
||||
</div> -->
|
||||
<p class="form-title">{{ $t('wizard.company_info') }}</p>
|
||||
<p class="form-desc">{{ $t('wizard.company_info_desc') }}</p>
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="input-label">{{ $tc('settings.company_info.company_logo') }}</label>
|
||||
<div id="pick-avatar" class="image-upload-box">
|
||||
<img v-if="previewLogo" :src="previewLogo" class="preview-logo">
|
||||
<div v-else class="upload-content">
|
||||
<font-awesome-icon class="upload-icon" icon="cloud-upload-alt"/>
|
||||
<p class="upload-text"> {{ $t('general.choose_file') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<avatar-cropper
|
||||
:labels="{ submit: 'submit', cancel: 'Cancle'}"
|
||||
:cropper-options="cropperOptions"
|
||||
:output-options="cropperOutputOptions"
|
||||
:output-quality="0.8"
|
||||
:upload-handler="cropperHandler"
|
||||
trigger="#pick-avatar"
|
||||
@changed="setFileObject"
|
||||
/>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.company_name') }}</label><span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.companyData.name.$error"
|
||||
v-model.trim="companyData.name"
|
||||
type="text"
|
||||
name="name"
|
||||
@input="$v.companyData.name.$touch()"
|
||||
/>
|
||||
<div v-if="$v.companyData.name.$error">
|
||||
<span v-if="!$v.companyData.name.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.country') }}</label><span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="country"
|
||||
:class="{'error': $v.companyData.country_id.$error }"
|
||||
:options="countries"
|
||||
:searchable="true"
|
||||
:allow-empty="false"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('general.select_country')"
|
||||
track-by="id"
|
||||
label="name"
|
||||
@input="fetchState()"
|
||||
/>
|
||||
<div v-if="$v.companyData.country_id.$error">
|
||||
<span v-if="!$v.companyData.country_id.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.state') }}</label>
|
||||
<base-select
|
||||
v-model="state"
|
||||
:options="states"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:disabled="isDisabledState"
|
||||
:placeholder="$t('general.select_state')"
|
||||
track-by="id"
|
||||
label="name"
|
||||
@input="fetchCities"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.city') }}</label>
|
||||
<base-select
|
||||
v-model="city"
|
||||
:options="cities"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:disabled="isDisabledCity"
|
||||
:placeholder="$t('general.select_city')"
|
||||
track-by="id"
|
||||
label="name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.address') }}</label>
|
||||
<base-text-area
|
||||
v-model.trim="companyData.address_street_1"
|
||||
:placeholder="$t('general.street_1')"
|
||||
name="billing_street1"
|
||||
rows="2"
|
||||
/>
|
||||
<base-text-area
|
||||
v-model="companyData.address_street_2"
|
||||
:placeholder="$t('general.street_2')"
|
||||
name="billing_street2"
|
||||
rows="2"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">{{ $t('wizard.zip_code') }}</label>
|
||||
<base-input
|
||||
v-model.trim="companyData.zip"
|
||||
type="text"
|
||||
name="zip"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">{{ $t('wizard.phone') }}</label>
|
||||
<base-input
|
||||
v-model.trim="companyData.phone"
|
||||
type="text"
|
||||
name="phone"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('wizard.save_cont') }}
|
||||
</base-button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MultiSelect from 'vue-multiselect'
|
||||
import AvatarCropper from 'vue-avatar-cropper'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
import Ls from '../../services/ls'
|
||||
const { required, minLength, email } = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiSelect,
|
||||
AvatarCropper
|
||||
},
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
cropperOutputOptions: {
|
||||
width: 150,
|
||||
height: 150
|
||||
},
|
||||
cropperOptions: {
|
||||
autoCropArea: 1,
|
||||
viewMode: 0,
|
||||
movable: true,
|
||||
zoomable: true
|
||||
},
|
||||
companyData: {
|
||||
logo: '',
|
||||
name: null,
|
||||
address_street_1: '',
|
||||
address_street_2: '',
|
||||
city_id: '',
|
||||
state_id: '',
|
||||
country_id: '',
|
||||
zip: '',
|
||||
phone: ''
|
||||
},
|
||||
loading: false,
|
||||
step: 1,
|
||||
countries: [],
|
||||
country: null,
|
||||
states: [],
|
||||
state: null,
|
||||
cities: [],
|
||||
city: null,
|
||||
previewLogo: null,
|
||||
isDisabledCity: true,
|
||||
isDisabledState: true
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
companyData: {
|
||||
name: {
|
||||
required
|
||||
},
|
||||
country_id: {
|
||||
required
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
country ({ id }) {
|
||||
this.companyData.country_id = id
|
||||
this.state = null
|
||||
this.city = null
|
||||
if (id !== null && id !== undefined) {
|
||||
this.isDisabledState = false
|
||||
return true
|
||||
}
|
||||
this.isDisabledState = true
|
||||
return true
|
||||
},
|
||||
state (newState) {
|
||||
if (newState !== null && newState !== undefined) {
|
||||
this.city = null
|
||||
this.companyData.state_id = newState.id
|
||||
this.isDisabledCity = false
|
||||
return true
|
||||
}
|
||||
this.companyData.state_id = null
|
||||
this.isDisabledCity = true
|
||||
this.cities = []
|
||||
this.city = null
|
||||
this.companyData.city_id = null
|
||||
return true
|
||||
},
|
||||
city (newCity) {
|
||||
if (newCity !== null && newCity !== undefined) {
|
||||
this.companyData.city_id = newCity.id
|
||||
return true
|
||||
}
|
||||
this.companyData.city_id = null
|
||||
return true
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.fetchCountry()
|
||||
},
|
||||
methods: {
|
||||
cropperHandler (cropper) {
|
||||
this.previewLogo = cropper.getCroppedCanvas().toDataURL(this.cropperOutputMime)
|
||||
},
|
||||
setFileObject (file) {
|
||||
this.fileObject = file
|
||||
},
|
||||
async next () {
|
||||
this.$v.companyData.$touch()
|
||||
if (this.$v.companyData.$invalid) {
|
||||
return true
|
||||
}
|
||||
this.loading = true
|
||||
let data = new FormData()
|
||||
data.append('logo', this.fileObject)
|
||||
data.append('name', this.companyData.name)
|
||||
data.append('address_street_1', this.companyData.address_street_1)
|
||||
data.append('address_street_2', this.companyData.address_street_2)
|
||||
data.append('city_id', this.companyData.city_id)
|
||||
data.append('state_id', this.companyData.state_id)
|
||||
data.append('country_id', this.companyData.country_id)
|
||||
data.append('zip', this.companyData.zip)
|
||||
data.append('phone', this.companyData.phone)
|
||||
|
||||
let response = await window.axios.post('/api/admin/onboarding/company', data, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
|
||||
if (response.data) {
|
||||
this.$emit('next')
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
onFileChange (e) {
|
||||
var input = event.target
|
||||
this.companyData.logo = input.files[0]
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader()
|
||||
reader.onload = (e) => {
|
||||
this.previewLogo = e.target.result
|
||||
}
|
||||
reader.readAsDataURL(input.files[0])
|
||||
}
|
||||
},
|
||||
async fetchCountry () {
|
||||
let res = await window.axios.get('/api/countries')
|
||||
if (res) {
|
||||
this.countries = res.data.countries
|
||||
}
|
||||
},
|
||||
async fetchState () {
|
||||
this.$v.companyData.country_id.$touch()
|
||||
let res = await window.axios.get(`/api/states/${this.country.id}`)
|
||||
if (res) {
|
||||
this.states = res.data.states
|
||||
}
|
||||
},
|
||||
async fetchCities () {
|
||||
if (this.state === null || this.state === undefined) {
|
||||
return false
|
||||
}
|
||||
let res = await window.axios.get(`/api/cities/${this.state.id}`)
|
||||
if (res) {
|
||||
this.cities = res.data.cities
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
216
resources/assets/js/views/wizard/Database.vue
Normal file
216
resources/assets/js/views/wizard/Database.vue
Normal file
@@ -0,0 +1,216 @@
|
||||
<template>
|
||||
<div class="card-body">
|
||||
<form action="" @submit.prevent="next()">
|
||||
<p class="form-title">{{ $t('wizard.database.database') }}</p>
|
||||
<p class="form-desc">{{ $t('wizard.database.desc') }}</p>
|
||||
<div class="row mt-5">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.database.app_url') }}</label>
|
||||
<span class="text-danger"> * </span>
|
||||
<base-input
|
||||
:invalid="$v.databaseData.app_url.$error"
|
||||
v-model.trim="databaseData.app_url"
|
||||
type="text"
|
||||
name="name"
|
||||
@input="$v.databaseData.app_url.$touch()"
|
||||
/>
|
||||
<div v-if="$v.databaseData.app_url.$error">
|
||||
<span v-if="!$v.databaseData.app_url.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
<span v-if="!$v.databaseData.app_url.url" class="text-danger">
|
||||
{{ $tc('validation.invalid_url') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.database.connection') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="databaseData.database_connection"
|
||||
:invalid="$v.databaseData.database_connection.$error"
|
||||
:options="connections"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
@change="$v.databaseData.database_connection.$touch()"
|
||||
/>
|
||||
<div v-if="$v.databaseData.database_connection.$error">
|
||||
<span v-if="!$v.databaseData.database_connection.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.database.port') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.databaseData.database_port.$error"
|
||||
v-model.trim="databaseData.database_port"
|
||||
type="text"
|
||||
name="database_port"
|
||||
@input="$v.databaseData.database_port.$touch()"
|
||||
/>
|
||||
<div v-if="$v.databaseData.database_port.$error">
|
||||
<span v-if="!$v.databaseData.database_port.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
<span v-if="!$v.databaseData.database_port.numeric" class="text-danger">
|
||||
{{ $tc('validation.numbers_only') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.database.db_name') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.databaseData.database_name.$error"
|
||||
v-model.trim="databaseData.database_name"
|
||||
type="text"
|
||||
name="database_name"
|
||||
@input="$v.databaseData.database_name.$touch()"
|
||||
/>
|
||||
<div v-if="$v.databaseData.database_name.$error">
|
||||
<span v-if="!$v.databaseData.database_name.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.database.username') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.databaseData.database_username.$error"
|
||||
v-model.trim="databaseData.database_username"
|
||||
type="text"
|
||||
name="database_username"
|
||||
@input="$v.databaseData.database_username.$touch()"
|
||||
/>
|
||||
<div v-if="$v.databaseData.database_username.$error">
|
||||
<span v-if="!$v.databaseData.database_username.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.database.password') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
v-model.trim="databaseData.database_password"
|
||||
type="password"
|
||||
name="name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.database.host') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.databaseData.database_hostname.$error"
|
||||
v-model.trim="databaseData.database_hostname"
|
||||
type="text"
|
||||
name="database_hostname"
|
||||
@input="$v.databaseData.database_hostname.$touch()"
|
||||
/>
|
||||
<div v-if="$v.databaseData.database_hostname.$error">
|
||||
<span v-if="!$v.databaseData.database_hostname.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-5"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('wizard.save_cont') }}
|
||||
</base-button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MultiSelect from 'vue-multiselect'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
const { required, numeric, url } = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiSelect
|
||||
},
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
databaseData: {
|
||||
database_connection: 'mysql',
|
||||
database_hostname: '127.0.0.1',
|
||||
database_port: '3306',
|
||||
database_name: null,
|
||||
database_username: null,
|
||||
database_password: null,
|
||||
app_url: null
|
||||
},
|
||||
loading: false,
|
||||
connections: [
|
||||
'sqlite',
|
||||
'mysql',
|
||||
'pgsql',
|
||||
'sqlsrv'
|
||||
]
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
databaseData: {
|
||||
database_connection: {
|
||||
required
|
||||
},
|
||||
database_hostname: {
|
||||
required
|
||||
},
|
||||
database_port: {
|
||||
required,
|
||||
numeric
|
||||
},
|
||||
database_name: {
|
||||
required
|
||||
},
|
||||
database_username: {
|
||||
required
|
||||
},
|
||||
app_url: {
|
||||
required,
|
||||
url
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async next () {
|
||||
this.$v.databaseData.$touch()
|
||||
if (this.$v.databaseData.$invalid) {
|
||||
return true
|
||||
}
|
||||
this.loading = true
|
||||
try {
|
||||
let response = await window.axios.post('/api/admin/onboarding/environment/database', this.databaseData)
|
||||
if (response.data.success) {
|
||||
this.$emit('next')
|
||||
window.toastr['success'](this.$t('wizard.success.' + response.data.success))
|
||||
return true
|
||||
} else {
|
||||
window.toastr['error'](this.$t('wizard.errors.' + response.data.error))
|
||||
}
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
window.toastr['error']('Somethig went wrong')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
208
resources/assets/js/views/wizard/EmailConfiguration.vue
Normal file
208
resources/assets/js/views/wizard/EmailConfiguration.vue
Normal file
@@ -0,0 +1,208 @@
|
||||
<template>
|
||||
<div class="card-body">
|
||||
<form action="" @submit.prevent="next()">
|
||||
<p class="form-title">{{ $t('wizard.mail.mail_config') }}</p>
|
||||
<p class="form-desc">{{ $t('wizard.mail.mail_config_desc') }}</p>
|
||||
<div class="row my-2 mt-5">
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('wizard.mail.driver') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="mailConfigData.mail_driver"
|
||||
:invalid="$v.mailConfigData.mail_driver.$error"
|
||||
:options="mail_drivers"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
@change="$v.mailConfigData.mail_driver.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_driver.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_driver.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('wizard.mail.host') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_host.$error"
|
||||
v-model.trim="mailConfigData.mail_host"
|
||||
type="text"
|
||||
name="mail_host"
|
||||
@input="$v.mailConfigData.mail_host.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_host.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_host.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('wizard.mail.username') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_username.$error"
|
||||
v-model.trim="mailConfigData.mail_username"
|
||||
type="text"
|
||||
name="db_name"
|
||||
@input="$v.mailConfigData.mail_username.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_username.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_username.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('wizard.mail.password') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_password.$error"
|
||||
v-model.trim="mailConfigData.mail_password"
|
||||
type="mail_password"
|
||||
name="name"
|
||||
@input="$v.mailConfigData.mail_password.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_password.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_password.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('wizard.mail.port') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_port.$error"
|
||||
v-model.trim="mailConfigData.mail_port"
|
||||
type="text"
|
||||
name="mail_port"
|
||||
@input="$v.mailConfigData.mail_port.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_port.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_port.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
<span v-if="!$v.mailConfigData.mail_port.numeric" class="text-danger">
|
||||
{{ $tc('validation.numbers_only') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('wizard.mail.encryption') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_encryption.$error"
|
||||
v-model.trim="mailConfigData.mail_encryption"
|
||||
type="text"
|
||||
name="name"
|
||||
@input="$v.mailConfigData.mail_encryption.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_encryption.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_encryption.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-5"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('wizard.save_cont') }}
|
||||
</base-button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MultiSelect from 'vue-multiselect'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
import Ls from '../../services/ls'
|
||||
const { required, email, numeric } = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiSelect
|
||||
},
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
mailConfigData: {
|
||||
mail_driver: 'smtp',
|
||||
mail_host: 'mailtrap.io',
|
||||
mail_port: 2525,
|
||||
mail_username: 'cc3c64516febd4',
|
||||
mail_password: 'e6a0176301f587',
|
||||
mail_encryption: 'tls'
|
||||
},
|
||||
loading: false,
|
||||
mail_drivers: []
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
mailConfigData: {
|
||||
mail_driver: {
|
||||
required
|
||||
},
|
||||
mail_host: {
|
||||
required
|
||||
},
|
||||
mail_port: {
|
||||
required,
|
||||
numeric
|
||||
},
|
||||
mail_username: {
|
||||
required
|
||||
},
|
||||
mail_password: {
|
||||
required
|
||||
},
|
||||
mail_encryption: {
|
||||
required
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getMailDrivers()
|
||||
},
|
||||
methods: {
|
||||
async getMailDrivers () {
|
||||
this.loading = true
|
||||
|
||||
let response = await window.axios.get('/api/admin/onboarding/environment/mail')
|
||||
|
||||
if (response.data) {
|
||||
this.mail_drivers = response.data
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async next () {
|
||||
this.$v.mailConfigData.$touch()
|
||||
if (this.$v.mailConfigData.$invalid) {
|
||||
return true
|
||||
}
|
||||
this.loading = true
|
||||
try {
|
||||
let response = await window.axios.post('/api/admin/onboarding/environment/mail', this.mailConfigData)
|
||||
if (response.data.success) {
|
||||
this.$emit('next')
|
||||
window.toastr['success'](this.$t('wizard.success.' + response.data.success))
|
||||
} else {
|
||||
window.toastr['error'](this.$t('wizard.errors.' + response.data.error))
|
||||
}
|
||||
this.loading = false
|
||||
return true
|
||||
} catch (e) {
|
||||
window.toastr['error']('Somethig went wrong')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
115
resources/assets/js/views/wizard/Index.vue
Normal file
115
resources/assets/js/views/wizard/Index.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div class="wizard">
|
||||
<div class="step-indicator">
|
||||
<img
|
||||
id="logo-crater"
|
||||
src="/assets/img/crater-logo.png"
|
||||
alt="Crater Logo"
|
||||
width="225"
|
||||
height="50"
|
||||
class="logo"
|
||||
>
|
||||
<div class="indicator-line">
|
||||
<div class="center">
|
||||
<div class="steps" :class="{'active': step === 1, 'completed': step > 1}">
|
||||
<font-awesome-icon v-if="step > 1" icon="check" class="icon-check"/>
|
||||
</div>
|
||||
<div class="steps" :class="{'active': step === 2, 'completed': step > 2}">
|
||||
<font-awesome-icon v-if="step > 2" icon="check" class="icon-check"/>
|
||||
</div>
|
||||
<div class="steps" :class="{'active': step === 3, 'completed': step > 3}">
|
||||
<font-awesome-icon v-if="step > 3" icon="check" class="icon-check"/>
|
||||
</div>
|
||||
<div class="steps" :class="{'active': step === 4, 'completed': step > 4}">
|
||||
<font-awesome-icon v-if="step > 4" icon="check" class="icon-check"/>
|
||||
</div>
|
||||
<div class="steps" :class="{'active': step === 5, 'completed': step > 5}">
|
||||
<font-awesome-icon v-if="step > 5" icon="check" class="icon-check"/>
|
||||
</div>
|
||||
<div class="steps" :class="{'active': step === 6, 'completed': step > 6}">
|
||||
<font-awesome-icon v-if="step > 6" icon="check" class="icon-check"/>
|
||||
</div>
|
||||
<div class="steps" :class="{'active': step === 7, 'completed': step > 7}">
|
||||
<font-awesome-icon v-if="step > 7" icon="check" class="icon-check"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-content">
|
||||
<div class="card wizard-card">
|
||||
<component
|
||||
:is="tab"
|
||||
@next="setTab"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import SystemRequirement from './SystemRequirement'
|
||||
import Permission from './Permission'
|
||||
import Database from './Database'
|
||||
import EmailConfiguration from './EmailConfiguration'
|
||||
import UserProfile from './UserProfile'
|
||||
import CompanyInfo from './CompanyInfo'
|
||||
import Settings from './Settings'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
step_1: SystemRequirement,
|
||||
step_2: Permission,
|
||||
step_3: Database,
|
||||
step_4: EmailConfiguration,
|
||||
step_5: UserProfile,
|
||||
step_6: CompanyInfo,
|
||||
step_7: Settings
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
tab: 'step_1',
|
||||
step: 1
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getOnboardingData()
|
||||
},
|
||||
methods: {
|
||||
async getOnboardingData () {
|
||||
let response = await window.axios.get('/api/admin/onboarding')
|
||||
if (response.data) {
|
||||
if (response.data.profile_complete === 'COMPLETED') {
|
||||
this.$router.push('/admin/dashboard')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let dbStep = parseInt(response.data.profile_complete)
|
||||
|
||||
if (dbStep) {
|
||||
this.step = dbStep + 1
|
||||
this.tab = `step_${dbStep + 1}`
|
||||
}
|
||||
|
||||
this.languages = response.data.languages
|
||||
this.currencies = response.data.currencies
|
||||
this.dateFormats = response.data.date_formats
|
||||
this.timeZones = response.data.time_zones
|
||||
|
||||
// this.settingData.currency = this.currencies.find(currency => currency.id === 1)
|
||||
// this.settingData.language = this.languages.find(language => language.code === 'en')
|
||||
// this.settingData.dateFormat = this.dateFormats.find(dateFormat => dateFormat.value === 'd M Y')
|
||||
}
|
||||
},
|
||||
setTab (data) {
|
||||
this.step++
|
||||
|
||||
if (this.step <= 7) {
|
||||
this.tab = 'step_' + this.step
|
||||
} else {
|
||||
// window.location.reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
69
resources/assets/js/views/wizard/Permission.vue
Normal file
69
resources/assets/js/views/wizard/Permission.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="card-body permissions">
|
||||
<p class="form-title">{{ $t('wizard.permissions.permissions') }}</p>
|
||||
<p class="form-desc">{{ $t('wizard.permissions.permission_desc') }}</p>
|
||||
<div class="d-flex justify-content-start">
|
||||
<div class="lists col-md-6">
|
||||
<div
|
||||
v-for="(permission, index) in permissions"
|
||||
:key="index"
|
||||
class="row list-items"
|
||||
>
|
||||
|
||||
<div class="col-sm-9 left-item">
|
||||
{{ permission.folder }}
|
||||
</div>
|
||||
<div class="col-sm-3 right-item">
|
||||
<span v-if="permission.isSet" class="verified"/>
|
||||
<span v-else class="not-verified"/>
|
||||
<span>{{ permission.permission }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
v-if="!errors"
|
||||
class="pull-right mt-5"
|
||||
icon="arrow-right"
|
||||
right-icon
|
||||
color="theme"
|
||||
@click="next"
|
||||
>
|
||||
{{ $t('wizard.continue') }}
|
||||
</base-button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Ls from '../../services/ls'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
permissions: [],
|
||||
errors: false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getPermissions()
|
||||
},
|
||||
methods: {
|
||||
async getPermissions () {
|
||||
this.loading = true
|
||||
|
||||
let response = await window.axios.get('/api/admin/onboarding/permissions', this.profileData)
|
||||
|
||||
if (response.data) {
|
||||
this.permissions = response.data.permissions.permissions
|
||||
this.errors = response.data.permissions.errors
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async next () {
|
||||
this.loading = true
|
||||
await this.$emit('next')
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
209
resources/assets/js/views/wizard/Settings.vue
Normal file
209
resources/assets/js/views/wizard/Settings.vue
Normal file
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<div class="card-body">
|
||||
<form action="" @submit.prevent="next()">
|
||||
<p class="form-title">{{ $t('wizard.preferences') }}</p>
|
||||
<p class="form-desc">{{ $t('wizard.preferences_desc') }}</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.currency') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="settingData.currency"
|
||||
:class="{'error': $v.settingData.currency.$error }"
|
||||
:options="currencies"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('settings.currencies.select_currency')"
|
||||
track-by="id"
|
||||
label="name"
|
||||
@input="$v.settingData.currency.$touch()"
|
||||
/>
|
||||
<div v-if="$v.settingData.currency.$error">
|
||||
<span v-if="!$v.settingData.currency.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.language') }}</label><span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="settingData.language"
|
||||
:class="{'error': $v.settingData.language.$error }"
|
||||
:options="languages"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('settings.preferences.select_language')"
|
||||
label="name"
|
||||
@input="$v.settingData.language.$touch()"
|
||||
/>
|
||||
<div v-if="$v.settingData.language.$error">
|
||||
<span v-if="!$v.settingData.language.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.date_format') }}</label><span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="settingData.dateFormat"
|
||||
:class="{'error': $v.settingData.dateFormat.$error }"
|
||||
:options="dateFormats"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('settings.preferences.select_date_formate')"
|
||||
label="display_date"
|
||||
@input="$v.settingData.dateFormat.$touch()"
|
||||
/>
|
||||
<div v-if="$v.settingData.dateFormat.$error">
|
||||
<span v-if="!$v.settingData.dateFormat.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.time_zone') }}</label><span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="settingData.timeZone"
|
||||
:class="{'error': $v.settingData.timeZone.$error }"
|
||||
:options="timeZones"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('settings.preferences.select_date_formate')"
|
||||
label="key"
|
||||
@input="$v.settingData.timeZone.$touch()"
|
||||
/>
|
||||
<div v-if="$v.settingData.timeZone.$error">
|
||||
<span v-if="!$v.settingData.timeZone.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.fiscal_year') }}</label><span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="settingData.fiscalYear"
|
||||
:class="{'error': $v.settingData.fiscalYear.$error }"
|
||||
:options="fiscalYears"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('settings.preferences.select_financial_year')"
|
||||
label="key"
|
||||
@input="$v.settingData.fiscalYear.$touch()"
|
||||
/>
|
||||
<div v-if="$v.settingData.fiscalYear.$error">
|
||||
<span v-if="!$v.settingData.fiscalYear.required" class="text-danger">{{ $tc('customers.errors.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button :loading="loading" class="pull-right" icon="save" color="theme" type="submit">
|
||||
{{ $t('wizard.save_cont') }}
|
||||
</base-button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MultiSelect from 'vue-multiselect'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
import Ls from '../../services/ls'
|
||||
const { required, minLength, email } = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiSelect
|
||||
},
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
settingData: {
|
||||
language: null,
|
||||
currency: null,
|
||||
timeZone: null,
|
||||
dateFormat: null,
|
||||
fiscalYear: null
|
||||
},
|
||||
loading: false,
|
||||
step: 1,
|
||||
languages: [],
|
||||
currencies: [],
|
||||
timeZones: [],
|
||||
dateFormats: [],
|
||||
fiscalYears: []
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
settingData: {
|
||||
currency: {
|
||||
required
|
||||
},
|
||||
language: {
|
||||
required
|
||||
},
|
||||
dateFormat: {
|
||||
required
|
||||
},
|
||||
timeZone: {
|
||||
required
|
||||
},
|
||||
fiscalYear: {
|
||||
required
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getOnboardingData()
|
||||
},
|
||||
methods: {
|
||||
async getOnboardingData () {
|
||||
let response = await window.axios.get('/api/admin/onboarding')
|
||||
if (response.data) {
|
||||
if (response.data.profile_complete === 'COMPLETED') {
|
||||
this.$router.push('/admin/dashboard')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let dbStep = parseInt(response.data.profile_complete)
|
||||
|
||||
if (dbStep) {
|
||||
this.step = dbStep + 1
|
||||
}
|
||||
|
||||
this.languages = response.data.languages
|
||||
this.currencies = response.data.currencies
|
||||
this.dateFormats = response.data.date_formats
|
||||
this.timeZones = response.data.time_zones
|
||||
this.fiscalYears = response.data.fiscal_years
|
||||
|
||||
this.settingData.currency = this.currencies.find(currency => currency.id === 1)
|
||||
this.settingData.language = this.languages.find(language => language.code === 'en')
|
||||
this.settingData.dateFormat = response.data.date_formats.find(dateFormat => dateFormat.carbon_format_value == 'd M Y')
|
||||
this.settingData.timeZone = this.timeZones.find(timeZone => timeZone.value === 'UTC')
|
||||
this.settingData.fiscalYear = this.fiscalYears.find(fiscalYear => fiscalYear.value === '1-12')
|
||||
}
|
||||
},
|
||||
async next () {
|
||||
this.$v.settingData.$touch()
|
||||
|
||||
if (this.$v.settingData.$invalid) {
|
||||
return true
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
|
||||
let data = {
|
||||
currency: this.settingData.currency.id,
|
||||
time_zone: this.settingData.timeZone.value,
|
||||
language: this.settingData.language.code,
|
||||
fiscal_year: this.settingData.fiscalYear.value,
|
||||
carbon_date_format: this.settingData.dateFormat.carbon_format_value,
|
||||
moment_date_format: this.settingData.dateFormat.moment_format_value
|
||||
}
|
||||
|
||||
let response = await window.axios.post('/api/admin/onboarding/settings', data)
|
||||
|
||||
if (response.data) {
|
||||
// this.$emit('next')
|
||||
this.loading = false
|
||||
Ls.set('auth.token', response.data.token)
|
||||
this.$router.push('/admin/dashboard')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
99
resources/assets/js/views/wizard/SystemRequirement.vue
Normal file
99
resources/assets/js/views/wizard/SystemRequirement.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div class="card-body">
|
||||
<p class="form-title">{{ $t('wizard.req.system_req') }}</p>
|
||||
<p class="form-desc">{{ $t('wizard.req.system_req_desc') }}</p>
|
||||
<div v-if="phpSupportInfo" class="d-flex justify-content-start">
|
||||
<div class="col-md-6">
|
||||
<div class="row list-items">
|
||||
<div class="col-md-9 left-item">
|
||||
{{ $t('wizard.req.php_req_version', { version: phpSupportInfo.minimum }) }}
|
||||
</div>
|
||||
<div class="col-md-3 right-item justify-content-end">
|
||||
{{ phpSupportInfo.current }}
|
||||
<span v-if="phpSupportInfo.supported" class="verified"/>
|
||||
<span v-else class="not-verified"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="requirements" class="d-flex justify-content-start">
|
||||
<div class="col-md-6">
|
||||
<div
|
||||
v-for="(requirement, index) in requirements"
|
||||
:key="index"
|
||||
class="row list-items"
|
||||
>
|
||||
|
||||
<div class="col-md-9 left-item">
|
||||
{{ index }}
|
||||
</div>
|
||||
<div class="col-md-3 right-item justify-content-end">
|
||||
<span v-if="requirement" class="verified"/>
|
||||
<span v-else class="not-verified"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
v-if="requirements"
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="arrow-right"
|
||||
color="theme"
|
||||
right-icon
|
||||
@click="next"
|
||||
>
|
||||
{{ $t('wizard.continue') }}
|
||||
</base-button>
|
||||
<base-button
|
||||
v-else
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
color="theme"
|
||||
@click="getRequirements"
|
||||
>
|
||||
{{ $t('wizard.req.check_req') }}
|
||||
</base-button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MultiSelect from 'vue-multiselect'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
import Ls from '../../services/ls'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiSelect
|
||||
},
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
requirements: null,
|
||||
phpSupportInfo: null,
|
||||
loading: false,
|
||||
isShow: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
listToggle () {
|
||||
this.isShow = !this.isShow
|
||||
},
|
||||
async getRequirements () {
|
||||
this.loading = true
|
||||
|
||||
let response = await window.axios.get('/api/admin/onboarding/requirements', this.profileData)
|
||||
|
||||
if (response.data) {
|
||||
this.requirements = response.data.requirements.requirements.php
|
||||
this.phpSupportInfo = response.data.phpSupportInfo
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async next () {
|
||||
this.loading = true
|
||||
await this.$emit('next')
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
141
resources/assets/js/views/wizard/UserProfile.vue
Normal file
141
resources/assets/js/views/wizard/UserProfile.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div class="card-body">
|
||||
<form action="" @submit.prevent="next()">
|
||||
<p class="form-title">{{ $t('wizard.account_info') }}</p>
|
||||
<p class="form-desc">{{ $t('wizard.account_info_desc') }}</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.name') }}</label><span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.profileData.name.$error"
|
||||
v-model.trim="profileData.name"
|
||||
type="text"
|
||||
name="name"
|
||||
@input="$v.profileData.name.$touch()"
|
||||
/>
|
||||
<div v-if="$v.profileData.name.$error">
|
||||
<span v-if="!$v.profileData.name.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
<span v-if="!$v.profileData.name.minLength" class="text-danger"> {{ $tc('validation.name_min_length', $v.profileData.name.$params.minLength.min, { count: $v.profileData.name.$params.minLength.min }) }} </span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.email') }}</label><span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.profileData.email.$error"
|
||||
v-model.trim="profileData.email"
|
||||
type="text"
|
||||
name="email"
|
||||
@input="$v.profileData.email.$touch()"
|
||||
/>
|
||||
<div v-if="$v.profileData.email.$error">
|
||||
<span v-if="!$v.profileData.email.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
<span v-if="!$v.profileData.email.email" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.password') }}</label><span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.profileData.password.$error"
|
||||
v-model.trim="profileData.password"
|
||||
type="password"
|
||||
name="password"
|
||||
@input="$v.profileData.password.$touch()"
|
||||
/>
|
||||
<div v-if="$v.profileData.password.$error">
|
||||
<span v-if="!$v.profileData.password.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ $t('wizard.confirm_password') }}</label><span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.profileData.confirm_password.$error"
|
||||
v-model.trim="profileData.confirm_password"
|
||||
type="password"
|
||||
name="confirm_password"
|
||||
@input="$v.profileData.confirm_password.$touch()"
|
||||
/>
|
||||
<div v-if="$v.profileData.confirm_password.$error">
|
||||
<span v-if="!$v.profileData.confirm_password.sameAsPassword" class="text-danger">{{ $tc('validation.password_incorrect') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-4"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('wizard.save_cont') }}
|
||||
</base-button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MultiSelect from 'vue-multiselect'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
import Ls from '../../services/ls'
|
||||
const { required, requiredIf, sameAs, minLength, email } = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiSelect
|
||||
},
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
profileData: {
|
||||
name: null,
|
||||
email: null,
|
||||
password: null,
|
||||
confirm_password: null
|
||||
},
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
profileData: {
|
||||
name: {
|
||||
required,
|
||||
minLength: minLength(3)
|
||||
},
|
||||
email: {
|
||||
email,
|
||||
required
|
||||
},
|
||||
password: {
|
||||
required
|
||||
},
|
||||
confirm_password: {
|
||||
required: requiredIf('isRequired'),
|
||||
sameAsPassword: sameAs('password')
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isRequired () {
|
||||
if (this.profileData.password === null || this.profileData.password === undefined || this.profileData.password === '') {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async next () {
|
||||
this.$v.profileData.$touch()
|
||||
if (this.$v.profileData.$invalid) {
|
||||
return true
|
||||
}
|
||||
this.loading = true
|
||||
let response = await window.axios.post('/api/admin/onboarding/profile', this.profileData)
|
||||
if (response.data) {
|
||||
this.$emit('next')
|
||||
this.loading = false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user