akaunting/resources/assets/js/components/AkauntingModalAddNew.vue
2023-04-25 10:01:27 +03:00

343 lines
13 KiB
Vue

<template>
<SlideYUpTransition :duration="animationDuration">
<div class="modal w-full h-full fixed top-0 left-0 right-0 z-50 overflow-y-auto overflow-hidden modal-add-new fade justify-center"
@click.self="closeModal"
:class="[modalPositionTop ? 'items-start' : 'items-center', {'show flex flex-wrap modal-background': show}, {'hidden': !show}]"
v-show="show"
tabindex="-1"
role="dialog"
data-modal-handle
:aria-hidden="!show">
<div class="w-full my-10 m-auto flex flex-col px-2 sm:px-0" :class="modalDialogClass ? modalDialogClass : 'max-w-md'">
<slot name="modal-content">
<div class="bg-body rounded-lg modal-content">
<div class="p-5">
<div class="flex items-center justify-between border-b pb-5">
<slot name="card-header">
<h4 class="text-base font-medium" v-html="title"></h4>
<button type="button" class="text-lg" @click="onCancel" aria-hidden="true">
<span class="rounded-md border-b-2 px-2 py-1 text-sm bg-gray-100">esc</span>
</button>
</slot>
</div>
</div>
<slot name="modal-body">
<div class="py-1 px-5" v-if="!is_component" v-html="message"></div>
<div class="py-1 px-5" v-else>
<form id="form-create" method="POST" action="#"/>
<component v-bind:is="component"></component>
</div>
</slot>
<div class="p-5 border-gray-300">
<slot name="card-footer">
<div class="flex items-center justify-end space-x-2 rtl:space-x-reverse">
<button type="button" class="px-6 py-1.5 hover:bg-gray-200 rounded-lg" :class="buttons.cancel.class" @click="onCancel">
{{ buttons.cancel.text }}
</button>
<a v-if="buttons.payment" :href="buttons.payment.url" class="px-6 py-1.5 text-xs bg-transparent hover:bg-gray-200 font-medium rounded-lg leading-6" :class="buttons.payment.class">
{{ buttons.payment.text }}
</a>
<button :disabled="form.loading" type="button" class="relative px-6 py-1.5 bg-green hover:bg-green-700 text-white rounded-lg" :class="buttons.confirm.class" @click="onSubmit">
<i v-if="form.loading" class="animate-submit delay-[0.28s] absolute w-2 h-2 rounded-full left-0 right-0 -top-3.5 m-auto before:absolute before:w-2 before:h-2 before:rounded-full before:animate-submit before:delay-[0.14s] after:absolute after:w-2 after:h-2 after:rounded-full after:animate-submit before:-left-3.5 after:-right-3.5 after:delay-[0.42s]"></i>
<span :class="[{'opacity-0': form.loading}]">{{ buttons.confirm.text }}</span>
</button>
</div>
</slot>
</div>
</div>
</slot>
</div>
</div>
</SlideYUpTransition>
</template>
<script>
import Vue from 'vue';
import { SlideYUpTransition } from "vue2-transitions";
import AkauntingModal from './AkauntingModal';
import AkauntingMoney from './AkauntingMoney';
import AkauntingRadioGroup from './AkauntingRadioGroup';
import AkauntingSelect from './AkauntingSelect';
import AkauntingSelectRemote from './AkauntingSelectRemote';
import AkauntingDate from './AkauntingDate';
import AkauntingRecurring from './AkauntingRecurring';
import Form from './../plugins/form';
import { Alert, ColorPicker } from 'element-ui';
import Global from './../mixins/global';
export default {
name: 'akaunting-modal-add-new',
components: {
SlideYUpTransition,
AkauntingRadioGroup,
AkauntingSelect,
AkauntingModal,
AkauntingMoney,
AkauntingDate,
AkauntingRecurring,
[ColorPicker.name]: ColorPicker,
},
props: {
show: Boolean,
is_component: Boolean,
title: {
type: String,
default: '',
description: "Modal header title"
},
message: {
type: String,
default: '',
description: "Modal body message"
},
buttons: {
type: Object,
default: function () {
return {
cancel: {
text: 'Cancel',
class: 'btn-outline-secondary',
},
confirm: {
text: 'Save',
class: 'disabled:bg-green-100',
}
};
},
description: "Modal footer button"
},
animationDuration: {
type: Number,
default: 800,
description: "Modal transition duration"
},
modalDialogClass: {
type: String,
default: '',
description: "Modal Body size Class"
},
modalPositionTop: {
type: Boolean,
default: false,
description: "Modal Body position Class"
},
},
data() {
return {
form: new Form('form-create'),
display: this.show,
component:'',
money: {
decimal: '.',
thousands: ',',
prefix: '$ ',
suffix: '',
precision: 2,
masked: false /* doesn't work with directive */
},
};
},
created: function () {
let documentClasses = document.body.classList;
documentClasses.add('overflow-y-hidden', 'overflow-overlay');
if (this.modalDialogClass) {
let modal_size = this.modalDialogClass.replace('modal-', 'max-w-screen-');
this.modalDialogClass = modal_size;
}
},
mounted() {
let form_prefix = this._uid;
if (this.is_component) {
this.component = Vue.component('add-new-component', (resolve, reject) => {
resolve({
template : '<div id="modal-add-new-form-' + form_prefix + '">' + this.message + '</div>',
mixins: [
Global
],
components: {
AkauntingRadioGroup,
AkauntingSelect,
AkauntingSelectRemote,
AkauntingModal,
AkauntingMoney,
AkauntingDate,
AkauntingRecurring,
[ColorPicker.name]: ColorPicker,
},
created: function() {
this.form = new Form('form-create');
// for override global currency variable..
this.currency = {
decimal: '.',
thousands: ',',
prefix: '$ ',
suffix: '',
precision: 2,
masked: false /* doesn't work with directive */
};
// Parent vue instance methods merge with child vue instance methods
if (this.$root.$options.methods) {
let parent_methods = this.$root.$options.methods;
for (let method_key in parent_methods) {
if (this.$options.methods[method_key] === undefined) {
this[method_key] = parent_methods[method_key];
}
}
}
// Parent vue instance data merge with child vue instance data
if (this.$root._data) {
let parent_data = this.$root._data;
for (let data_key in parent_data) {
if (this[data_key] === undefined) {
this[data_key] = parent_data[data_key];
}
}
}
},
mounted() {
let form_id = document.getElementById('modal-add-new-form-' + form_prefix).children[0].id;
this.form = new Form(form_id);
},
data: function () {
return {
form: {},
currency: {
decimal: '.',
thousands: ',',
prefix: '$ ',
suffix: '',
precision: 2,
masked: false /* doesn't work with directive */
},
selected_card: null,
}
},
methods: {
onChangeRate() {
this.form.rate = this.form.rate.replace(',', '.');
},
onChangeCode(code) {
window.axios.get(url + '/settings/currencies/config', {
params: {
code: code
}
})
.then(response => {
this.form.rate = response.data.rate;
this.form.precision = response.data.precision;
this.form.symbol = response.data.symbol;
this.form.symbol_first = response.data.symbol_first;
this.form.decimal_mark = response.data.decimal_mark;
this.form.thousands_separator = response.data.thousands_separator;
})
.catch(error => {
});
},
// Change bank account get money and currency rate
async onChangePaymentAccount(account_id) {
let payment_account = Promise.resolve(window.axios.get(url + '/banking/accounts/currency', {
params: {
account_id: account_id
}
}));
payment_account.then(response => {
this.form.currency = response.data.currency_name;
this.form.currency_code = response.data.currency_code;
this.form.currency_rate = response.data.currency_rate;
this.currency.decimal = response.data.decimal_mark;
this.currency.thousands = response.data.thousands_separator;
this.currency.prefix = (response.data.symbol_first) ? response.data.symbol : '';
this.currency.suffix = (! response.data.symbol_first) ? response.data.symbol : '';
this.currency.precision = parseInt(response.data.precision);
})
.catch(error => {
});
},
},
watch: {
'selected_card': function (newVal, oldVal) {
this.form.card_id = newVal;
},
},
})
});
}
window.addEventListener('keyup',(e) => {
if (e.key === 'Escape') {
this.onCancel();
}
});
},
methods: {
closeModal() {
this.$emit("update:show", false);
this.$emit("close");
},
onSubmit() {
this.form = this.$children[0].$children[0].form;
this.form.loading = true;
this.$emit("submit", this.form);
},
onCancel() {
let documentClasses = document.body.classList;
documentClasses.remove('overflow-y-hidden', 'overflow-overlay');
this.$emit("cancel");
}
},
watch: {
show(val) {
let documentClasses = document.body.classList;
if (val) {
documentClasses.add('overflow-y-hidden', 'overflow-overlay');
} else {
documentClasses.remove('overflow-y-hidden', 'overflow-overlay');
}
}
}
}
</script>