Files
astra-frontend/src/pages/newMedicalCard/components/BasicDataForms/InsuranceForm.vue
2023-10-04 14:03:38 +03:00

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>