408 lines
13 KiB
Vue
408 lines
13 KiB
Vue
<template lang="pug">
|
|
medical-form-wrapper(
|
|
id="insurance",
|
|
title="Страховка",
|
|
:is-loading-data="isLoadingData",
|
|
:is-check-change="isCheckChange",
|
|
:is-edit="isEdit",
|
|
:open-edit="openEdit",
|
|
:save="saveChange",
|
|
:cancel="cancelEdit"
|
|
)
|
|
q-form.form-wrap.gap-6.w-full(ref="insuranceForm", :no-error-focus="true")
|
|
.flex.flex-col.gap-2(v-for="insurance in insuranceConfig", :key="insurance.insuranceKey")
|
|
.font-semibold.text-sm.whitespace-nowrap {{insurance.insuranceLabel}}
|
|
.flex.w-full.items-center.gap-4(
|
|
v-for="field in insurance.fields",
|
|
:key="insurance.insuranceKey + field.key",
|
|
:style="{marginTop: field.label === 'Документы' ? '20px' : null}"
|
|
)
|
|
.label-field.font-sm.text-sm.whitespace-nowrap {{`${field.label} :`}}
|
|
.flex.gap-3.items-center.h-10(
|
|
v-if="field.type === 'photo'",
|
|
)
|
|
.flex.w-10.h-10.relative(v-if="insuranceData[insurance.insuranceKey]?.attachments?.photo")
|
|
img.rounded.avatar.object-cover(
|
|
:src="insuranceData[insurance.insuranceKey]?.attachments?.photo",
|
|
alt="AV"
|
|
)
|
|
q-badge.delete(
|
|
floating,
|
|
v-if="isEdit",
|
|
@click="removeImage(insurance?.insuranceKey, field?.key)",
|
|
rounded,
|
|
:style="{padding: 0}"
|
|
)
|
|
q-icon.cancel-icon(name="app:cancel-mini", size="16px")
|
|
.replace-photo.font-medium.text-base.cursor-pointer(
|
|
v-if="isEdit",
|
|
@click="changeModal(insurance.insuranceKey)"
|
|
) {{ insuranceData[insurance.insuranceKey]?.attachments?.photo ? "Заменить фото" : "Добавить фото" }}
|
|
base-modal(
|
|
v-if="insurance.insuranceKey === photoId"
|
|
v-model="showModal",
|
|
title="Загрузить изображение"
|
|
)
|
|
base-upload-photo(
|
|
:key="insurance.insuranceKey"
|
|
v-model="insuranceData[photoId][field.key]"
|
|
:confirm-upload="confirmChangePhoto"
|
|
)
|
|
.flex.h-10.relative.gap-x-2.w-full(v-else-if="field.type === 'select'")
|
|
.w-full.flex.items-center.change.px-4.rounded {{selectCategory(basic[insurance.insuranceKey][field.key])}}
|
|
q-btn.change.flex.w-7.h-9.rounded-md(
|
|
v-if="isEdit",
|
|
@click="openModalCategories",
|
|
dense,
|
|
padding="8px"
|
|
)
|
|
q-icon.icon(name="app:folder", size="24px")
|
|
base-modal(
|
|
default-padding,
|
|
hide-header,
|
|
v-model="showModalCategories",
|
|
title="Категории"
|
|
)
|
|
base-category-selection(
|
|
:benefit-data="benefitData",
|
|
:close-modal-categories="closeModalCategories",
|
|
:save-categories="saveCategories",
|
|
:show-modal="showModalCategories",
|
|
:basic="basic.benefit",
|
|
@search="filterDataBenefit"
|
|
)
|
|
.flex.font-medium.text-smm.absolute.top-11(
|
|
v-if="basic?.benefit[insurance?.discount]",
|
|
:style="{color: 'var(--font-grey-color)'}"
|
|
)
|
|
span Процент скидки:
|
|
span(
|
|
:style="{color: 'var(--font-dark-blue-color)'}"
|
|
) {{"\xa0" + basic?.benefit[insurance?.discount] + "%"}}
|
|
.w-full.flex.flex-col.relative(v-else)
|
|
base-input(
|
|
v-model="insuranceData[insurance.insuranceKey][field.key]",
|
|
@update:model-value="checkChangeInput",
|
|
:readonly="!isEdit",
|
|
size="M",
|
|
width="100%",
|
|
:name="insurance.insuranceKey + ':' + field.key",
|
|
:rule="[(val) => checkFields(val, insurance.insuranceKey, field.rules)]"
|
|
)
|
|
q-icon.my-auto.cursor-pointer.copy(
|
|
size="20px",
|
|
name="app:copy",
|
|
v-if="checkCopiedFields(field.key, insuranceData[insurance.insuranceKey])",
|
|
@click="copyValue(insuranceData[insurance.insuranceKey][field.key])"
|
|
)
|
|
</template>
|
|
|
|
<script>
|
|
import { baseInsuranceForm } from "@/pages/newMedicalCard/utils/medicalConfig";
|
|
import { mapActions, mapGetters, mapState } from "vuex";
|
|
import MedicalFormWrapper from "@/pages/newMedicalCard/components/MedicalFormWrapper.vue";
|
|
import BaseAvatar from "@/components/base/BaseAvatar.vue";
|
|
import { fetchWrapper } from "@/shared/fetchWrapper";
|
|
import BaseModal from "@/components/base/BaseModal.vue";
|
|
import BaseUploadPhoto from "@/components/base/BaseUploadPhoto.vue";
|
|
import BaseCategorySelection from "@/components/base/BaseCategorySelection.vue";
|
|
import { addNotification } from "@/components/Notifications/notificationContext";
|
|
import BaseInput from "@/components/base/BaseInput.vue";
|
|
import {
|
|
checkChangeData,
|
|
getFieldsNameUnvalidated,
|
|
} from "@/shared/utils/changesObjects.js";
|
|
|
|
export default {
|
|
name: "InsuranceForm",
|
|
components: {
|
|
MedicalFormWrapper,
|
|
BaseAvatar,
|
|
BaseInput,
|
|
BaseModal,
|
|
BaseUploadPhoto,
|
|
BaseCategorySelection,
|
|
},
|
|
data() {
|
|
return {
|
|
insuranceConfig: baseInsuranceForm,
|
|
isCheckChange: false,
|
|
isEdit: false,
|
|
isLoadingData: false,
|
|
showModal: false,
|
|
showModalCategories: false,
|
|
photoId: "",
|
|
copiedFields: ["series", "number"],
|
|
insuranceData: {},
|
|
initializationData: {
|
|
OMS: {
|
|
category: "OMS",
|
|
id: null,
|
|
series: null,
|
|
number: null,
|
|
issued_by: null,
|
|
issued_at: "",
|
|
attachments: null,
|
|
},
|
|
DMS: {
|
|
category: "OMS",
|
|
id: null,
|
|
series: null,
|
|
number: null,
|
|
issued_by: null,
|
|
issued_at: "",
|
|
attachments: null,
|
|
},
|
|
},
|
|
};
|
|
},
|
|
computed: {
|
|
...mapGetters({
|
|
url: "getUrl",
|
|
}),
|
|
...mapState({
|
|
basic: (state) => state.medical?.basicData,
|
|
benefitData: (state) => state.medical?.benefitData,
|
|
}),
|
|
initialDocData() {
|
|
return this.$store.state.medical.documents;
|
|
},
|
|
},
|
|
methods: {
|
|
checkFields(val, insuranceKey, defaultRule) {
|
|
const filteredFields = ["series", "number"];
|
|
if (
|
|
filteredFields?.every(
|
|
(elem) => !this.insuranceData?.[insuranceKey]?.[elem]
|
|
) &&
|
|
!this.initialDocData?.[insuranceKey]?.id
|
|
) {
|
|
this.$refs.insuranceForm
|
|
.getValidationComponents()
|
|
.filter(
|
|
(elem) =>
|
|
elem.name === `${insuranceKey}:series` ||
|
|
elem.name === `${insuranceKey}:number`
|
|
)
|
|
.forEach((elem) => elem.resetValidation());
|
|
return true;
|
|
}
|
|
return defaultRule(val);
|
|
},
|
|
filterDataBenefit(text) {
|
|
if (text.length > 1)
|
|
return this.$store.dispatch("getBenefitDataSearch", text);
|
|
this.$store.dispatch("getBenefitData", text);
|
|
},
|
|
removeImage(docKey, field) {
|
|
this.insuranceData[docKey][field] = {};
|
|
this.checkChangeInput();
|
|
},
|
|
checkCopiedFields(key, item) {
|
|
return (
|
|
!this.isEdit &&
|
|
this.copiedFields.some((elem) => elem === key) &&
|
|
item[key]
|
|
);
|
|
},
|
|
copyValue(text) {
|
|
navigator.clipboard.writeText(text);
|
|
},
|
|
selectCategory(str) {
|
|
if (str) return str.length > 30 ? str.substr(0, 30) + "..." : str;
|
|
return "Выберите категорию";
|
|
},
|
|
saveCategories(obj) {
|
|
this.showModalCategories = false;
|
|
this.basic.benefit.id = obj.id;
|
|
this.basic.benefit.name = obj.name;
|
|
this.basic.benefit.discount = obj.discount;
|
|
this.isCheckChange = true;
|
|
},
|
|
changeModal(id) {
|
|
if (id === "benefit") return;
|
|
this.photoId = id;
|
|
this.showModal = true;
|
|
},
|
|
closeModalCategories() {
|
|
this.showModalCategories = false;
|
|
},
|
|
openModalCategories() {
|
|
//if (this.isEdit) this.showModalCategories = true;
|
|
},
|
|
checkChangeInput() {
|
|
this.isCheckChange = checkChangeData(
|
|
this.destruct(this.initialDocData),
|
|
this.insuranceData
|
|
);
|
|
},
|
|
confirmChangePhoto() {
|
|
this.showModal = false;
|
|
this.isCheckChange = true;
|
|
},
|
|
saveChange() {
|
|
const form = this.$refs.insuranceForm;
|
|
form.validate().then((validate) => {
|
|
if (!validate) {
|
|
getFieldsNameUnvalidated(form).forEach((elem) => {
|
|
let error = {};
|
|
this.insuranceConfig.forEach(({ insuranceKey, fields }) => {
|
|
let findedElem = fields.find(
|
|
(el) => insuranceKey + ":" + el.key === elem
|
|
);
|
|
if (findedElem) error = findedElem?.errorMessage;
|
|
});
|
|
this.addErrorNotification(error?.title, error?.message);
|
|
});
|
|
} else {
|
|
let request = [];
|
|
Object.keys(this.insuranceData).forEach((elem) => {
|
|
this.checkChangePhoto(elem, "attachments");
|
|
let newData = JSON.parse(JSON.stringify(this.insuranceData[elem]));
|
|
newData.attachments = {};
|
|
if (!checkChangeData(this.initialDocData?.[elem], newData)) return;
|
|
delete newData.id;
|
|
delete newData.attachments;
|
|
Object.keys(this.insuranceData[elem])?.forEach((key) => {
|
|
if (!this.insuranceData?.[elem]?.[key]) delete newData?.[key];
|
|
});
|
|
if (!this.initialDocData?.[elem]?.id) {
|
|
newData.person_id =
|
|
this.$store.state.medical?.basicData?.personalData?.id;
|
|
request.push(this.createData("documents/", newData));
|
|
} else
|
|
request.push(
|
|
this.updateData(
|
|
`documents/${this.initialDocData?.[elem]?.id}`,
|
|
newData
|
|
)
|
|
);
|
|
});
|
|
if (request.length)
|
|
Promise.allSettled(request).then(() => {
|
|
this.getMedicalDataById(this.$route.params.id);
|
|
this.isEdit = false;
|
|
this.isCheckChange = false;
|
|
this.$refs.form?.resetValidation();
|
|
});
|
|
}
|
|
});
|
|
},
|
|
checkChangePhoto(updatedObjId, field) {
|
|
if (this.insuranceData[updatedObjId][field]?.file)
|
|
console.log(
|
|
updatedObjId,
|
|
field,
|
|
this.insuranceData[updatedObjId][field]?.file[0]
|
|
);
|
|
},
|
|
addErrorNotification(title, message) {
|
|
addNotification(title + message, title, message, "error", 5000);
|
|
},
|
|
async createData(url, body) {
|
|
return await fetchWrapper.post(url, body);
|
|
},
|
|
async updateData(url, body) {
|
|
return await fetchWrapper.patch(url, body);
|
|
},
|
|
cancelEdit() {
|
|
this.insuranceData = this.destruct(this.initialDocData);
|
|
this.isEdit = false;
|
|
this.isCheckChange = false;
|
|
},
|
|
openEdit() {
|
|
this.isEdit = true;
|
|
},
|
|
destruct(data) {
|
|
const { OMS, DMS } = JSON.parse(JSON.stringify(data));
|
|
return {
|
|
OMS: OMS,
|
|
DMS: DMS,
|
|
};
|
|
},
|
|
...mapActions({
|
|
getMedicalDataById: "getMedicalDataById",
|
|
}),
|
|
},
|
|
watch: {
|
|
showModalCategories: {
|
|
immediate: true,
|
|
handler(newVal) {
|
|
if (newVal) this.$store.dispatch("getBenefitData");
|
|
},
|
|
},
|
|
initialDocData: {
|
|
deep: true,
|
|
immediate: true,
|
|
handler(newVal) {
|
|
if (Object.keys(newVal).length) {
|
|
this.insuranceData = this.destruct(newVal);
|
|
} else this.insuranceData = this.initializationData;
|
|
},
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="sass" scoped>
|
|
.q-field :deep(.q-field__control)
|
|
min-height: 40px
|
|
width: 302px
|
|
align-items: center
|
|
background: rgba(0, 0, 0, 0.05)
|
|
color: var(--font-dark-blue-color)
|
|
|
|
.avatar
|
|
height: 100%
|
|
|
|
.replace-photo
|
|
color: var(--btn-blue-color)
|
|
|
|
.form-wrap
|
|
display: grid
|
|
grid-template-columns: repeat(3, 1fr)
|
|
grid-template-rows: repeat(1, 1fr)
|
|
@media(max-width: 1440px)
|
|
grid-template-columns: repeat(2, 1fr)
|
|
grid-template-rows: 1.2fr 0.8fr
|
|
|
|
.label-field
|
|
min-width: 110px
|
|
color: var(--font-grey-color)
|
|
|
|
.q-badge
|
|
padding: 4px
|
|
cursor: pointer
|
|
|
|
.delete
|
|
background-color: var(--btn-red-color)
|
|
|
|
.icon :deep(path)
|
|
fill: var(--font-grey-color)
|
|
|
|
.icon-cancel :deep(path)
|
|
fill: var(--default-white)
|
|
|
|
.copy :deep(path)
|
|
fill: var(--font-grey-color)
|
|
|
|
.change
|
|
background: var(--bg-light-grey)
|
|
color: var(--font-grey-color)
|
|
border: 1px solid var(--gray-secondary)
|
|
|
|
.q-field--outlined.q-field--readonly :deep(.q-field__control)
|
|
background: var(--bg-light-grey) !important
|
|
&:before
|
|
border-color: var(--bg-light-grey) !important
|
|
transition: none
|
|
&:hover:before
|
|
border-color: var(--bg-light-grey) !important
|
|
|
|
.q-field--outlined.q-field--readonly :deep(.q-field__native)
|
|
cursor: default
|
|
|
|
.cancel-icon :deep(path)
|
|
fill: white
|
|
</style>
|