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

358 lines
11 KiB
Vue

<template lang="pug">
medical-form-wrapper(
id="documents",
title="Документы",
:is-check-change="isCheckChange",
:is-edit="isEdit",
:cancel="cancelEdit",
:open-edit="openEdit",
:save="saveChange"
)
q-form.form-wrap.gap-x-6.w-full(ref="documentForm", :no-error-focus="true")
.data-section.flex.flex-col.gap-2(
v-for="data in configData",
:key="data.dataLabel",
:class="data?.dataClass"
)
.font-semibold.text-sm.whitespace-nowrap {{data.dataLabel}}
.flex.w-full.items-center.gap-4(
v-for="field in data.fields",
:key="field.label"
)
.label-field.font-sm.text-sm.whitespace-nowrap {{`${field.label} :`}}
.flex.gap-3.items-center.h-10(v-if="field.type === 'photo'")
q-avatar(
rounded,
size="40px",
v-if="docData[data.dataKey]?.attachments?.photo"
)
img.h-10.w-10.object-cover(
:src="docData[data.dataKey]?.attachments?.photo",
:alt="docData[data.dataKey][field.label]"
)
q-badge.delete(
floating,
v-if="isEdit",
rounded,
@click="removeImage(data?.dataKey, field?.key)",
: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="openModal(data.dataKey)",
) {{ docData[data.dataKey][field.key]?.photo ? "Заменить фото" : "Добавить фото"}}
base-modal(v-model="showModal", title="Загрузить изображение" v-if="photoId === data.dataKey")
base-upload-photo(
v-model="docData[photoId][field.key]",
:confirm-upload="confirmChangePhoto",
)
base-input-date(
v-if="field.type === 'date'",
v-model="docData[data.dataKey][field.key]",
:name="data.dataKey + ':' + field.key",
@update:model-value="checkChangeDocData",
:readonly="!isEdit",
width="100%",
:mask="field?.inputMask",
:rule="(val) => !personDataField.includes(data.dataKey + ':' + field.key) ? checkPassportFields(val, field.rules) : field.rules(val)",
size="M",
)
base-input(
v-if="field.type === 'text'",
v-model="docData[data.dataKey][field.key]",
:name="data.dataKey + ':' + field.key",
@update:model-value="checkChangeDocData",
:readonly="!isEdit",
:type="field.type",
width="100%",
:mask="field?.inputMask",
:rule="[(val) => !personDataField.includes(data.dataKey + ':' + field.key) ? checkPassportFields(val, field.rules) : field.rules(val, initialDocData?.[data.dataKey]?.id)]",
size="M"
)
q-icon.my-auto.cursor-pointer.copy(
size="20px",
name="app:copy",
v-if="checkCopiedFields(field.key) && !!docData[data.dataKey][field.key]",
@click="copyValue(docData[data.dataKey][field.key])"
)
</template>
<script>
import MedicalFormWrapper from "@/pages/newMedicalCard/components/MedicalFormWrapper.vue";
import { documentForm } from "@/pages/newMedicalCard/utils/medicalConfig";
import BaseAvatar from "@/components/base/BaseAvatar.vue";
import BaseModal from "@/components/base/BaseModal.vue";
import BaseUploadPhoto from "@/components/base/BaseUploadPhoto.vue";
import {
checkChangeData,
getFieldsNameUnvalidated,
} from "@/shared/utils/changesObjects.js";
import { fetchWrapper } from "@/shared/fetchWrapper.js";
import TheNotificationProvider from "@/components/Notifications/TheNotificationProvider";
import { addNotification } from "@/components/Notifications/notificationContext";
import BaseInput from "@/components/base/BaseInput.vue";
import BaseInputDate from "@/components/base/BaseInputDate.vue";
import { mapActions } from "vuex";
export default {
name: "DocumentsForm",
components: {
MedicalFormWrapper,
BaseInput,
BaseAvatar,
BaseModal,
BaseUploadPhoto,
TheNotificationProvider,
BaseInputDate,
},
data() {
return {
configData: documentForm,
isEdit: false,
docData: null,
isCheckChange: false,
isLoadingData: true,
copiedFields: [
"series",
"number",
"insurance_number",
"tax_identification_number",
],
initializationData: {
passport: {
category: "passport",
id: null,
series: null,
number: null,
issued_by: null,
issued_by_org_code: null,
issued_at: null,
attachments: null,
},
insurance_number: {
id: null,
category: "insurance_number",
number: null,
attachments: null,
},
tax_identification_number: {
id: null,
category: "tax_identification_number",
number: null,
attachments: null,
},
},
personDataField: [
"insurance_number:number",
"tax_identification_number:number",
],
showModal: false,
photoId: "",
};
},
computed: {
initialDocData() {
return this.$store.state.medical.documents;
},
passportFields() {
let excludedFields = [
"attachments",
"id",
"category",
"issued_by_org_code",
];
return Object.keys(this.docData.passport).filter(
(key) => !excludedFields.includes(key)
);
},
},
methods: {
checkPassportFields(val, defaultRule) {
if (
this.passportFields.every((elem) => !this.docData.passport[elem]) &&
!this.initialDocData.passport?.id
) {
this.$refs.documentForm
.getValidationComponents()
.filter((elem) => !this.personDataField.includes(elem.name))
.forEach((elem) => elem.resetValidation());
return true;
}
return defaultRule(val);
},
removeImage(docKey, field) {
this.docData[docKey][field] = {};
this.checkChangeDocData();
},
copyValue(text) {
navigator.clipboard.writeText(text);
},
checkCopiedFields(key) {
return !this.isEdit && this.copiedFields.some((elem) => elem === key);
},
cancelEdit() {
this.docData = this.destruct(this.initialDocData);
this.isEdit = false;
this.isCheckChange = false;
this.$refs.documentForm.resetValidation();
},
openEdit() {
this.isEdit = true;
},
checkChangeDocData() {
this.isCheckChange = checkChangeData(
this.destruct(this.initialDocData),
this.docData
);
},
openModal(id) {
this.photoId = id;
this.showModal = true;
},
confirmChangePhoto() {
this.showModal = false;
this.isCheckChange = true;
},
saveChange() {
const form = this.$refs.documentForm;
form.validate().then((validate) => {
if (!validate) {
getFieldsNameUnvalidated(form).forEach((elem) => {
let error = {};
this.configData.forEach(({ dataKey, fields }) => {
let findedElem = fields.find(
(el) => dataKey + ":" + el.key === elem
);
if (findedElem) error = findedElem?.errorMessage;
});
this.addErrorNotification(error?.title, error?.message);
});
} else {
let request = [];
Object.keys(this.docData).forEach((elem) => {
this.checkChangePhoto(elem, "attachments");
let newData = JSON.parse(JSON.stringify(this.docData[elem]));
newData.attachments = {};
if (!checkChangeData(this.initialDocData?.[elem], newData)) return;
delete newData.id;
if (newData?.issued_by_org_code) {
console.log(
"passport issued_by_org_code",
newData.issued_by_org_code
);
delete newData.issued_by_org_code;
}
delete newData.attachments;
Object.keys(this.docData[elem])?.forEach((key) => {
if (!this.docData[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
)
);
}
});
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.docData[updatedObjId][field]?.file)
console.log(
updatedObjId,
field,
this.docData[updatedObjId][field]?.file[0]
);
},
async createData(url, body) {
return await fetchWrapper.post(url, body);
},
async updateData(url, body) {
return await fetchWrapper.patch(url, body);
},
async deletePhoto(url) {
return await fetchWrapper.del(url);
},
addErrorNotification(title, message) {
addNotification(title + message, title, message, "error", 5000);
},
convertFormat(date) {
return date ? date.split(".").reverse().join("-") : "";
},
...mapActions({
getMedicalDataById: "getMedicalDataById",
}),
destruct(data) {
const { passport, insurance_number, tax_identification_number } =
JSON.parse(JSON.stringify(data));
return {
passport: passport,
insurance_number: insurance_number,
tax_identification_number: tax_identification_number,
};
},
},
watch: {
initialDocData: {
deep: true,
immediate: true,
handler(value) {
if (Object.keys(value).length) this.docData = this.destruct(value);
else this.docData = this.initializationData;
},
},
},
};
</script>
<style lang="sass" scoped>
.form-wrap
display: grid
grid-template-columns: repeat(3, 1fr)
row-gap: 32px
grid-template-rows: 1.2fr 1.8fr
@media(max-width: 1440px)
grid-template-columns: repeat(2, 1fr)
grid-template-rows: 1.2fr 1.8fr
.label-field
min-width: 110px
color: var(--font-grey-color)
.replace-photo
color: var(--btn-blue-color)
.photo-field
min-width: 302px
.icon-copy .cursor
cursor: pointer !important
.icon-cancel :deep(path)
fill: var(--default-white)
.q-badge
padding: 4px
cursor: pointer
.delete
background-color: var(--btn-red-color)
.cancel-icon :deep(path)
fill: white
.copy :deep(path)
fill: var(--font-grey-color)
.passport
grid-column: 1 / 2
grid-row: 1 / 3
.insurance
grid-column: 2 / 3
grid-row: 1 / 2
.tax
grid-column: 2 / 3
grid-row: 2 / 3
</style>