Merge branch 'page-govno' into 'master'

Page govno

See merge request andrusyakka/urban-couscous!496
This commit is contained in:
Kirill Andrusyak
2023-08-01 22:58:02 +00:00
14 changed files with 216 additions and 142 deletions

7
package-lock.json generated
View File

@@ -11,6 +11,7 @@
"@dop/astra-ui": "^0.2.5", "@dop/astra-ui": "^0.2.5",
"@vuelidate/core": "^2.0.0", "@vuelidate/core": "^2.0.0",
"@vuelidate/validators": "^2.0.0", "@vuelidate/validators": "^2.0.0",
"lodash": "^4.17.21",
"moment": "^2.29.4", "moment": "^2.29.4",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.1.5", "vue-router": "^4.1.5",
@@ -7578,8 +7579,7 @@
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"dev": true
}, },
"node_modules/lodash.assign": { "node_modules/lodash.assign": {
"version": "4.2.0", "version": "4.2.0",
@@ -17981,8 +17981,7 @@
"lodash": { "lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"dev": true
}, },
"lodash.assign": { "lodash.assign": {
"version": "4.2.0", "version": "4.2.0",

View File

@@ -11,6 +11,7 @@
"@dop/astra-ui": "^0.2.5", "@dop/astra-ui": "^0.2.5",
"@vuelidate/core": "^2.0.0", "@vuelidate/core": "^2.0.0",
"@vuelidate/validators": "^2.0.0", "@vuelidate/validators": "^2.0.0",
"lodash": "^4.17.21",
"moment": "^2.29.4", "moment": "^2.29.4",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.1.5", "vue-router": "^4.1.5",

View File

@@ -1,5 +1,5 @@
<template lang="pug"> <template lang="pug">
.flex.flex-col.w-full.h-full.gap-y-2.pb-2 .flex.flex-col.w-full.h-full.gap-y-2.pb-2.no-scroll
the-header( the-header(
:url="url", :url="url",
:is-open-form="isOpenForm", :is-open-form="isOpenForm",
@@ -8,7 +8,7 @@
:set-updated-clients="setUpdatedClients", :set-updated-clients="setUpdatedClients",
:write-created-client-id="writeCreatedClientId" :write-created-client-id="writeCreatedClientId"
) )
.flex.flex-auto.page-wrapper .flex.grow.no-scroll
the-sidebar the-sidebar
router-view.mx-2( router-view.mx-2(
:open-form="openForm", :open-form="openForm",
@@ -59,7 +59,3 @@ export default {
}, },
}; };
</script> </script>
<style lang="sass" scoped>
.page-wrapper
height: calc(100vh - 56px - 16px)
</style>

View File

@@ -1,5 +1,5 @@
<template lang="pug"> <template lang="pug">
.sidebar.flex.flex-col.justify-between.flex-auto.pt-4.px-2.pb-7.rounded .sidebar.flex.flex-col.justify-between.pt-4.px-2.pb-7.rounded
.flex.flex-col.gap-y-4 .flex.flex-col.gap-y-4
base-button-sidebar( base-button-sidebar(
v-for="button in pageSettings.filter((el) => el.id !== 'settings')", v-for="button in pageSettings.filter((el) => el.id !== 'settings')",

View File

@@ -0,0 +1,60 @@
<template lang="pug">
.w-full.h-full.flex.flex-col
.flex.w-full.gap-x-2.pb-2
medical-header(
v-model="currentMenuItem",
:change-shown-remove-modal="changeShownRemoveModal",
)
medical-records
component(
v-if="currentMenuItem",
v-bind:is="currentMenuItem",
)
base-modal(
v-model="isShownRemoveModal",
title="Удаление медкарты"
)
medical-remove-modal(:change-shown-remove-modal="changeShownRemoveModal")
</template>
<script>
import MedicalHeader from "@/pages/newMedicalCard/components/MedicalHeader.vue";
import MedicalRecords from "@/pages/newMedicalCard/components/MedicalRecords.vue";
import BaseModal from "@/components/base/BaseModal.vue";
import MedicalRemoveModal from "@/pages/newMedicalCard/components/MedicalRemoveModal.vue";
import MedicalBaseInfo from "@/pages/newMedicalCard/components/MedicalBaseInfo.vue";
export default {
name: "TheCreateMedicalCard",
components: {
MedicalRemoveModal,
BaseModal,
MedicalRecords,
MedicalHeader,
MedicalBaseInfo,
},
data() {
return {
isShownRemoveModal: false,
currentMenuItem: "MedicalBaseInfo",
};
},
created() {
this.$store.dispatch("setMedicalCardData", {
created_at: new Date(),
updated_at: new Date(),
type: "new",
number: "новая",
person: {
last_name: "Введите",
first_name: "имя",
patronymic: "пациента",
priority: 4,
allergic: [],
},
});
},
};
</script>
<style scoped lang="sass"></style>

View File

@@ -1,6 +1,5 @@
<template lang="pug"> <template lang="pug">
.medcards-wrapper.flex.flex-col.w-full.gap-y-2.h-full .medcards-wrapper.flex.flex-col.gap-y-2.h-full
table-patients
medical-card-search medical-card-search
</template> </template>
@@ -13,3 +12,9 @@ export default {
components: { MedicalCardSearch, TablePatients }, components: { MedicalCardSearch, TablePatients },
}; };
</script> </script>
<style lang="sass">
.medcards-wrapper
width: calc(100vw - 72px)
overflow: hidden
</style>

View File

@@ -1,6 +1,6 @@
<template lang="pug"> <template lang="pug">
.medical-wrapper.flex.h-full.rounded.w-full.flex-col .medical-wrapper.rounded
list-header list-header(@search="getMedcards")
list-contents list-contents
</template> </template>
@@ -10,10 +10,18 @@ import ListContents from "@/pages/medcards/components/MedicalCardSearchList.vue"
export default { export default {
name: "MedicalCardSearch", name: "MedicalCardSearch",
components: { ListHeader, ListContents }, components: { ListHeader, ListContents },
methods: {
getMedcards(value) {
console.log(value);
},
},
}; };
</script> </script>
<style lang="sass" scoped> <style lang="sass" scoped>
.medical-wrapper .medical-wrapper
background-color: var(--default-white) background-color: var(--default-white)
display: flex
flex-direction: column
overflow: hidden
</style> </style>

View File

@@ -1,42 +1,16 @@
<template lang="pug"> <template lang="pug">
.header-wrapper.flex.w-full.justify-between.p-4 .header-wrapper.flex.w-full.justify-between.p-4
.flex.items-center.justify-center.gap-x-2 .flex.items-center.justify-center.gap-x-2
base-select.search( base-input.search(
width="438px", :width="438",
size="M", size="M",
placeholder="Найти медкарту", placeholder="Введите ФИО или номер телефона",
icon-left, icon-left,
hide-dropdown-icon, v-model="filterString"
use-input
:items="filteringMedcardsList",
custom-option,
:filter-fn="filterFn",
:popup-content-style="{height: filteringMedcardsList?.length > 3 ? '216px' : ''}"
) )
template(v-slot:iconLeft) template(#iconLeft)
q-icon.search-icon(name="app:search", size="20px") q-icon.search-icon(name="app:search", size="20px")
template(v-slot:customOption="slotProps") base-button(width="216px", @click="openCreateMedcardPage")
.w-full.item.px-4.py-2.flex.gap-x-3.cursor-pointer(
v-bind="slotProps.props"
)
q-avatar(size="40px")
img(:src="slotProps.avatar")
.flex.flex-col.gap-y-1
.text-dark.text-sm.font-medium {{ slotProps.label }}
.text-xsx.grey-color Медкарта {{ `#${slotProps.medcard?.split(" ")?.join("")}` }}
template(v-slot:beforeOptions)
.h-10.w-full.px-4.pt-3.pb-2.flex.items-center
span.text-sm.grey-color {{ filteringMedcardsList.length }} результатов
template(v-slot:noOption)
.w-full.px-4.py-3.flex.items-center.text-sm.grey-color.font-medium Результатов по запросу не найдено
base-select(
width="280px",
:items="sortingOptions",
size="M",
placeholder="Сортировать по ...",
v-model="sortingType"
)
base-button(width="216px")
q-icon.plus.mr-2(name="app:plus", size="24px") q-icon.plus.mr-2(name="app:plus", size="24px")
span Создать медкарту span Создать медкарту
</template> </template>
@@ -45,47 +19,26 @@
import BaseInput from "@/components/base/BaseInput.vue"; import BaseInput from "@/components/base/BaseInput.vue";
import BaseSelect from "@/components/base/BaseSelect.vue"; import BaseSelect from "@/components/base/BaseSelect.vue";
import BaseButton from "@/components/base/BaseButton.vue"; import BaseButton from "@/components/base/BaseButton.vue";
import {
medcardsList, import debounce from "lodash/debounce";
sortingOptions,
} from "@/pages/medcards/utils/medcardsConfig.js";
export default { export default {
name: "MedicalCardSearchHeader", name: "MedicalCardSearchHeader",
components: { BaseInput, BaseSelect, BaseButton }, components: { BaseInput, BaseSelect, BaseButton },
emits: ["search"],
data() { data() {
return { return {
filteringMedcardsList: null, filterString: "",
sortingOptions: sortingOptions,
sortingType: null,
}; };
}, },
computed: {
serializedMedcardsList() {
return medcardsList.map((elem) => ({
label: `${elem?.last_name} ${elem?.first_name} ${elem?.patronymic}`,
id: elem?.id,
avatar: elem?.avatar,
medcard: elem?.medcard,
}));
},
},
methods: { methods: {
filterFn(val, update) { openCreateMedcardPage() {
update(() => { alert("Создать медкарту с ФИО: " + this.filterString);
this.filteringMedcardsList = this.serializedMedcardsList?.filter(
(elem) => {
let reg = new RegExp(`^${val}`, "ig");
if (reg.test(elem.label)) return elem;
}
);
});
},
initializeMedcardsList() {
this.filteringMedcardsList = this.serializedMedcardsList;
}, },
}, },
mounted() { watch: {
this.initializeMedcardsList(); filterString: debounce(function (value) {
this.$emit("search", value);
}, 300),
}, },
}; };
</script> </script>

View File

@@ -1,20 +1,20 @@
<template lang="pug"> <template lang="pug">
.list-wrapper.rounded.w-full(id="listWrapper") .scroll-wrapper
.w-full.header.h-10.flex .list-wrapper.rounded.w-full(id="listWrapper")
.h-full.py-10px.px-4.flex.items-center.justify-start.font-semibold.text-sm.grey-color( .w-full.header.h-10.flex
v-for="field in headerConfig", .h-full.py-10px.px-4.flex.items-center.justify-start.font-semibold.text-sm.grey-color(
:key="field.title", v-for="field in headerConfig",
:style="headerStyle(field)" :key="field.title",
) {{ field.title }} :style="headerStyle(field)"
.h-full.w-8(v-if="scrollPresence") ) {{ field.title }}
.body.w-full .h-full.w-8(v-if="scrollPresence")
row( .body.w-full
v-for="medcard in medcardsInfo", row(
:key="medcard.id" v-for="medcard in medcardsInfo",
:scroll-presence="scrollPresence", :key="medcard.id"
:header-style="headerStyle", :header-style="headerStyle",
:medcard-info="medcard", :medcard-info="medcard",
) )
</template> </template>
<script> <script>
@@ -36,8 +36,6 @@ export default {
computed: { computed: {
scrollPresence() { scrollPresence() {
return this.medcardsInfo.length > 9; return this.medcardsInfo.length > 9;
// const wrapper = document.getElementById("listWrapper");
// return wrapper?.scrollHeight > wrapper?.clientHeight;
}, },
}, },
methods: { methods: {
@@ -59,13 +57,21 @@ export default {
</script> </script>
<style lang="sass" scoped> <style lang="sass" scoped>
.scroll-wrapper
flex-grow: 1
overflow-y: hidden
.list-wrapper
overflow: hidden
height: 100%
display: flex
flex-direction: column
min-width: min-content
.header .header
background-color: var(--gray-thirdly) background-color: var(--gray-thirdly)
border-bottom: 1px solid var(--gray-secondary) border-bottom: 1px solid var(--gray-secondary)
.grey-color .grey-color
color: var(--font-grey-color) color: var(--font-grey-color)
.body .body
height: calc(100vh - 56px - 24px - 360px - 72px - 40px)
overflow-y: auto overflow-y: auto
&::-webkit-scrollbar-track &::-webkit-scrollbar-track
margin: 24px 0 24px 0 margin: 24px 0 24px 0

View File

@@ -39,7 +39,6 @@ export default {
name: "MedicalCardSearchRow", name: "MedicalCardSearchRow",
components: { TheNotificationProvider }, components: { TheNotificationProvider },
props: { props: {
scrollPresence: Boolean,
headerStyle: Function, headerStyle: Function,
medcardInfo: Object, medcardInfo: Object,
}, },

View File

@@ -35,12 +35,7 @@
.flex.gap-x-3.items-center .flex.gap-x-3.items-center
.text.font-semibold Время: .text.font-semibold Время:
.flex.gap-x-1 .flex.gap-x-1
.input.flex.items-center.pl-4.rounded-md base-input.input.no-border(size="XS", mask="##:## - ##:##")
.dark-blue.font-medium 13:00 - 14:00
q-btn.change.flex.w-7.h-7.rounded-md(@click="isShowTime = true", dense, padding="4px 4px")
q-icon.icon(name="app:time", size="20px")
base-modal(v-model="isShowTime", title="Время", modal-padding)
base-time-modal(:times="times", :close-modal-time="closeModalTime", :data="data")
.flex.h-14.gap-x-3.items-center.text-smm .flex.h-14.gap-x-3.items-center.text-smm
.text.font-semibold Медкарта: .text.font-semibold Медкарта:
.flex.gap-x-1 .flex.gap-x-1
@@ -71,10 +66,17 @@ import MedcardsModal from "./MedcardsModal.vue";
import { patientList } from "@/pages/newCalendar/utils/calendarConfig.js"; import { patientList } from "@/pages/newCalendar/utils/calendarConfig.js";
import { trimName } from "@/pages/newCalendar/utils/calendarFunctions.js"; import { trimName } from "@/pages/newCalendar/utils/calendarFunctions.js";
import * as moment from "moment/moment"; import * as moment from "moment/moment";
import BaseInput from "@/components/base/BaseInput.vue";
export default { export default {
name: "HeaderRecordForm", name: "HeaderRecordForm",
components: { BaseCalendar, BaseModal, BaseTimeModal, MedcardsModal }, components: {
BaseInput,
BaseCalendar,
BaseModal,
BaseTimeModal,
MedcardsModal,
},
props: { currentStatus: Object, statuses: Array, choiceStatus: Function }, props: { currentStatus: Object, statuses: Array, choiceStatus: Function },
data() { data() {
return { return {
@@ -83,7 +85,7 @@ export default {
isShowTime: false, isShowTime: false,
isShowMedcards: false, isShowMedcards: false,
patients: patientList.find(({ id }) => id === 2).data, patients: patientList.find(({ id }) => id === 2).data,
times: { from: "8:30", to: "10:30" }, times: { from: "08:30", to: "10:30" },
data: [ data: [
{ {
start: "8:00", start: "8:00",
@@ -109,6 +111,18 @@ export default {
this.isShowMedcards = false; this.isShowMedcards = false;
this.patient = medcard; this.patient = medcard;
}, },
// validateTimeString(value = "") {
// const [start = "", end = ""] = value.split(" - ");
// this.validateTime(start);
// this.times = {
// to: this.validateTime(end),
// from: this.validateTime(start),
// };
// },
// validateTime(value = "") {
// const [h, m = "00"] = value.split(":");
// return moment(`${h}:${m}`, "HH:mm").format("HH:mm");
// },
}, },
}; };
</script> </script>
@@ -117,6 +131,11 @@ export default {
.input .input
width: 200px width: 200px
border: 1px solid var(--gray-secondary) border: 1px solid var(--gray-secondary)
& :deep(input)
min-width: 50px
--text-size: 14px
& :deep(.q-field__control)
padding-left: 1rem
.icon :deep(path) .icon :deep(path)
fill: var(--font-grey-color) fill: var(--font-grey-color)

View File

@@ -113,6 +113,8 @@ export default {
}), }),
...mapState({ ...mapState({
basic: (state) => state.medical.basicData, basic: (state) => state.medical.basicData,
isNew: (state) => state.medical.medicalCard.type === "new",
medicalCard: (state) => state.medical.medicalCard,
}), }),
}, },
methods: { methods: {
@@ -195,15 +197,22 @@ export default {
const form = this.$refs.formBasicData; const form = this.$refs.formBasicData;
form.validate().then((validate) => { form.validate().then((validate) => {
if (validate) { if (validate) {
this.isLoadingData = true; let person = this.basic.personalData;
let updateBasic = this.updateBasicData(); this.$store.dispatch("setMedicalCardData", {
Promise.allSettled(updateBasic) ...this.medicalCard,
.then(() => this.$store.dispatch("getMedicalCardData")) person: {
.then(() => { ...this.medicalCard.person,
this.isLoadingData = false; ...person,
this.isEdit = false; },
this.isCheckChange = false; });
}); //let updateBasic = this.updateBasicData();
// Promise.allSettled(updateBasic)
// .then(() => this.$store.dispatch("getMedicalCardData"))
// .then(() => {
// this.isLoadingData = false;
// this.isEdit = false;
// this.isCheckChange = false;
// });
} else { } else {
getFieldsNameUnvalidated(form).forEach((errorKey) => { getFieldsNameUnvalidated(form).forEach((errorKey) => {
addNotification( addNotification(
@@ -221,6 +230,9 @@ export default {
this.isEdit = true; this.isEdit = true;
}, },
}, },
mounted() {
this.isNew && this.openEdit();
},
}; };
</script> </script>

View File

@@ -7,6 +7,7 @@ import TheLogin from "@/pages/login/TheLogin";
import LoggedInLayout from "@/components/LoggedInLayout"; import LoggedInLayout from "@/components/LoggedInLayout";
import TheMedicalCard from "@/pages/newMedicalCard/TheMedicalCard"; import TheMedicalCard from "@/pages/newMedicalCard/TheMedicalCard";
import { fetchWrapper } from "@/shared/fetchWrapper"; import { fetchWrapper } from "@/shared/fetchWrapper";
import TheCreateMedicalCard from "@/pages/createMedicalCard/TheCreateMedicalCard.vue";
const ifNotAuthenticated = async (to, from, next) => { const ifNotAuthenticated = async (to, from, next) => {
const data = await fetchWrapper.get("users/me"); const data = await fetchWrapper.get("users/me");
@@ -41,6 +42,7 @@ export default createRouter({
{ path: "medcards", component: TheMedcards }, { path: "medcards", component: TheMedcards },
{ path: "settings", component: TheSettings }, { path: "settings", component: TheSettings },
{ path: "medical-card", component: TheMedicalCard }, { path: "medical-card", component: TheMedicalCard },
{ path: "create-medical-card", component: TheCreateMedicalCard },
], ],
}, },
], ],

View File

@@ -255,26 +255,34 @@ const getters = {
}; };
}, },
getContactsData(state) { getContactsData(state) {
let phones = state.medicalCard.person.contacts let phones =
.filter((el) => el.kind === "PHONE") state.medicalCard?.person?.contacts
.map((el) => ({ ...el })); ?.filter((el) => el.kind === "PHONE")
let emails = state.medicalCard.person.contacts ?.map((el) => ({ ...el })) || [];
.filter((el) => el.kind === "EMAIL") let emails =
.map((el) => ({ ...el })); state.medicalCard?.person?.contacts
let networks = state.medicalCard.person.contacts ?.filter((el) => el.kind === "EMAIL")
.filter((el) => el.kind !== "PHONE" && el.kind !== "EMAIL") ?.map((el) => ({ ...el })) || [];
.map((el) => ({ ...el })); let networks =
state.medicalCard?.person?.contacts
?.filter((el) => el.kind !== "PHONE" && el.kind !== "EMAIL")
?.map((el) => ({ ...el })) || [];
return { return {
phones: [...phones], phones,
emails: [...emails], emails,
networks: [...networks], networks,
}; };
}, },
getAllergiesData(state) { getAllergiesData(state) {
return [...state.medicalCard.person.allergic.map((el) => ({ ...el }))]; return [
...(state.medicalCard?.person?.allergic?.map((el) => ({ ...el })) || []),
];
}, },
getConfidantData(state) { getConfidantData(state) {
return [...state.medicalCard.confidant.map((el) => getConfidantObject(el))]; return [
...(state.medicalCard?.confidant?.map((el) => getConfidantObject(el)) ||
[]),
];
}, },
getAvatar(state) { getAvatar(state) {
let lastName = state?.medicalCard?.person?.last_name; let lastName = state?.medicalCard?.person?.last_name;
@@ -454,7 +462,7 @@ const actions = {
commit("setAllergiesData"); commit("setAllergiesData");
commit("setConfidantData"); commit("setConfidantData");
commit("setHealthStateData"); commit("setHealthStateData");
commit("setEventsPersonData", res.person.id); commit("setEventsPersonData", res?.person?.id);
}); });
}, },
getPersonsFiltredList() { getPersonsFiltredList() {
@@ -491,6 +499,12 @@ const actions = {
getProtocolData({ commit }, props) { getProtocolData({ commit }, props) {
commit("setProtocolData", props); commit("setProtocolData", props);
}, },
setMedicalCardData({ commit }, props) {
commit("setMedicalCard", props);
},
setBasicData({ commit }, props) {
commit("setBasicData", props);
},
}; };
const mutations = { const mutations = {