<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>