mirror of
https://github.com/crater-invoice/crater.git
synced 2025-10-29 12:41:10 -04:00
build version 400
This commit is contained in:
500
resources/assets/js/components/base/modal/CustomField/Index.vue
Normal file
500
resources/assets/js/components/base/modal/CustomField/Index.vue
Normal file
@ -0,0 +1,500 @@
|
||||
<template>
|
||||
<div class="custom-field-modal">
|
||||
<form action="" @submit.prevent="submitCustomFieldData">
|
||||
<div
|
||||
class="px-8 py-8 overflow-y-auto sw-scroll sm:p-6"
|
||||
style="max-height: 600px"
|
||||
>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.name')"
|
||||
:error="nameError"
|
||||
horizontal
|
||||
required
|
||||
>
|
||||
<sw-input
|
||||
ref="name"
|
||||
:invalid="$v.formData.name.$error"
|
||||
v-model="formData.name"
|
||||
type="text"
|
||||
@input="$v.formData.name.$touch()"
|
||||
/>
|
||||
</sw-input-group>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.model')"
|
||||
:error="modalTypeError"
|
||||
class="mt-5"
|
||||
horizontal
|
||||
required
|
||||
>
|
||||
<sw-select
|
||||
v-model="formData.model_type"
|
||||
:options="modelTypes"
|
||||
:invalid="$v.formData.model_type.$error"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="false"
|
||||
@input="$v.formData.model_type.$touch()"
|
||||
/>
|
||||
</sw-input-group>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.required')"
|
||||
class="mt-5"
|
||||
horizontal
|
||||
>
|
||||
<sw-switch v-model="formData.is_required" style="margin-top: -20px" />
|
||||
</sw-input-group>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.type')"
|
||||
:error="dataTypeError"
|
||||
class="mt-5"
|
||||
horizontal
|
||||
required
|
||||
>
|
||||
<sw-select
|
||||
v-model="selectType"
|
||||
:options="dataTypes"
|
||||
:invalid="$v.selectType.$error"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="false"
|
||||
track-by="label"
|
||||
label="label"
|
||||
@input="onSelectTypeChange"
|
||||
/>
|
||||
</sw-input-group>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.label')"
|
||||
:error="labelError"
|
||||
class="mt-5"
|
||||
horizontal
|
||||
required
|
||||
>
|
||||
<sw-input
|
||||
ref="name"
|
||||
:invalid="$v.formData.label.$error"
|
||||
v-model="formData.label"
|
||||
type="text"
|
||||
@input="$v.formData.label.$touch()"
|
||||
/>
|
||||
</sw-input-group>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.options')"
|
||||
class="mt-5"
|
||||
v-if="isDropdownSelected"
|
||||
horizontal
|
||||
>
|
||||
<option-create @onAdd="addNewOptions" />
|
||||
<div
|
||||
v-for="(option, index) in formData.options"
|
||||
:key="index"
|
||||
class="flex items-center"
|
||||
style="margin-top: 5px"
|
||||
>
|
||||
<sw-input v-model="option.name" type="text" style="width: 90%" />
|
||||
<minus-circle-icon
|
||||
@click="removeOption(index)"
|
||||
class="ml-1 cursor-pointer icon text-danger"
|
||||
/>
|
||||
</div>
|
||||
</sw-input-group>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.default_value')"
|
||||
horizontal
|
||||
class="relative mt-5"
|
||||
v-if="formData.type"
|
||||
>
|
||||
<component
|
||||
:value="formData.default_answer"
|
||||
:is="formData.type + 'Type'"
|
||||
:options="formData.options"
|
||||
:defaultDateTime="formData.dateTimeValue"
|
||||
v-model="formData.default_answer"
|
||||
/>
|
||||
</sw-input-group>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.placeholder')"
|
||||
v-if="!isSwitchTypeSelected"
|
||||
class="mt-5"
|
||||
horizontal
|
||||
>
|
||||
<sw-input v-model="formData.placeholder" type="text" />
|
||||
</sw-input-group>
|
||||
<sw-input-group
|
||||
:label="$t('settings.custom_fields.order')"
|
||||
:error="orderError"
|
||||
class="mt-5"
|
||||
horizontal
|
||||
>
|
||||
<sw-input
|
||||
v-model="formData.order"
|
||||
:invalid="$v.formData.order.$error"
|
||||
type="number"
|
||||
@input="$v.formData.order.$touch()"
|
||||
/>
|
||||
</sw-input-group>
|
||||
</div>
|
||||
<div
|
||||
class="z-0 flex justify-end p-4 border-t border-solid border-gray-light border-modal-bg"
|
||||
>
|
||||
<sw-button
|
||||
class="mr-3"
|
||||
type="button"
|
||||
variant="primary-outline"
|
||||
@click="closeCategoryModal"
|
||||
>
|
||||
{{ $t('general.cancel') }}
|
||||
</sw-button>
|
||||
<sw-button
|
||||
:loading="isLoading"
|
||||
:disabled="isLoading"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
>
|
||||
<save-icon v-if="!isLoading" class="mr-2" />
|
||||
{{ !isEdit ? $t('general.save') : $t('general.update') }}
|
||||
</sw-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import { MinusCircleIcon } from '@vue-hero-icons/solid'
|
||||
import InputType from './types/InputType'
|
||||
import NumberType from './types/NumberType'
|
||||
import SwitchType from './types/SwitchType'
|
||||
import TextAreaType from './types/TextAreaType'
|
||||
import TimeType from './types/TimeType'
|
||||
import UrlType from './types/UrlType'
|
||||
import PhoneType from './types/PhoneType'
|
||||
import DateTimeType from './types/DateTimeType'
|
||||
import DateType from './types/DateType'
|
||||
import DropdownType from './types/DropdownType'
|
||||
|
||||
import OptionCreate from './types/OptionsCreate'
|
||||
import moment from 'moment'
|
||||
|
||||
const {
|
||||
required,
|
||||
requiredIf,
|
||||
numeric,
|
||||
minLength,
|
||||
} = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MinusCircleIcon,
|
||||
OptionCreate,
|
||||
InputType,
|
||||
NumberType,
|
||||
SwitchType,
|
||||
TextAreaType,
|
||||
TimeType,
|
||||
UrlType,
|
||||
PhoneType,
|
||||
DateTimeType,
|
||||
DateType,
|
||||
DropdownType,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEdit: false,
|
||||
dateType: 'custom',
|
||||
isLoading: false,
|
||||
relativeDateTypes: [
|
||||
'Today',
|
||||
'Tomorrow',
|
||||
'Yesterday',
|
||||
'Starting Date of Week',
|
||||
'Ending Date of Week',
|
||||
'Starting Date of Next Week',
|
||||
'Ending Date of Next Week',
|
||||
'Starting Date of Previous Week',
|
||||
'Ending Date of Previous Week',
|
||||
'Starting Date of Month',
|
||||
'Ending Date of Month',
|
||||
'Starting Date of Next Month',
|
||||
'Ending Date of Next Month',
|
||||
'Starting Date of Previous Month',
|
||||
'Ending Date of Previous Month',
|
||||
'Starting Date of Fiscal Month',
|
||||
'Ending Date of Fiscal Month',
|
||||
],
|
||||
dataTypes: [
|
||||
{ label: 'Text', value: 'Input' },
|
||||
{ label: 'Textarea', value: 'TextArea' },
|
||||
{ label: 'Phone', value: 'Phone' },
|
||||
{ label: 'URL', value: 'Url' },
|
||||
{ label: 'Number', value: 'Number' },
|
||||
{ label: 'Select Field', value: 'Dropdown' },
|
||||
{ label: 'Switch Toggle', value: 'Switch' },
|
||||
{ label: 'Date', value: 'Date' },
|
||||
{ label: 'Time', value: 'Time' },
|
||||
{ label: 'Date & Time', value: 'DateTime' },
|
||||
],
|
||||
modelTypes: ['Customer', 'Invoice', 'Estimate', 'Expense', 'Payment'],
|
||||
selectType: null,
|
||||
formData: {
|
||||
label: null,
|
||||
type: null,
|
||||
name: null,
|
||||
default_answer: null,
|
||||
is_required: false,
|
||||
placeholder: null,
|
||||
model_type: null,
|
||||
order: 1,
|
||||
options: [],
|
||||
},
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
selectType: {
|
||||
required,
|
||||
},
|
||||
formData: {
|
||||
name: {
|
||||
required,
|
||||
},
|
||||
label: {
|
||||
required,
|
||||
},
|
||||
model_type: {
|
||||
required,
|
||||
},
|
||||
order: {
|
||||
required,
|
||||
numeric,
|
||||
},
|
||||
options: {
|
||||
required: requiredIf('isDropdownSelected'),
|
||||
minLength: minLength(1),
|
||||
$each: {
|
||||
name: {
|
||||
required: requiredIf('isDropdownSelected'),
|
||||
minLength: minLength(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('modal', ['modalData', 'modalDataID', 'refreshData']),
|
||||
isDropdownSelected() {
|
||||
if (this.selectType && this.selectType.label === 'Select Field') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
isSwitchTypeSelected() {
|
||||
if (this.selectType && this.selectType.label === 'Switch Toggle') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
nameError() {
|
||||
if (!this.$v.formData.name.$error) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (!this.$v.formData.name.required) {
|
||||
return this.$tc('validation.required')
|
||||
}
|
||||
},
|
||||
labelError() {
|
||||
if (!this.$v.formData.label.$error) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (!this.$v.formData.label.required) {
|
||||
return this.$tc('validation.required')
|
||||
}
|
||||
},
|
||||
modalTypeError() {
|
||||
if (!this.$v.formData.model_type.$error) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (!this.$v.formData.model_type.required) {
|
||||
return this.$tc('validation.required')
|
||||
}
|
||||
},
|
||||
dataTypeError() {
|
||||
if (!this.$v.selectType.$error) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (!this.$v.selectType.required) {
|
||||
return this.$tc('validation.required')
|
||||
}
|
||||
},
|
||||
hasPlaceHolder() {
|
||||
if (this.selectType.label == 'Switch Toggle') {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
orderError() {
|
||||
if (!this.$v.formData.order.$error) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (!this.$v.formData.order.required) {
|
||||
return this.$tc('validation.required')
|
||||
}
|
||||
|
||||
if (!this.$v.formData.order.numeric) {
|
||||
return this.$tc('validation.numbers_only')
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'formData.type'(newValue, oldvalue) {
|
||||
if (oldvalue != null || oldvalue != undefined) {
|
||||
this.onChangeReset()
|
||||
}
|
||||
},
|
||||
dateType(newValue, oldvalue) {
|
||||
if (oldvalue != null || oldvalue != undefined) {
|
||||
this.onChangeReset()
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.modalDataID) {
|
||||
this.setData()
|
||||
return true
|
||||
}
|
||||
this.formData.model_type = this.modelTypes[0]
|
||||
this.selectType = this.dataTypes[0]
|
||||
this.formData.type = this.dataTypes[0].value
|
||||
},
|
||||
methods: {
|
||||
...mapActions('customFields', [
|
||||
'addCustomField',
|
||||
'updateCustomField',
|
||||
'fetchCustomField',
|
||||
]),
|
||||
...mapActions('modal', ['closeModal']),
|
||||
resetFormData() {
|
||||
this.formData = {
|
||||
label: null,
|
||||
label: null,
|
||||
type: null,
|
||||
dateTimeValue: null,
|
||||
default_answer: null,
|
||||
is_required: false,
|
||||
placeholder: null,
|
||||
model_type: null,
|
||||
options: [{ name: '' }],
|
||||
}
|
||||
this.$v.$reset()
|
||||
},
|
||||
async submitCustomFieldData() {
|
||||
this.$v.selectType.$touch()
|
||||
this.$v.formData.$touch()
|
||||
|
||||
if (this.$v.$invalid) {
|
||||
return false
|
||||
}
|
||||
|
||||
let data = {
|
||||
...this.formData,
|
||||
options: this.formData.options.map((option) => option.name),
|
||||
default_answer:
|
||||
this.isDropdownSelected && this.formData.default_answer
|
||||
? this.formData.default_answer.name
|
||||
: this.formData.default_answer,
|
||||
}
|
||||
if (this.isSwitchTypeSelected && this.formData.default_answer == null) {
|
||||
data.default_answer = false
|
||||
}
|
||||
if (data.type == 'Date') {
|
||||
data.default_answer = data.default_answer
|
||||
? moment(data.default_answer).format('YYYY-MM-DD')
|
||||
: null
|
||||
}
|
||||
if (data.type == 'Time' && typeof data.default_answer == 'object') {
|
||||
let HH =
|
||||
data && data.default_answer && data.default_answer.HH
|
||||
? data.default_answer.HH
|
||||
: null
|
||||
let mm =
|
||||
data && data.default_answer && data.default_answer.mm
|
||||
? data.default_answer.mm
|
||||
: null
|
||||
let ss =
|
||||
data && data.default_answer && data.default_answer.ss
|
||||
? data.default_answer.ss
|
||||
: null
|
||||
data.default_answer = `${HH}:${mm}:${ss}`
|
||||
}
|
||||
let response = null
|
||||
if (this.isEdit) {
|
||||
this.isLoading = true
|
||||
response = await this.updateCustomField(data)
|
||||
window.toastr['success'](
|
||||
this.$tc('settings.custom_fields.updated_message')
|
||||
)
|
||||
this.refreshData()
|
||||
this.closeCategoryModal()
|
||||
return true
|
||||
}
|
||||
|
||||
this.isLoading = true
|
||||
response = await this.addCustomField(data)
|
||||
|
||||
window.toastr['success'](this.$tc('settings.custom_fields.added_message'))
|
||||
this.refreshData()
|
||||
this.closeCategoryModal()
|
||||
return true
|
||||
},
|
||||
addNewOptions(option) {
|
||||
this.formData.options = [{ name: option }, ...this.formData.options]
|
||||
},
|
||||
removeOption(index) {
|
||||
this.formData.options.splice(index, 1)
|
||||
},
|
||||
async setData() {
|
||||
let response = await this.fetchCustomField(this.modalDataID)
|
||||
let fieldData = response.data.customField
|
||||
this.isEdit = true
|
||||
let data = {
|
||||
...fieldData,
|
||||
options: [],
|
||||
dateTimeValue: fieldData.defaultAnswer,
|
||||
default_answer: fieldData.defaultAnswer,
|
||||
options: fieldData.options
|
||||
? fieldData.options.map((option) => {
|
||||
return { name: option ? option : '' }
|
||||
})
|
||||
: [],
|
||||
}
|
||||
this.selectType = this.dataTypes.find(
|
||||
(type) => type.value == fieldData.type
|
||||
)
|
||||
if (data.type == 'Dropdown') {
|
||||
data.default_answer = { name: fieldData.defaultAnswer }
|
||||
}
|
||||
this.formData = { ...data }
|
||||
},
|
||||
onChangeReset() {
|
||||
this.formData = {
|
||||
...this.formData,
|
||||
default_answer: null,
|
||||
is_required: false,
|
||||
placeholder: null,
|
||||
options: [],
|
||||
}
|
||||
},
|
||||
onSelectTypeChange(data) {
|
||||
this.formData.type = data.value
|
||||
this.$v.selectType.$touch()
|
||||
},
|
||||
closeCategoryModal() {
|
||||
this.resetFormData()
|
||||
this.closeModal()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user