base_ui/pages/admin/forms/new-form.vue
2025-02-20 09:52:41 +03:30

459 lines
13 KiB
Vue

<template>
<NuxtLayout name="default" :menu="adminMenu">
<div class="container-fluid">
<div class="row justify-content-center">
<template v-if="canView">
<!--start: show content if user entered the from title or is edit mode -->
<div v-if="isFormTitleEntered" class="col">
<h5 class="mb-4">
{{ keyValue?.value ?? "عنوان فرم وارد نشده است." }}
<button-component
classes="d-inline-flex"
@click="openNewFormModal"
buttonText=""
>
<span class="tavasi tavasi-Component-242--1"></span>
</button-component>
</h5>
<div class="row no-gutters justify-content-center">
<div class="col">
<div class="list-and-actions-container">
<!-- load Simple/Tab component -->
<keep-alive>
<component
:ref="formMode"
:is="formMode"
:formTitleData="form"
:newFormItem="newFormItem"
@open-new-form-item="openNewFormItem"
></component>
</keep-alive>
<!--start: form actions ( save/preview form) -->
<div
class="d-flex justify-content-end mt-5 ms-3 form-actions"
>
<button-component
classes="btn btn-secondary mx-2"
@click="showFormPreView"
buttonText="پیش نمایش فرم"
>
</button-component>
<button-component
classes="btn btn-primary"
@click="saveFinalForm"
buttonText="ذخیره"
>
</button-component>
</div>
<!--end: form actions ( save/preview form) -->
</div>
</div>
<!-- start: create new form element -->
<div class="col-auto" v-if="showNewFormItem">
<NewFormItem
:key="changeDetectionCounter"
@close-new-form-item="closeNewFormItem"
@add-item-content="addFormItemToFormElements"
:editFormData="editFormData"
></NewFormItem>
</div>
<!-- end: create new form element -->
</div>
</div>
<!--end: show content if user entered the from title or is edit mode -->
</template>
<no-data v-else>
<the-content-loading v-if="fetchingData"></the-content-loading>
<div v-else class="d-flex justify-content-center align-items-center">
<div
class="alert alert-warning d-flex justify-content-center align-items-center"
>
<span
class="tavasi tavasi-warning-circle color-inherit ms-1 text__32"
></span>
عدم دسترسی
</div>
</div>
</no-data>
</div>
<!-- create new form modal -->
<base-modal
v-if="showNewFormTitleModal"
modalSize="modal-md"
modalTitle="فرم جدید"
@close="closeFormModal"
@save="saveFormTitle"
>
<form-builder
ref="titleFormBuilder"
:formElements="formItem"
:formData="form"
></form-builder>
</base-modal>
<!--form preview modal -->
<base-modal
v-if="showPreviewModal"
:showSaveButton="false"
modalSize="modal-lg"
modalTitle="فرم پیش نمایش"
@close="closePreviewModal"
@save="saveFinalForm"
>
<!-- displayMode : horizontal | vertical -->
<form-builder
ref="previewFormBuilder"
displayMode="horizontal"
:formElements="previewFormItems"
:formData="previewFormItemsData"
></form-builder>
</base-modal>
</div>
</NuxtLayout>
</template>
<script>
import keyValueApi from "~/apis/keyValueApi";
import adminMenu from "~/json/admin/json/menu.json";
// import HttpService from "@services/httpService";
// import { mapActions } from "vuex";
import { mapState, mapActions } from "pinia";
import { useCommonStore } from "~/stores/commonStore";
import { defineAsyncComponent } from "vue";
export default {
name: "newForm",
setup() {
definePageMeta({
name: "newForm",
layout: false,
});
},
beforeMount() {
// this.httpService = new HttpService();
this.httpService = useNuxtApp()["$http"];
},
mounted() {
this.checkPermisionBeforGetList();
},
data() {
return {
adminMenu: adminMenu,
canView: false,
changeDetectionCounter: 0,
isFormTitleEntered: false,
fetchingData: false,
httpService: undefined,
// show/hide preview modal
showPreviewModal: false,
previewFormItems: [],
previewFormItemsData: {},
// show/hide new form title
showNewFormTitleModal: false,
showNewFormItem: false,
newFormItem: undefined,
formMode: "SimpleForm",
// formMode: "TabForm",
// store form-item when user clicked on the table edit button in the simple/tab.
editFormData: undefined,
changeDetection: true,
// form model.
form: {
title: "",
comment: null,
type: 1,
},
keyValue: {
key: "",
value: "",
value_json: null,
project_id: 0,
organ_code: 0,
},
// FormItem model.
formItem: {
title: "",
items: [
{
key: "title",
label: "عنوان",
type: "string",
placeholder: "عنوان را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "comment",
label: "توضیحات",
type: "textarea",
placeholder: "توضیحات را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "type",
label: "نوع",
type: "select",
placeholder: "نوع را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [
{
value: 1,
title: "فرم ساده",
},
{
value: 2,
title: "فرم چند بخشی",
},
],
},
],
},
};
},
methods: {
// ...mapActions(["checkPermissions"]),
...mapActions(useCommonStore, ["checkPermissions"]),
checkPermisionBeforGetList() {
const isEditMode = Boolean(this.$route.params.id);
this.checkPermissions({
permission: isEditMode ? "forms_edit" : "forms_new",
_this: this,
})
.then(() => {
if (this.$route.params.id) {
this.getForm(this.$route.params.id)
.then(() => {
this.canView = true;
})
.catch(() => {
this.canView = false;
})
.finally(() => {
this.fetchingData = false;
});
} else this.openNewFormModal();
})
.catch(() => {
this.canView = false;
});
},
/*
summary: save final form
description: saving the edited/created form with its meta and table_columns.
@fires when user clicks on the save button.
@return void.
*/
saveFinalForm() {
if (this.buttonLoading) return;
this.buttonLoading = true;
const url =
this.keyValueUrl() + this.$route.params.id
? keyValueApi.forms.edit
: keyValueApi.forms.add;
// const formData = this.$refs[this.formMode].localMainFormElements;
const formData = {};
formData.value = this.form.title;
formData.value_json = {
type: this.formMode == "SimpleForm" ? 1 : 2,
table_columns: JSON.stringify(formData.table_columns),
form: JSON.stringify(this.$refs[this.formMode].localMainFormElements),
};
// formData.table_columns = null;
// formData.table_columns = JSON.stringify(formData.table_columns);
this.httpService
.postRequest(url, formData)
.then((res) => {
mySwalToast({
title: res.message,
html: null,
icon: "success",
});
this.form.meta = JSON.parse(this.form.meta);
this.form.table_columns = JSON.parse(this.form.table_columns);
})
.finally(() => {
this.buttonLoading = false;
});
},
showFormPreView() {
this.previewFormItems = this.$refs[this.formMode].localMainFormElements;
this.showPreviewModal = true;
setTimeout(() => {
$("#base-modal").modal({ backdrop: "static", keyboard: false }, "show");
}, 500);
},
// close preview modal
closePreviewModal() {
$("#base-modal").modal("hide");
setTimeout(() => {
this.showPreviewModal = false;
}, 500);
},
// open new form modal
openNewFormModal() {
this.showNewFormTitleModal = true;
setTimeout(() => {
$("#base-modal").modal({ backdrop: "static", keyboard: false }, "show");
}, 500);
},
// close new form modal
closeFormModal() {
if (!this.$route.params.id) this.$router.push({ name: "formList" });
$("#base-modal").modal("hide");
setTimeout(() => {
this.showNewFormTitleModal = false;
}, 500);
},
// get form details
async getForm(formId) {
if (this.fetchingData) return;
this.fetchingData = true;
const url = this.keyValueUrl()+ keyValueApi.forms.get;
return await this.httpService
.getRequest(url + "/" + formId)
.then((res) => {
this.keyValue = res.data;
// this.form.type = "TabForm";
// this.openNewFormModal();
this.form.title = this.keyValue.value;
let meta = JSON.parse(this.keyValue.value_json);
this.form.table_columns = meta.table_columns;
this.form.meta = meta.form;
if (meta.type == 1) this.formMode = "SimpleForm";
else if (meta.type == 2) this.formMode = "TabForm";
this.isFormTitleEntered = true;
});
},
// save new form title
saveFormTitle() {
if (this.buttonLoading) return;
this.buttonLoading = true;
this.form = this.$refs.titleFormBuilder.localFormData;
const url =
this.keyValueUrl() + this.$route.params.id
? keyValueApi.forms.edit
: keyValueApi.forms.add;
const { title, comment, id = undefined, type } = this.form;
const formData = {
title,
comment,
id,
type,
};
this.httpService
.postRequest(url, formData)
.then((res) => {
mySwalToast({
title: "تبریک",
html: res.message,
icon: "success",
});
this.form = res.data;
this.form.meta = this.form.meta ? JSON.parse(this.form.meta) : null;
this.form.table_columns = this.form.table_columns
? JSON.parse(this.form.table_columns)
: null;
if (type == 1) this.formMode = "SimpleForm";
else if (type == 2) this.formMode = "TabForm";
this.isFormTitleEntered = true;
this.closeFormModal();
})
.finally(() => {
this.buttonLoading = false;
});
},
// new form item methods
addFormItemToFormElements(newFormItem) {
this.newFormItem = structuredClone(newFormItem);
},
// open new form item panel
openNewFormItem(data = undefined) {
this.showNewFormItem = true;
this.editFormData = data;
this.changeDetectionCounter += 1;
},
// close new form item panel
closeNewFormItem() {
this.showNewFormItem = false;
},
},
components: {
// NewFormItem: () => import("@forms/forms/NewFormItem.vue"),
// SimpleForm: () => import("@forms/components/SimpleForm.vue"),
// TabForm: () => import("@forms/components/TabForm.vue"),
TabForm: defineAsyncComponent(() =>
import("@/components/admin/components/TabForm.vue")
),
SimpleForm: defineAsyncComponent(() =>
import("@/components/admin/components/SimpleForm.vue")
),
NewFormItem: defineAsyncComponent(() =>
import("@/components/admin/components/NewFormItem.vue")
),
},
};
</script>
<style lang="scss">
.list-and-actions-container {
position: relative;
.form-actions {
// position: absolute;
// bottom: 1em;
// left: 2em;
background-image: linear-gradient(to bottom, transparent, #fff);
}
}
</style>