Merge branch '8-editing-documents-block' into 'master'

Редактирование блока документы и страховка на мед.карте, исправить отображение плашек в календаре для пациента с большим количеством контактов

See merge request astra/astra-frontend!507
This commit is contained in:
Kirill Andrusyak
2023-08-29 18:03:22 +00:00
10 changed files with 389 additions and 462 deletions

View File

@@ -55,6 +55,7 @@ export default {
default: false, default: false,
}, },
type: { type: {
type: String,
default: "text", default: "text",
}, },
accept: { accept: {

View File

@@ -9,7 +9,7 @@
:readonly="readonly", :readonly="readonly",
:disable="disabled", :disable="disabled",
mask="##.##.####", mask="##.##.####",
:rules="[checkInput]", :rules="[(val) => rule ? rule(val) : defaultRule(val)]",
:lazy-rules="lazyRule", :lazy-rules="lazyRule",
:item-aligned="itemAligned", :item-aligned="itemAligned",
no-error-icon, no-error-icon,
@@ -60,7 +60,8 @@ export default {
width: Number, width: Number,
lazyRule: [Boolean, String], lazyRule: [Boolean, String],
itemAligned: Boolean, itemAligned: Boolean,
modelValue: Date, rule: Function,
modelValue: String,
placeholder: String, placeholder: String,
disabled: Boolean, disabled: Boolean,
label: String, label: String,
@@ -79,27 +80,15 @@ export default {
computed: { computed: {
value: { value: {
get() { get() {
if ( this.changeInternalDate(
moment(this.modelValue).isValid() && moment(this.checkFormat(this.modelValue)).isValid()
typeof this.modelValue === "object" ? moment(this.modelValue)
) {
this.changeInternalDate(moment(this.modelValue));
return moment(this.modelValue).format("DD.MM.YYYY");
}
if (moment(this.convertFormat(this.modelValue)).isValid()) {
this.changeInternalDate(moment(this.modelValue));
return this.modelValue;
}
this.changeInternalDate(null);
return null;
},
set(value) {
this.$emit(
"update:modelValue",
moment(this.convertFormat(value)).isValid()
? new Date(moment(this.convertFormat(value)))
: null : null
); );
return this.convertISOFormat(this.modelValue);
},
set(value) {
this.$emit("update:modelValue", this.convertRUFormat(value));
}, },
}, },
sizeVariable() { sizeVariable() {
@@ -148,13 +137,22 @@ export default {
}, },
}, },
methods: { methods: {
convertFormat(date) { convertISOFormat(date) {
return date && date?.length === 10 return date?.split("-")?.reverse()?.join(".");
? date.split(".").reverse().join("-")
: null;
}, },
checkInput(val) { convertRUFormat(date) {
return moment(this.convertFormat(val)).isValid(); return date?.split(".")?.reverse()?.join("-");
},
checkFormat(date) {
return date && date?.length === 10 ? date : null;
},
defaultRule(val) {
return (
!val ||
moment(
this.checkFormat(val) ? this.convertRUFormat(val) : null
).isValid()
);
}, },
closeCalendar() { closeCalendar() {
this.calendarVisibility = false; this.calendarVisibility = false;

View File

@@ -64,15 +64,27 @@ export default {
}, },
computed: { computed: {
contacts() { contacts() {
let contactList = this.record?.person?.contacts let contactList = [];
?.filter( this.record?.person?.contacts?.find((elem) => {
(elem) => elem.category === "PHONE" || elem.category === "EMAIL" if (elem.category === "PHONE") {
) contactList.push({
?.map((elem) => ({ kind: elem?.category,
kind: elem.category, icon: networks?.find((item) => item.id === elem.category)?.icon,
icon: networks.find((item) => item.id === elem.category)?.icon, value: elem?.value,
value: elem.value, });
})); return true;
}
});
this.record?.person?.contacts?.find((elem) => {
if (elem.category === "EMAIL") {
contactList.push({
kind: elem?.category,
icon: networks?.find((item) => item.id === elem.category)?.icon,
value: elem?.value,
});
return true;
}
});
if (this.collapsedDisplayCondition) { if (this.collapsedDisplayCondition) {
contactList.length = 1; contactList.length = 1;
return contactList; return contactList;

View File

@@ -57,7 +57,7 @@ export default {
return { return {
patient: {}, patient: {},
phone: "", phone: "",
birth_date: {}, birth_date: "",
time: {}, time: {},
patientData: patientData, patientData: patientData,
currentStatus: patientData.statuses.find((e) => e.name === "Не принят"), currentStatus: patientData.statuses.find((e) => e.name === "Не принят"),

View File

@@ -19,19 +19,20 @@
q-avatar( q-avatar(
rounded, rounded,
size="40px", size="40px",
v-if="docData[data.dataKey][field.key]?.photo" v-if="docData[data.dataKey]?.attachments?.photo"
) )
img.h-10.w-10.object-cover( img.h-10.w-10.object-cover(
:src="docData[data.dataKey][field.key]?.photo", :src="docData[data.dataKey]?.attachments?.photo",
:alt="docData[data.dataKey][field.label]" :alt="docData[data.dataKey][field.label]"
) )
q-badge.delete( q-badge.delete(
floating, floating,
v-if="isEdit", v-if="isEdit",
rounded, rounded,
@click="removeImage(data?.dataKey, field?.key)" @click="removeImage(data?.dataKey, field?.key)",
:style="{padding: 0}"
) )
q-icon.icon-cancel(name="app:cancel", size="8px") q-icon.cancel-icon(name="app:cancel-mini", size="16px")
.replace-photo.font-medium.text-base.cursor-pointer( .replace-photo.font-medium.text-base.cursor-pointer(
v-if="isEdit", v-if="isEdit",
@click="openModal(data.dataKey)", @click="openModal(data.dataKey)",
@@ -44,46 +45,30 @@
base-input-date( base-input-date(
v-if="field.type === 'date'", v-if="field.type === 'date'",
v-model="docData[data.dataKey][field.key]", v-model="docData[data.dataKey][field.key]",
:name="field.key", :name="data.dataKey + ':' + field.key",
@update:model-value="checkChangeDocData", @update:model-value="checkChangeDocData",
:readonly="!isEdit", :readonly="!isEdit",
:width="302", :width="302",
:mask="field?.inputMask", :mask="field?.inputMask",
:rule="[(val) => !personDataField.includes(field.key) ? checkPassportFields(val, field.rules) : field.rules(val)]", :rule="(val) => !personDataField.includes(data.dataKey + ':' + field.key) ? checkPassportFields(val, field.rules) : field.rules(val)",
:autogrow="field.key === 'issued_by_org'", size="M",
size="M"
) )
base-input( base-input(
v-if="field.type === 'text' && field.key !== 'issued_by_org'", v-if="field.type === 'text'",
v-model="docData[data.dataKey][field.key]", v-model="docData[data.dataKey][field.key]",
:name="field.key", :name="data.dataKey + ':' + field.key",
@update:model-value="checkChangeDocData", @update:model-value="checkChangeDocData",
:readonly="!isEdit", :readonly="!isEdit",
:type="field.type", :type="field.type",
:width="302", :width="302",
:mask="field?.inputMask", :mask="field?.inputMask",
:rule="[(val) => !personDataField.includes(field.key) ? checkPassportFields(val, field.rules) : field.rules(val)]", :rule="[(val) => !personDataField.includes(data.dataKey + ':' + field.key) ? checkPassportFields(val, field.rules) : field.rules(val, initialDocData?.[data.dataKey]?.id)]",
size="M" size="M"
) )
.icon-copy.my-auto.text-lg.label-field.cursor-pointer( .icon-copy.my-auto.text-lg.label-field.cursor-pointer(
v-if="checkCopiedFields(field.key) && !!docData[data.dataKey][field.key]", v-if="checkCopiedFields(field.key) && !!docData[data.dataKey][field.key]",
@click="copyValue(docData[data.dataKey][field.key])" @click="copyValue(docData[data.dataKey][field.key])"
) )
base-textarea(
v-if="field.type === 'text' && field.key === 'issued_by_org'",
v-model="docData[data.dataKey][field.key]",
:name="field.key",
@update:model-value="checkChangeDocData",
:readonly="!isEdit",
:type="field.type",
:width="302",
:mask="field?.inputMask",
:rule="[(val) => !personDataField.includes(field.key) ? checkPassportFields(val, field.rules) : field.rules(val)]",
autogrow,
size="auto",
height="57px"
padding="10px 16px"
)
</template> </template>
<script> <script>
@@ -101,7 +86,7 @@ import TheNotificationProvider from "@/components/Notifications/TheNotificationP
import { addNotification } from "@/components/Notifications/notificationContext"; import { addNotification } from "@/components/Notifications/notificationContext";
import BaseInput from "@/components/base/BaseInput.vue"; import BaseInput from "@/components/base/BaseInput.vue";
import BaseInputDate from "@/components/base/BaseInputDate.vue"; import BaseInputDate from "@/components/base/BaseInputDate.vue";
import BaseTextarea from "@/components/base/BaseTextarea.vue.vue"; import { mapActions } from "vuex";
export default { export default {
name: "DocumentsForm", name: "DocumentsForm",
components: { components: {
@@ -112,7 +97,6 @@ export default {
BaseUploadPhoto, BaseUploadPhoto,
TheNotificationProvider, TheNotificationProvider,
BaseInputDate, BaseInputDate,
BaseTextarea,
}, },
data() { data() {
return { return {
@@ -121,7 +105,6 @@ export default {
docData: null, docData: null,
isCheckChange: false, isCheckChange: false,
isLoadingData: true, isLoadingData: true,
approvedPassportData: false,
copiedFields: [ copiedFields: [
"series", "series",
"number", "number",
@@ -130,34 +113,42 @@ export default {
], ],
initializationData: { initializationData: {
passport: { passport: {
category: "passport",
id: null, id: null,
series: null, series: null,
number: null, number: null,
issued_by_org: null, issued_by: null,
issued_by_org_code: null, issued_by_org_code: null,
issued_by_date: null, issued_at: null,
photo: null, attachments: null,
}, },
insurance_number: { insurance_number: {
insurance_number: null, id: null,
photo_insurance_number: null, category: "insurance_number",
number: null,
attachments: null,
}, },
tax_identification_number: { tax_identification_number: {
tax_identification_number: null, id: null,
photo_tax_identification_number: null, category: "tax_identification_number",
number: null,
attachments: null,
}, },
}, },
personDataField: ["insurance_number", "tax_identification_number"], personDataField: [
"insurance_number:number",
"tax_identification_number:number",
],
showModal: false, showModal: false,
photoId: "", photoId: "",
}; };
}, },
computed: { computed: {
initialDocData() { initialDocData() {
return this.$store.state.medical?.documents; return this.$store.state.medical.documents;
}, },
passportFields() { passportFields() {
let excludedFields = ["photo", "id"]; let excludedFields = ["attachments", "id", "category"];
return Object.keys(this.docData.passport).filter( return Object.keys(this.docData.passport).filter(
(key) => !excludedFields.includes(key) (key) => !excludedFields.includes(key)
); );
@@ -173,15 +164,13 @@ export default {
.getValidationComponents() .getValidationComponents()
.filter((elem) => !this.personDataField.includes(elem.name)) .filter((elem) => !this.personDataField.includes(elem.name))
.forEach((elem) => elem.resetValidation()); .forEach((elem) => elem.resetValidation());
this.approvedPassportData = true;
return true; return true;
} }
this.approvedPassportData = false;
return defaultRule(val); return defaultRule(val);
}, },
removeImage(docKey, field) { removeImage(docKey, field) {
this.docData[docKey][field] = {}; this.docData[docKey][field] = {};
this.isCheckChange = true; this.checkChangeDocData();
}, },
copyValue(text) { copyValue(text) {
navigator.clipboard.writeText(text); navigator.clipboard.writeText(text);
@@ -190,9 +179,7 @@ export default {
return !this.isEdit && this.copiedFields.some((elem) => elem === key); return !this.isEdit && this.copiedFields.some((elem) => elem === key);
}, },
cancelEdit() { cancelEdit() {
this.docData = JSON.parse(JSON.stringify(this.initialDocData)); this.docData = this.destruct(this.initialDocData);
this.docData.passport.issued_by_date =
this.initialDocData?.passport?.issued_by_date;
this.isEdit = false; this.isEdit = false;
this.isCheckChange = false; this.isCheckChange = false;
this.$refs.documentForm.resetValidation(); this.$refs.documentForm.resetValidation();
@@ -201,7 +188,10 @@ export default {
this.isEdit = true; this.isEdit = true;
}, },
checkChangeDocData() { checkChangeDocData() {
this.isCheckChange = checkChangeData(this.initialDocData, this.docData); this.isCheckChange = checkChangeData(
this.destruct(this.initialDocData),
this.docData
);
}, },
openModal(id) { openModal(id) {
this.photoId = id; this.photoId = id;
@@ -217,95 +207,48 @@ export default {
if (!validate) { if (!validate) {
getFieldsNameUnvalidated(form).forEach((elem) => { getFieldsNameUnvalidated(form).forEach((elem) => {
let error = {}; let error = {};
this.configData.forEach(({ fields }) => { this.configData.forEach(({ dataKey, fields }) => {
let findedElem = fields.find((el) => el.key === elem); let findedElem = fields.find(
(el) => dataKey + ":" + el.key === elem
);
if (findedElem) error = findedElem?.errorMessage; if (findedElem) error = findedElem?.errorMessage;
}); });
this.addErrorNotification(error?.title, error?.message); this.addErrorNotification(error?.title, error?.message);
}); });
} else { } else {
let passportFormData = new FormData();
let documentsFormData = new FormData();
form.getValidationComponents().forEach((elem) => {
if (!this.personDataField.includes(elem.name)) {
if (elem.name === "issued_by_date") {
passportFormData.append(
elem.name,
this.convertFormat(elem.modelValue) ?? ""
);
} else passportFormData.append(elem.name, elem.modelValue ?? "");
} else documentsFormData.append(elem.name, elem.modelValue ?? "");
});
this.checkChangePhoto("passport", "photo", passportFormData);
this.checkChangePhoto(
"insurance_number",
"photo_insurance_number",
documentsFormData
);
this.checkChangePhoto(
"tax_identification_number",
"photo_tax_identification_number",
documentsFormData
);
let request = []; let request = [];
if (!this.approvedPassportData) { Object.keys(this.docData).forEach((elem) => {
if (!this.initialDocData.passport?.id) { this.checkChangePhoto(elem, "attachments");
passportFormData.append("kind", "PASSPORT"); let newData = JSON.parse(JSON.stringify(this.docData[elem]));
passportFormData.append( newData.attachments = {};
"person", if (!checkChangeData(this.initialDocData?.[elem], newData)) return;
this.$store.state.medical?.basicData?.personalData?.id delete newData.id;
); if (newData?.issued_by_org_code) {
request.push( console.log(
this.sendData( "passport issued_by_org_code",
"general/identity_document/create/", newData.issued_by_org_code
passportFormData
)
); );
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 { } else {
if (this.checkPhotoDeletion("passport", "photo"))
request.push(
this.deletePhoto(
`general/identity_document/${this.initialDocData.passport?.id}/delete_photo/`
)
);
request.push( request.push(
this.sendData( this.updateData(
`general/identity_document/${this.initialDocData.passport?.id}/update/`, `documents/${this.initialDocData?.[elem]?.id}`,
passportFormData newData
) )
); );
} }
} });
if (
this.checkPhotoDeletion(
"insurance_number",
"photo_insurance_number"
)
)
request.push(
this.deletePhoto(
`general/person/${this.$store.state.medical?.basicData?.personalData?.id}/delete_photo_insurance_number/`
)
);
if (
this.checkPhotoDeletion(
"tax_identification_number",
"photo_tax_identification_number"
)
)
request.push(
this.deletePhoto(
`general/person/${this.$store.state.medical?.basicData?.personalData?.id}/delete_photo_tax_identification_number/`
)
);
request.push(
this.sendData(
`general/person/${this.$store.state.medical?.basicData?.personalData?.id}/update/`,
documentsFormData
)
);
Promise.allSettled(request).then(() => { Promise.allSettled(request).then(() => {
this.$store.dispatch("getMedicalCardData"); this.getMedicalDataById(this.$route.params.id);
this.isEdit = false; this.isEdit = false;
this.isCheckChange = false; this.isCheckChange = false;
this.$refs.form?.resetValidation(); this.$refs.form?.resetValidation();
@@ -313,18 +256,19 @@ export default {
} }
}); });
}, },
checkChangePhoto(updatedObjId, field, formData) { checkChangePhoto(updatedObjId, field) {
if (this.docData[updatedObjId][field]?.file) if (this.docData[updatedObjId][field]?.file)
formData.append(field, this.docData[updatedObjId][field]?.file[0]); console.log(
updatedObjId,
field,
this.docData[updatedObjId][field]?.file[0]
);
}, },
checkPhotoDeletion(updatedObjId, field) { async createData(url, body) {
return ( return await fetchWrapper.post(url, body);
!Object.keys(this.docData[updatedObjId][field]).length &&
this.initialDocData[updatedObjId][field]?.photo
);
}, },
async sendData(url, body) { async updateData(url, body) {
return await fetchWrapper.post(url, body, "formData"); return await fetchWrapper.patch(url, body);
}, },
async deletePhoto(url) { async deletePhoto(url) {
return await fetchWrapper.del(url); return await fetchWrapper.del(url);
@@ -333,7 +277,19 @@ export default {
addNotification(title + message, title, message, "error", 5000); addNotification(title + message, title, message, "error", 5000);
}, },
convertFormat(date) { convertFormat(date) {
return date ? date.split(".").reverse().join("-") : null; 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: { watch: {
@@ -341,11 +297,8 @@ export default {
deep: true, deep: true,
immediate: true, immediate: true,
handler(value) { handler(value) {
if (Object.keys(value).length) { if (Object.keys(value).length) this.docData = this.destruct(value);
this.docData = JSON.parse(JSON.stringify(this.initialDocData)); else this.docData = this.initializationData;
this.docData.passport.issued_by_date =
this.initialDocData?.passport?.issued_by_date;
} else this.docData = this.initializationData;
}, },
}, },
}, },
@@ -377,4 +330,6 @@ export default {
cursor: pointer cursor: pointer
.delete .delete
background-color: var(--btn-red-color) background-color: var(--btn-red-color)
.cancel-icon :deep(path)
fill: white
</style> </style>

View File

@@ -8,7 +8,7 @@
:save="saveChange", :save="saveChange",
:cancel="cancelEdit" :cancel="cancelEdit"
) )
.form-wrap.gap-24.w-full q-form.form-wrap.gap-24.w-full(ref="insuranceForm", :no-error-focus="true")
.flex.flex-col.gap-4(v-for="insurance in insuranceConfig", :key="insurance.insuranceKey") .flex.flex-col.gap-4(v-for="insurance in insuranceConfig", :key="insurance.insuranceKey")
.font-semibold.text-sm.whitespace-nowrap {{insurance.insuranceLabel}} .font-semibold.text-sm.whitespace-nowrap {{insurance.insuranceLabel}}
.flex.w-full.justify-between.items-center.gap-4( .flex.w-full.justify-between.items-center.gap-4(
@@ -17,23 +17,27 @@
:style="{marginTop: field.label === 'Документы' ? '20px' : null}" :style="{marginTop: field.label === 'Документы' ? '20px' : null}"
) )
.label-field.font-sm.text-sm.whitespace-nowrap {{`${field.label} :`}} .label-field.font-sm.text-sm.whitespace-nowrap {{`${field.label} :`}}
.avatar-field.flex.gap-3.items-center.h-10.w-10(v-if="field.type === 'avatar'") .flex.gap-3.items-center.h-10.w-10(
.flex.w-10.h-10.relative(v-if="basic[insurance.insuranceKey][field.key]?.photo") v-if="field.type === 'photo'",
:style="{'min-width': field.label === 'Документы' ? '324px' : '302px'}"
)
.flex.w-10.h-10.relative(v-if="insuranceData[insurance.insuranceKey]?.attachments?.photo")
img.rounded.avatar.object-cover( img.rounded.avatar.object-cover(
:src="basic[insurance.insuranceKey][field.key].photo", :src="insuranceData[insurance.insuranceKey]?.attachments?.photo",
alt="AV" alt="AV"
) )
q-badge.delete( q-badge.delete(
floating, floating,
v-if="isEdit", v-if="isEdit",
@click="removeImage(insurance?.insuranceKey, field?.key)", @click="removeImage(insurance?.insuranceKey, field?.key)",
rounded rounded,
:style="{padding: 0}"
) )
q-icon.icon-cancel(name="app:cancel", size="8px") q-icon.cancel-icon(name="app:cancel-mini", size="16px")
.replace-photo.font-medium.text-base.cursor-pointer( .replace-photo.font-medium.text-base.cursor-pointer(
v-if="isEdit", v-if="isEdit",
@click="changeModal(insurance.insuranceKey)" @click="changeModal(insurance.insuranceKey)"
) {{ basic[insurance.insuranceKey][field.key]?.photo ? "Заменить фото" : "Добавить фото" }} ) {{ insuranceData[insurance.insuranceKey]?.attachments?.photo ? "Заменить фото" : "Добавить фото" }}
base-modal( base-modal(
v-if="insurance.insuranceKey === photoId" v-if="insurance.insuranceKey === photoId"
v-model="showModal", v-model="showModal",
@@ -41,14 +45,14 @@
) )
base-upload-photo( base-upload-photo(
:key="insurance.insuranceKey" :key="insurance.insuranceKey"
v-model="basic[photoId][field.key]" v-model="insuranceData[photoId][field.key]"
:confirm-upload="confirmChangePhoto" :confirm-upload="confirmChangePhoto"
) )
.category.flex.h-10.relative.gap-x-2(v-else-if="field.type === 'select'") .category.flex.h-10.relative.gap-x-2(v-else-if="field.type === 'select'")
.category-select.flex.items-center.change.px-4.rounded {{selectCategory(basic[insurance.insuranceKey][field.key])}} .category-select.flex.items-center.change.px-4.rounded {{selectCategory(basic[insurance.insuranceKey][field.key])}}
q-btn.change.flex.w-7.h-9.rounded-md( q-btn.change.flex.w-7.h-9.rounded-md(
v-if="isEdit", v-if="isEdit",
@click="showModalCategories = true", @click="openModalCategories",
dense, dense,
padding="8px" padding="8px"
) )
@@ -77,33 +81,36 @@
) {{"\xa0" + basic?.benefit[insurance?.discount] + "%"}} ) {{"\xa0" + basic?.benefit[insurance?.discount] + "%"}}
.input-container.flex.flex-col.relative(v-else) .input-container.flex.flex-col.relative(v-else)
base-input( base-input(
v-model="basic[insurance.insuranceKey][field.key]", v-model="insuranceData[insurance.insuranceKey][field.key]",
@update:model-value="checkChangeInput", @update:model-value="checkChangeInput",
:mask="field?.inputMask",
:readonly="!isEdit", :readonly="!isEdit",
:type="field.type", size="M",
size="M" :name="insurance.insuranceKey + ':' + field.key",
:rule="[(val) => checkFields(val, insurance.insuranceKey, field.rules)]"
) )
q-icon.my-auto.text-lg.label-field.cursor-pointer.copy( q-icon.my-auto.text-lg.label-field.cursor-pointer.copy(
size="18px", size="18px",
name="app:copy", name="app:copy",
v-if="checkCopiedFields(field.key, basic[insurance.insuranceKey])", v-if="checkCopiedFields(field.key, insuranceData[insurance.insuranceKey])",
@click="copyValue(basic[insurance.insuranceKey][field.key])" @click="copyValue(insuranceData[insurance.insuranceKey][field.key])"
) )
</template> </template>
<script> <script>
import { baseInsuranceForm } from "@/pages/newMedicalCard/utils/medicalConfig"; import { baseInsuranceForm } from "@/pages/newMedicalCard/utils/medicalConfig";
import { mapGetters, mapState } from "vuex"; import { mapActions, mapGetters, mapState } from "vuex";
import MedicalFormWrapper from "@/pages/newMedicalCard/components/MedicalFormWrapper.vue"; import MedicalFormWrapper from "@/pages/newMedicalCard/components/MedicalFormWrapper.vue";
import BaseAvatar from "@/components/base/BaseAvatar.vue"; import BaseAvatar from "@/components/base/BaseAvatar.vue";
import { fetchWrapper } from "@/shared/fetchWrapper"; import { fetchWrapper } from "@/shared/fetchWrapper";
import BaseModal from "@/components/base/BaseModal.vue"; import BaseModal from "@/components/base/BaseModal.vue";
import BaseUploadPhoto from "@/components/base/BaseUploadPhoto.vue"; import BaseUploadPhoto from "@/components/base/BaseUploadPhoto.vue";
import BaseCategorySelection from "@/components/base/BaseCategorySelection.vue"; import BaseCategorySelection from "@/components/base/BaseCategorySelection.vue";
import { checkChangeData } from "@/shared/utils/changesObjects";
import { addNotification } from "@/components/Notifications/notificationContext"; import { addNotification } from "@/components/Notifications/notificationContext";
import BaseInput from "@/components/base/BaseInput.vue"; import BaseInput from "@/components/base/BaseInput.vue";
import {
checkChangeData,
getFieldsNameUnvalidated,
} from "@/shared/utils/changesObjects.js";
export default { export default {
name: "InsuranceForm", name: "InsuranceForm",
@@ -125,28 +132,70 @@ export default {
showModalCategories: false, showModalCategories: false,
photoId: "", photoId: "",
copiedFields: ["series", "number"], 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: { computed: {
...mapGetters({ ...mapGetters({
url: "getUrl", url: "getUrl",
avatar: "getAvatar",
initDataBasic: "getBasicData",
}), }),
...mapState({ ...mapState({
basic: (state) => state.medical?.basicData, basic: (state) => state.medical?.basicData,
benefitData: (state) => state.medical?.benefitData, benefitData: (state) => state.medical?.benefitData,
}), }),
initialDocData() {
return this.$store.state.medical.documents;
},
}, },
methods: { 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) { filterDataBenefit(text) {
if (text.length > 1) if (text.length > 1)
return this.$store.dispatch("getBenefitDataSearch", text); return this.$store.dispatch("getBenefitDataSearch", text);
this.$store.dispatch("getBenefitData", text); this.$store.dispatch("getBenefitData", text);
}, },
removeImage(docKey, field) { removeImage(docKey, field) {
this.basic[docKey][field] = {}; this.insuranceData[docKey][field] = {};
this.isCheckChange = true; this.checkChangeInput();
}, },
checkCopiedFields(key, item) { checkCopiedFields(key, item) {
return ( return (
@@ -170,194 +219,125 @@ export default {
this.isCheckChange = true; this.isCheckChange = true;
}, },
changeModal(id) { changeModal(id) {
if (id === "benefit") return;
this.photoId = id; this.photoId = id;
this.showModal = true; this.showModal = true;
}, },
closeModalCategories() { closeModalCategories() {
this.showModalCategories = false; this.showModalCategories = false;
}, },
openModalCategories() {
//if (this.isEdit) this.showModalCategories = true;
},
checkChangeInput() { checkChangeInput() {
this.isCheckChange = this.isCheckChange = checkChangeData(
JSON.stringify(this.initDataBasic) !== JSON.stringify(this.basic) this.destruct(this.initialDocData),
? true this.insuranceData
: false; );
}, },
confirmChangePhoto() { confirmChangePhoto() {
this.showModal = false; this.showModal = false;
this.isCheckChange = true; this.isCheckChange = true;
}, },
saveChange() {
updateBasicData() { const form = this.$refs.insuranceForm;
let insuranceDMS = this.basic.insuranceDMS; form.validate().then((validate) => {
let insuranceOMS = this.basic.insuranceOMS; if (!validate) {
let personal = this.basic.personalData; getFieldsNameUnvalidated(form).forEach((elem) => {
let benefit = this.basic.benefit; let error = {};
this.insuranceConfig.forEach(({ insuranceKey, fields }) => {
const insuranceFormDataDMS = new FormData(); let findedElem = fields.find(
const insuranceFormDataOMS = new FormData(); (el) => insuranceKey + ":" + el.key === elem
const benefitFormData = new FormData(); );
if (findedElem) error = findedElem?.errorMessage;
if (insuranceDMS.series && insuranceDMS.number) { });
for (let key in insuranceDMS) { this.addErrorNotification(error?.title, error?.message);
if (insuranceDMS[key] && key !== "photo" && key !== "id")
insuranceFormDataDMS.append(key, insuranceDMS[key]);
}
}
if (
insuranceDMS.photo.file &&
insuranceDMS.photo.photo !== this.initDataBasic.insuranceDMS.photo.photo
)
insuranceFormDataDMS.append("photo", insuranceDMS.photo.file[0]);
if (insuranceOMS.series && insuranceOMS.number) {
for (let key in insuranceOMS) {
if (insuranceOMS[key] && key !== "photo" && key !== "id")
insuranceFormDataOMS.append(key, insuranceOMS[key]);
}
}
if (
insuranceOMS.photo.file &&
insuranceOMS.photo.photo !== this.initDataBasic.insuranceOMS.photo.photo
)
insuranceFormDataOMS.append("photo", insuranceOMS.photo.file[0]);
const request = Object.keys(this.basic).map((key) => {
if (
key === "insuranceDMS" &&
!insuranceDMS?.id &&
insuranceDMS.series &&
insuranceDMS.number
) {
insuranceFormDataDMS.append("title", "DMS");
insuranceFormDataDMS.append("person", personal.id);
return this.sendData(
`general/insurance_policy/create/`,
insuranceFormDataDMS
);
}
if (
key === "insuranceOMS" &&
!insuranceOMS?.id &&
insuranceOMS.series &&
insuranceOMS.number
) {
insuranceFormDataOMS.append("title", "OMS");
insuranceFormDataOMS.append("person", personal.id);
return this.sendData(
`general/insurance_policy/create/`,
insuranceFormDataOMS
);
}
if (
checkChangeData(this.initDataBasic.insuranceDMS, insuranceDMS) &&
key === "insuranceDMS" &&
insuranceDMS.id
) {
this.checkedPhoto(
insuranceDMS.photo,
insuranceDMS.id,
"insurance_policy",
"delete_photo"
);
insuranceFormDataDMS.append("title", "DMS");
return this.sendData(
`general/insurance_policy/${insuranceDMS.id}/update/`,
insuranceFormDataDMS
);
} else if (
insuranceDMS.id &&
(!insuranceDMS.series || !insuranceDMS.number)
) {
this.addErrorNotification(
"Ошибка заполнения формы ДМС",
"Пожалуйста заполните все поля"
);
}
if (
checkChangeData(this.initDataBasic.insuranceOMS, insuranceOMS) &&
key === "insuranceOMS" &&
insuranceOMS.id
) {
this.checkedPhoto(
insuranceOMS.photo,
insuranceOMS.id,
"insurance_policy",
"delete_photo"
);
insuranceFormDataOMS.append("title", "OMS");
return this.sendData(
`general/insurance_policy/${insuranceOMS.id}/update/`,
insuranceFormDataOMS
);
} else if (
insuranceOMS.id &&
(!insuranceOMS.series || !insuranceOMS.number)
) {
this.addErrorNotification(
"Ошибка заполнения формы ОМС",
"Пожалуйста заполните все поля"
);
}
if (
checkChangeData(this.initDataBasic.benefit, benefit) &&
key === "benefit"
) {
this.checkedPhoto(
benefit.photo,
personal.id,
"person",
"delete_photo_benefit"
);
fetchWrapper.post(`general/person/${personal.id}/update/`, {
benefit: benefit.id,
}); });
if ( } else {
benefit.photo.file && let request = [];
benefit.photo.photo !== this.initDataBasic.benefit.photo.photo Object.keys(this.insuranceData).forEach((elem) => {
) { this.checkChangePhoto(elem, "attachments");
benefitFormData.append("photo_benefit", benefit.photo.file[0]); let newData = JSON.parse(JSON.stringify(this.insuranceData[elem]));
return this.sendData( newData.attachments = {};
`general/person/${personal.id}/update/`, if (!checkChangeData(this.initialDocData?.[elem], newData)) return;
benefitFormData 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();
});
} }
}); });
return request;
}, },
checkedPhoto(photo, id, key, title) { checkChangePhoto(updatedObjId, field) {
if (!photo?.photo) { if (this.insuranceData[updatedObjId][field]?.file)
return this.delPhoto(`general/${key}/${id}/${title}/`); console.log(
} updatedObjId,
field,
this.insuranceData[updatedObjId][field]?.file[0]
);
}, },
addErrorNotification(title, message) { addErrorNotification(title, message) {
addNotification(title + message, title, message, "error", 5000); addNotification(title + message, title, message, "error", 5000);
}, },
async createData(url, body) {
async sendData(url, body) { return await fetchWrapper.post(url, body);
return await fetchWrapper.post(url, body, "formData");
}, },
async delPhoto(url) { async updateData(url, body) {
return await fetchWrapper.del(url); return await fetchWrapper.patch(url, body);
}, },
cancelEdit() { cancelEdit() {
this.$store.dispatch("returnInitData"); this.insuranceData = this.destruct(this.initialDocData);
this.isEdit = false; this.isEdit = false;
this.isCheckChange = false; this.isCheckChange = false;
}, },
openEdit() { openEdit() {
this.isEdit = true; this.isEdit = true;
}, },
saveChange() { destruct(data) {
this.isLoadingData = true; const { OMS, DMS } = JSON.parse(JSON.stringify(data));
let updateBasic = this.updateBasicData(); return {
Promise.allSettled(updateBasic) OMS: OMS,
.then(() => this.$store.dispatch("getMedicalCardData")) DMS: DMS,
.then(() => { };
this.isLoadingData = false; },
this.isEdit = false; ...mapActions({
this.isCheckChange = false; 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;
},
}, },
}, },
}; };
@@ -371,9 +351,6 @@ export default {
background: rgba(0, 0, 0, 0.05) background: rgba(0, 0, 0, 0.05)
color: var(--font-dark-blue-color) color: var(--font-dark-blue-color)
.avatar-field
min-width: 302px
.avatar .avatar
height: 100% height: 100%
@@ -434,4 +411,7 @@ export default {
.q-field--outlined.q-field--readonly :deep(.q-field__native) .q-field--outlined.q-field--readonly :deep(.q-field__native)
cursor: default cursor: default
.cancel-icon :deep(path)
fill: white
</style> </style>

View File

@@ -64,7 +64,7 @@ export default {
data() { data() {
return { return {
protocolData: { protocolData: {
date: null, date: "",
startTime: null, startTime: null,
}, },
}; };
@@ -96,19 +96,27 @@ export default {
...mapActions({ ...mapActions({
createProtocol: "createProtocol", createProtocol: "createProtocol",
}), }),
checkFormat(date) {
return date && date?.length === 10 ? date : null;
},
saveProtocol() { saveProtocol() {
if ( if (
!Object.keys(this.protocolData).every((key) => this.protocolData[key]) !Object.keys(this.protocolData).every((key) => this.protocolData[key])
) { )
return; return;
}
let time = this.protocolData.startTime.split(":"); let time = this.protocolData.startTime.split(":");
let start = moment(this.protocolData.date).hour(time[0]).minute(time[1]); let start = moment(this.checkFormat(this.protocolData.date))
?.hour(time[0])
?.minute(time[1]);
let createdProtocol = { let createdProtocol = {
start: start.isValid() ? start.format() : null, start: start.isValid() ? start.format() : null,
end: start.isValid() ? start.add(30, "m").format() : null, end: start.isValid() ? start.add(30, "m").format() : null,
status: null,
}; };
if (
Object.keys(createdProtocol)?.some((elem) => !createdProtocol?.[elem])
)
return;
createdProtocol.status = null;
this.createProtocol(createdProtocol); this.createProtocol(createdProtocol);
this.changeShownCreateModal(false); this.changeShownCreateModal(false);
this.createInspection(); this.createInspection();

View File

@@ -379,47 +379,63 @@ export const baseInfoMenu = [
export const baseInsuranceForm = [ export const baseInsuranceForm = [
{ {
insuranceLabel: "ОМС", insuranceLabel: "ОМС",
insuranceKey: "insuranceOMS", insuranceKey: "OMS",
fields: [ fields: [
{ {
key: "series", key: "series",
label: "Серия", label: "Серия",
type: "text", type: "text",
inputMask: "####", rules: (val) => ruleNotValue(val),
errorMessage: {
title: "Ошибка валидации",
message: "Серия полиса ОМС не заполнена",
},
}, },
{ {
key: "number", key: "number",
label: "Номер", label: "Номер",
type: "text", type: "text",
inputMask: "####-####-####", rules: (val) => ruleNotValue(val),
errorMessage: {
title: "Ошибка валидации",
message: "Номер полиса ОМС не заполнен",
},
}, },
{ {
key: "photo", key: "attachments",
label: "Фото ОМС", label: "Фото ОМС",
type: "avatar", type: "photo",
}, },
], ],
}, },
{ {
insuranceLabel: "ДМС", insuranceLabel: "ДМС",
insuranceKey: "insuranceDMS", insuranceKey: "DMS",
fields: [ fields: [
{ {
key: "series", key: "series",
label: "Серия", label: "Серия",
type: "text", type: "text",
inputMask: "####", rules: (val) => ruleNotValue(val),
errorMessage: {
title: "Ошибка валидации",
message: "Серия полиса ДМС не заполнена",
},
}, },
{ {
key: "number", key: "number",
label: "Номер", label: "Номер",
type: "text", type: "text",
inputMask: "####-####-####", rules: (val) => ruleNotValue(val),
errorMessage: {
title: "Ошибка валидации",
message: "Номер полиса ДМС не заполнен",
},
}, },
{ {
key: "photo", key: "attachments",
label: "Фото ДМС", label: "Фото ДМС",
type: "avatar", type: "photo",
}, },
], ],
}, },
@@ -436,7 +452,7 @@ export const baseInsuranceForm = [
{ {
key: "photo", key: "photo",
label: "Документы", label: "Документы",
type: "avatar", type: "photo",
}, },
], ],
}, },
@@ -475,7 +491,7 @@ export const documentForm = [
rules: (val) => ruleLengthValue(val, 6), rules: (val) => ruleLengthValue(val, 6),
}, },
{ {
key: "issued_by_org", key: "issued_by",
label: "Кем выдан", label: "Кем выдан",
type: "text", type: "text",
errorMessage: { errorMessage: {
@@ -496,7 +512,7 @@ export const documentForm = [
rules: (val) => ruleLengthValue(val, 7), rules: (val) => ruleLengthValue(val, 7),
}, },
{ {
key: "issued_by_date", key: "issued_at",
label: "Дата выдачи", label: "Дата выдачи",
type: "date", type: "date",
rules: (val) => ruleDateValue(val), rules: (val) => ruleDateValue(val),
@@ -506,7 +522,7 @@ export const documentForm = [
}, },
}, },
{ {
key: "photo", key: "attachments",
label: "Фото паспорта", label: "Фото паспорта",
type: "photo", type: "photo",
}, },
@@ -517,7 +533,7 @@ export const documentForm = [
dataKey: "insurance_number", dataKey: "insurance_number",
fields: [ fields: [
{ {
key: "insurance_number", key: "number",
label: "Номер СНИЛС", label: "Номер СНИЛС",
type: "text", type: "text",
inputMask: "###-###-### ##", inputMask: "###-###-### ##",
@@ -525,10 +541,10 @@ export const documentForm = [
title: "Ошибка валидации", title: "Ошибка валидации",
message: "СНИЛС содержит менее 11 цифр", message: "СНИЛС содержит менее 11 цифр",
}, },
rules: (val) => ruleOptionalFields(val, 14), rules: (val, id) => ruleOptionalFields(val, 14, id),
}, },
{ {
key: "photo_insurance_number", key: "attachments",
label: "Фото СНИЛС", label: "Фото СНИЛС",
type: "photo", type: "photo",
}, },
@@ -539,7 +555,7 @@ export const documentForm = [
dataKey: "tax_identification_number", dataKey: "tax_identification_number",
fields: [ fields: [
{ {
key: "tax_identification_number", key: "number",
label: "Номер ИНН", label: "Номер ИНН",
type: "text", type: "text",
inputMask: "############", inputMask: "############",
@@ -547,10 +563,10 @@ export const documentForm = [
title: "Ошибка валидации", title: "Ошибка валидации",
message: "ИНН содержит менее 12 цифр", message: "ИНН содержит менее 12 цифр",
}, },
rules: (val) => ruleOptionalFields(val, 12), rules: (val, id) => ruleOptionalFields(val, 12, id),
}, },
{ {
key: "photo_tax_identification_number", key: "attachments",
label: "Фото ИНН", label: "Фото ИНН",
type: "photo", type: "photo",
}, },

View File

@@ -1,4 +1,5 @@
import * as moment from "moment/moment"; import * as moment from "moment/moment";
export function ruleNotValue(val, text) { export function ruleNotValue(val, text) {
return !!val || text || false; return !!val || text || false;
} }
@@ -7,8 +8,8 @@ export function ruleLengthValue(val, minLength, text) {
return (val && val.length === minLength) || text || false; return (val && val.length === minLength) || text || false;
} }
export function ruleOptionalFields(val, minLength, text) { export function ruleOptionalFields(val, minLength, id, text) {
return !val || val.length === minLength || text || false; return (!val && !id) || val.length === minLength || text || false;
} }
export function ruleEmailValue(val, text) { export function ruleEmailValue(val, text) {
@@ -21,12 +22,16 @@ export function ruleMaxLength(val, maxLength, text) {
} }
export function ruleDateValue(val, text) { export function ruleDateValue(val, text) {
let date = moment(
val && val?.length === 10 ? val.split(".").reverse().join("-") : null
);
return ( return (
(val && !moment(val).isAfter(moment().format("YYYY-MM-DD"))) || (date.isValid() && !date.isAfter(moment().format("YYYY-MM-DD"))) ||
text || text ||
false false
); );
} }
export function ruleNumberInput(val, max, min, text) { export function ruleNumberInput(val, max, min, text) {
return (val <= max && val >= min) || text || false; return (val <= max && val >= min) || text || false;
} }

View File

@@ -34,20 +34,6 @@ const state = () => ({
house: null, house: null,
flat: null, flat: null,
}, },
insuranceDMS: {
series: null,
number: null,
photo: null,
id: null,
organization: null,
},
insuranceOMS: {
series: null,
number: null,
photo: null,
id: null,
organization: null,
},
benefit: { benefit: {
id: null, id: null,
discount: null, discount: null,
@@ -142,8 +128,6 @@ const getters = {
(el) => el.category === "CURRENT_ADDRESS" (el) => el.category === "CURRENT_ADDRESS"
) || {}; ) || {};
let person = state.medicalCard.person; let person = state.medicalCard.person;
let OMS = person?.insurance_policy?.find((e) => e.title === "OMS");
let DMS = person?.insurance_policy?.find((e) => e.title === "DMS");
return { return {
personalData: { personalData: {
last_name: person?.last_name || "", last_name: person?.last_name || "",
@@ -153,7 +137,7 @@ const getters = {
(person?.gender && (person?.gender &&
genderOptions.find((el) => el.id === person?.gender)) || genderOptions.find((el) => el.id === person?.gender)) ||
"", "",
birth_date: person?.birth_date ? new Date(person?.birth_date) : "", birth_date: person?.birth_date || "",
photo: person?.photo photo: person?.photo
? { ? {
photo: rootState.getUrl + person.photo, photo: rootState.getUrl + person.photo,
@@ -176,30 +160,6 @@ const getters = {
house: residenceAddress?.house || "", house: residenceAddress?.house || "",
flat: residenceAddress?.flat || "", flat: residenceAddress?.flat || "",
}, },
insuranceDMS: {
series: DMS?.series,
number: DMS?.number,
photo: DMS?.photo
? {
photo: rootState.getUrl + DMS?.photo,
file: null,
}
: {},
id: DMS?.id,
organization: DMS?.organization,
},
insuranceOMS: {
series: OMS?.series,
number: OMS?.number,
photo: OMS?.photo
? {
photo: rootState.getUrl + OMS?.photo,
file: null,
}
: {},
id: OMS?.id,
organization: OMS?.organization,
},
benefit: { benefit: {
name: person?.benefit?.name, name: person?.benefit?.name,
id: person?.benefit?.id, id: person?.benefit?.id,
@@ -214,46 +174,38 @@ const getters = {
}; };
}, },
getDocumentsData(state, rootState) { getDocumentsData(state, rootState) {
let person = state.medicalCard?.person; const fields = [
const passport = person?.identity_document?.find( "passport",
(el) => el.kind === "PASSPORT" "insurance_number",
); "tax_identification_number",
return { "OMS",
passport: { "DMS",
id: passport?.id ?? "", ];
series: passport?.series ?? "", let result = {};
number: passport?.number ?? "", fields.forEach((elem) => {
issued_by_org: passport?.issued_by_org ?? "", const document = state.medicalCard?.person?.documents?.find(
issued_by_org_code: passport?.issued_by_org_code ?? "", ({ category }) => category === elem
issued_by_date: passport?.issued_by_date );
? new Date(passport?.issued_by_date) const isPassport = elem === "passport";
: null, const isPolicy = elem === "OMS" || elem === "DMS";
photo: passport?.photo result[elem] = {
category: elem,
id: document?.id || "",
series: document?.series || (isPolicy || isPassport ? "" : "000"),
number: document?.number || "",
issued_by: document?.issued_by || (isPassport ? "" : "000"),
issued_by_org_code:
document?.issued_by_org_code || (isPassport ? "000-000" : ""),
issued_at: document?.issued_at || "",
attachments: document?.attachments?.length
? { ? {
photo: rootState.getUrl + passport.photo, photo: rootState.getUrl + document?.attachments?.[0],
file: null, file: null,
} }
: {}, : {},
}, };
insurance_number: { });
insurance_number: person?.insurance_number ?? "", return result;
photo_insurance_number: person?.photo_insurance_number
? {
photo: rootState.getUrl + person.photo_insurance_number,
file: null,
}
: {},
},
tax_identification_number: {
tax_identification_number: person?.tax_identification_number ?? "",
photo_tax_identification_number: person?.photo_tax_identification_number
? {
photo: rootState.getUrl + person?.photo_tax_identification_number,
file: null,
}
: {},
},
};
}, },
getContactsData(state) { getContactsData(state) {
let phones = let phones =