Merge branch 'ASTRA-108' into 'master'

Resolve ASTRA-108

See merge request andrusyakka/urban-couscous!413
This commit is contained in:
Vasiliy Gavrilin
2023-06-09 17:29:28 +00:00
10 changed files with 491 additions and 53 deletions

View File

@@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.84087 4.11519C7.4338 4.68057 7.29199 5.37779 7.29199 5.83333V8.54167H12.7087V5.83333C12.7087 5.37779 12.5669 4.68057 12.1598 4.11519C11.7757 3.58168 11.13 3.125 10.0003 3.125C8.87069 3.125 8.22499 3.58168 7.84087 4.11519ZM13.9587 8.54167V5.83333C13.9587 5.17776 13.7671 4.20832 13.1742 3.38481C12.5583 2.52943 11.5374 1.875 10.0003 1.875C8.46329 1.875 7.44232 2.52943 6.82645 3.38481C6.23352 4.20832 6.04199 5.17776 6.04199 5.83333V8.54167H4.16699C3.82181 8.54167 3.54199 8.82149 3.54199 9.16667V17.5C3.54199 17.8452 3.82181 18.125 4.16699 18.125H15.8337C16.1788 18.125 16.4587 17.8452 16.4587 17.5V9.16667C16.4587 8.82149 16.1788 8.54167 15.8337 8.54167H13.9587ZM4.79199 9.79167V16.875H15.2087V9.79167H4.79199Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 883 B

View File

@@ -1,9 +1,9 @@
<template lang="pug"> <template lang="pug">
base-input-container.gap-y-2(:label="label", :style="{width: width + 'px' }") base-input-container.gap-y-2(:important="important", :label="label", :style="{width: width + 'px' }")
q-input( q-input(
v-model="value", v-model="value",
:name="name", :name="name",
:multiple="multiple" :multiple="multiple",
:class="{'circle': circle, 'font-input': true, 'doc': doc}", :class="{'circle': circle, 'font-input': true, 'doc': doc}",
:input-style="{ color: textColor, borderColor: borderColor, resize: resize, fontSize: fontSize, fontWeight: fontWeight, lineHeight: lineHeight}", :input-style="{ color: textColor, borderColor: borderColor, resize: resize, fontSize: fontSize, fontWeight: fontWeight, lineHeight: lineHeight}",
:borderless="borderless", :borderless="borderless",
@@ -26,7 +26,7 @@
:standout="standout" :standout="standout"
:accept="accept", :accept="accept",
:debounce="debounce", :debounce="debounce",
:shadow-text="shadowText" :shadow-text="shadowText",
hide-bottom-space hide-bottom-space
) )
template(v-slot:prepend, v-if="iconLeft") template(v-slot:prepend, v-if="iconLeft")
@@ -116,6 +116,7 @@ export default {
iconLeft: Boolean, iconLeft: Boolean,
iconRight: Boolean, iconRight: Boolean,
name: String, name: String,
important: Boolean,
}, },
emits: ["update:modelValue"], emits: ["update:modelValue"],
computed: { computed: {

View File

@@ -1,6 +1,7 @@
<template lang="pug"> <template lang="pug">
.flex.flex-col.gap-y-2 .flex.flex-col.gap-y-2
.label.font-semibold.text-sm.opacity-40(v-if="label") {{ label }} .label.font-semibold.text-sm.opacity-40(v-if="label") {{ label }}
span.-mt-2(v-if="important", :style="{color: 'var(--font-obligatory-color)'}") *
slot slot
</template> </template>
@@ -9,6 +10,7 @@ export default {
name: "BaseInputContainer", name: "BaseInputContainer",
props: { props: {
label: String, label: String,
important: Boolean,
}, },
}; };
</script> </script>

View File

@@ -0,0 +1,94 @@
<template lang="pug">
.flex.gap-x-3.w-full.py-6
q-btn(
color="secondary",
text-color="primary",
style="width: 40px; height: 40px",
rounded,
no-caps,
padding="0 16px"
)
q-icon(v-if="image === defaultIcon", name="app:icon-download")
q-avatar(v-else, size="40px", round)
img(:src="image")
q-menu(anchor="bottom middle", self="top right", v-model="showPopup")
.flex.flex-col.p-4.gap-y-3
.flex.items-center.gap-x-2.cursor-pointer(@click="changeOpenModal")
q-icon(name="app:computer", size="18px", color="primary")
span.text-smm.title Загрузить с компьютера
.flex.items-center.gap-x-2.cursor-pointer
q-icon(name="app:camera", size="18px", color="primary")
span.text-smm.title Сделать фото
base-modal(v-model="showModal", title="Загрузить изображение")
.flex.flex-col.items-center.justify-center(
:style="{padding: '153px 370px'}"
)
.avatar-wrapper.flex.relative
base-input(
circle,
type="file",
id="image-upload",
accept="image/*",
@change="(e) => previewImage(e)"
)
.avatar.flex.absolute.items-center.gap-x-6
img.avatar.object-cover(for="image-upload", :src="image", v-if="image")
q-btn(round, color="primary", @click="closeAddImage", icon="app:icon-ok")
base-input.w-full(v-model="infoClient.basic.full_name", placeholder="ФИО пациента*", outlined)
</template>
<script>
import BaseModal from "./BaseModal.vue";
import BaseInput from "./BaseInput.vue";
import addImageIcon from "@/assets/icons/photo.svg";
export default {
name: "BaseInputFullName",
components: { BaseModal, BaseInput },
props: { infoClient: Object },
data() {
return {
defaultIcon: addImageIcon,
showModal: false,
showPopup: false,
image: addImageIcon,
};
},
methods: {
closeAddImage() {
this.showModal = false;
this.showPopup = false;
},
changeOpenModal() {
this.showModal = true;
this.showPopup = false;
},
previewImage(event) {
let picture = event.target.files;
let reader = new FileReader();
reader.onload = (e) => {
this.image = e.target.result;
};
reader.readAsDataURL(picture[0]);
},
},
watch: {
showModal: function () {
if (this.showModal === false) {
this.closeAddImage();
}
},
},
};
</script>
<style lang="sass" scoped>
.avatar-wrapper
width: 400px
height: 400px
border-radius: 50%
.avatar
height: 100%
border-radius: 50%
</style>

View File

@@ -6,7 +6,7 @@
ref="dialog" ref="dialog"
) )
.base-content( .base-content(
:class="{'draggable': draggable, 'base-content-default': !defaultPadding}", :class="{'draggable': draggable, 'base-content-default': !defaultPadding, 'base-modal-default': modalPadding}",
ref="contentRef", ref="contentRef",
:style="{...contentStyles, height}" :style="{...contentStyles, height}"
) )
@@ -30,6 +30,7 @@ export default {
draggable: Boolean, draggable: Boolean,
hideOverlay: Boolean, hideOverlay: Boolean,
defaultPadding: Boolean, defaultPadding: Boolean,
modalPadding: Boolean,
hideHeader: Boolean, hideHeader: Boolean,
height: { height: {
type: String, type: String,
@@ -135,6 +136,9 @@ export default {
.base-content-default .base-content-default
padding: 32px 40px padding: 32px 40px
.base-modal-default
padding: 28px 32px
.base-content .base-content
width: auto width: auto
background-color: var(--default-white) background-color: var(--default-white)

View File

@@ -0,0 +1,91 @@
<template lang="pug">
.flex.flex-col.gap-y-6.pt-6
.table-time.flex.p-4
.flex.flex-col.gap-1(v-for="time in timeCoil")
.flex {{ time }}
.side.flex.p-1.h-9(:style="{columnGap: '2px'}")
q-btn.left-side(size="9px", padding="0 8px", color="primary")
q-icon(name="app:icon-ok")
q-btn.right-side(size="4px", padding="0 4px")
img(:src="lockIcon")
.flex.justify-between.items-center
.flex.gap-2
q-btn(
color="primary",
outline,
size="16px",
no-caps,
label="Отмена",
:style="{width: '108px', height: '40px'}",
padding="0",
@click="closeModalTime"
)
q-btn(
color="primary",
size="16px",
no-caps,
label="Сохранить"
:style="{width: '132px', height: '40px'}",
padding="0",
@click="closeModalTime"
)
.text.font-bold.text-6xl {{`${times.from} - ${times.to}`}}
</template>
<script>
import lockIcon from "@/assets/icons/locked.svg";
export default {
name: "BaseTimeModal",
props: { times: Object, closeModalTime: Function },
data() {
return { lockIcon, select: false };
},
computed: {
validateStartTime() {
return this.verifyTime("8:00");
},
validateEndTime() {
return this.verifyTime("19:00");
},
timeCoil() {
let time = [];
for (let i = this.validateStartTime; i <= this.validateEndTime; i++) {
time.push(`${i}:00`);
}
return time;
},
},
methods: {
verifyTime(dayTime) {
let timeArray = dayTime.split(":").map((elem) => parseInt(elem, 10));
let newTime = timeArray[1] > 30 ? timeArray[0] + 1 : timeArray[0];
return newTime;
},
},
};
</script>
<style lang="sass" scoped>
.table-time
width: 463px
height: 174px
border: 1px solid var(--border-light-grey-color)
border-radius: 6px
flex-wrap: wrap !important
.text
color: var(--font-dark-blue-color)
.side
border-left: 1px solid var(--border-light-grey-color)
border-right: 1px solid var(--border-light-grey-color)
.left-side
border-radius: 6px 1px 1px 6px
background: #4772F2
.right-side
border-radius: 1px 6px 6px 1px
background: #FF6565
</style>

View File

@@ -11,20 +11,23 @@
type="date" type="date"
v-model="basicInfo.birth_date", v-model="basicInfo.birth_date",
label="Дата рождения", label="Дата рождения",
outlined outlined,
important
) )
base-input( base-input(
v-model="phone.username", v-model="phone.username",
placeholder="+7 (915) 6449223", placeholder="+7 (915) 6449223",
mask="+7 (###) ###-##-##", mask="+7 (###) ###-##-##",
label="Номер телефона", label="Номер телефона",
outlined outlined,
important
) )
base-input( base-input(
v-model="email.username", v-model="email.username",
placeholder="user@yandex.ru", placeholder="user@yandex.ru",
label="Email", label="Email",
outlined outlined,
important
) )
.flex.flex-col.col-start-1.col-end-3.w-100(class="gap-y-1.5") .flex.flex-col.col-start-1.col-end-3.w-100(class="gap-y-1.5")
span.text-sm.font-semibold.opacity-40.input-info Ссылки на соцсети span.text-sm.font-semibold.opacity-40.input-info Ссылки на соцсети

View File

@@ -3,7 +3,8 @@
calendar-sidebar(v-if="!isOpen", :open-sidebar="openSidebar", :create-form="createForm") calendar-sidebar(v-if="!isOpen", :open-sidebar="openSidebar", :create-form="createForm")
calendar-open-sidebar(v-else, :open-sidebar="openSidebar", :create-form="createForm") calendar-open-sidebar(v-else, :open-sidebar="openSidebar", :create-form="createForm")
calendar-wrapper.ml-2(:open-sidebar="isOpen") calendar-wrapper.ml-2(:open-sidebar="isOpen")
record-creation-form(:is-show-form="isShowForm") base-modal(v-model="isShowForm", title="Создание записи", modal-padding)
record-creation-form(v-model="isShowForm", :close-form="closeForm")
</template> </template>
<script> <script>
@@ -12,6 +13,7 @@ import CalendarOpenSidebar from "@/pages/newCalendar/components/CalendarOpenSide
import CalendarWrapper from "@/pages/newCalendar/components/CalendarWrapper"; import CalendarWrapper from "@/pages/newCalendar/components/CalendarWrapper";
import RecordCreationForm from "@/pages/newCalendar/components/RecordCreationForm"; import RecordCreationForm from "@/pages/newCalendar/components/RecordCreationForm";
import * as moment from "moment/moment"; import * as moment from "moment/moment";
import BaseModal from "@/components/base/BaseModal.vue";
export default { export default {
name: "TheCalendar", name: "TheCalendar",
@@ -20,6 +22,7 @@ export default {
CalendarOpenSidebar, CalendarOpenSidebar,
CalendarWrapper, CalendarWrapper,
RecordCreationForm, RecordCreationForm,
BaseModal,
}, },
data() { data() {
return { return {
@@ -35,6 +38,9 @@ export default {
createForm() { createForm() {
this.isShowForm = true; this.isShowForm = true;
}, },
closeForm() {
this.isShowForm = false;
},
}, },
}; };
</script> </script>

View File

@@ -1,29 +1,46 @@
<template lang="pug"> <template lang="pug">
base-modal(v-model="isShowForm", title="Создание записи")
.flex.flex-col.pt-6.gap-y-4(:style="{maxWidth: '682px'}") .flex.flex-col.pt-6.gap-y-4(:style="{maxWidth: '682px'}")
.flex.gap-x-10 .flex.gap-x-10
.flex.flex-col.gap-y-4.text-smm .flex.flex-col.gap-y-4.text-smm
.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 .input.flex.items-center.pl-4.gap-x-1
.text-input.font-medium Не принят img(:src="currentStatus.icon")
.text-input.font-medium {{currentStatus.name}}
q-btn.change.flex.w-7.h-7(dense, padding="4px 4px") q-btn.change.flex.w-7.h-7(dense, padding="4px 4px")
img(:src="folder") img(:src="folder")
q-menu
.status.flex.items-center.gap-x-1.font-medium.text-smm(
v-for="status in patientData.statuses",
@click="choiceStatus(status)",
v-close-popup
)
img(:src="status.icon")
span {{status.name}}
.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 .input.flex.items-center.pl-4
.text-input.font-medium 24 мая 2020 .text-input.font-medium {{currentDate.format("DD MMMM YYYY")}}
q-btn.change.flex.w-7.h-7(dense, padding="4px 4px") q-btn.change.flex.w-7.h-7(dense, padding="4px 4px")
img(:src="calendar") img(:src="calendar")
q-menu(
transition-show="scale",
transition-hide="scale",
self="top middle",
:offset="[118, 14]",
)
base-calendar(v-model="currentDate")
.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 .input.flex.items-center.pl-4
.text-input.font-medium 13:00 - 14:00 .text-input.font-medium 13:00 - 14:00
q-btn.change.flex.w-7.h-7(dense, padding="4px 4px") q-btn.change.flex.w-7.h-7(@click="isShowTime = true", dense, padding="4px 4px")
img(:src="time") img(:src="time")
base-modal(v-model="isShowTime", title="Время", modal-padding)
base-time-modal(:times="times", :close-modal-time="closeModalTime")
.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
@@ -36,31 +53,163 @@
.change.flex.items-center .change.flex.items-center
q-btn(dense, padding="24px 8px") q-btn(dense, padding="24px 8px")
q-icon(name="app:icon-plus", size="12px") q-icon(name="app:icon-plus", size="12px")
.flex.items-center.gap-x-3 .flex.items-center.gap-x-3.text-smm
.text.font-semibold.text-smm Услуги .text.font-semibold Услуги:
.flex.gap-x-1 .flex.gap-x-1
.services.flex .services.flex.items-center.px-4.font-medium.text
.change.flex.w-7.h-7 span Выберите услуги
q-btn.change.flex.w-7.h-7(dense, padding="4px 4px")
img(:src="folder")
base-input-full-name(:info-client="patientData")
.flex.flex-col.flex-auto.l.gap-y-8
.flex
button.title-info.px-6.py-2.cursor-pointer.w-full.text-sm(
v-for="form in forms",
@click="selectForm(form.component)",
:class="{active: form.component === currentForm}",
:key="form.id",
:id="form.id"
) {{form.title}}
component(
v-bind:is="currentForm",
:basic-info="patientData.basic",
:phone="patientData.phone",
:email="patientData.email",
:add-network="addNewNetwork",
:priority-list="patientData.priorityList",
:identity-document="patientData.identity_document",
:addresses="patientData.addresses",
:save-file="saveDocFile",
:networks-list="getNetworksList",
)
.footer.flex.gap-2
q-btn(
color="primary",
outline,
size="16px",
no-caps,
label="Отменить"
:style="{width: '126px', height: '40px'}",
padding="0",
@click="closeForm"
)
q-btn(
color="primary",
size="16px",
no-caps,
label="Создать запись"
:style="{width: '174px', height: '40px'}",
padding="0",
@click="closeForm"
)
</template> </template>
<script> <script>
import { column } from "@/pages/clients/utils/tableConfig";
import { v_model } from "@/shared/mixins/v-model";
import BaseModal from "@/components/base/BaseModal.vue"; import BaseModal from "@/components/base/BaseModal.vue";
import noname from "@/assets/icons/noname.svg"; import noname from "@/assets/icons/noname.svg";
import folder from "@/assets/icons/folder.svg"; import folder from "@/assets/icons/folder.svg";
import time from "@/assets/icons/time.svg"; import time from "@/assets/icons/time.svg";
import calendar from "@/assets/icons/calendar-grey.svg"; import calendar from "@/assets/icons/calendar-grey.svg";
import FormCreateBasicInfo from "@/pages/clients/components/FormCreateBasicInfo";
import FormCreateIdentityDocuments from "@/pages/clients/components/FormCreateIdentityDocuments";
import FormCreateAddresses from "@/pages/clients/components/FormCreateAddresses";
import BaseInput from "@/components/base/BaseInput.vue";
import BaseInputFullName from "@/components/base/BaseInputFullName.vue";
import { patientData } from "@/pages/newCalendar/utils/calendarConfig.js";
import BaseCalendar from "@/components/base/BaseCalendar.vue";
import BaseTimeModal from "@/components/base/BaseTimeModal.vue";
import * as moment from "moment/moment";
export default { export default {
name: "RecordCreationForm", name: "RecordCreationForm",
components: { BaseModal }, components: {
props: { isShowForm: Boolean }, BaseModal,
FormCreateBasicInfo,
FormCreateIdentityDocuments,
FormCreateAddresses,
BaseInput,
BaseInputFullName,
BaseCalendar,
BaseTimeModal,
},
props: { isShowForm: Boolean, closeForm: Function },
mixins: [v_model],
data() { data() {
return { noname, folder, time, calendar, isPhoto: false }; return {
noname,
folder,
time,
calendar,
isPhoto: false,
patientData: patientData,
currentStatus: patientData.statuses.find((e) => e.name === "Не принят"),
currentDate: moment().clone(),
isShowTime: false,
times: { from: "8:30", to: "10:30" },
forms: [
{
title: "Основное",
id: "basic",
component: "form-create-basic-info",
},
{
title: "ДУЛ",
id: "doc",
component: "form-create-identity-documents",
},
{
title: "Адрес",
id: "address",
component: "form-create-addresses",
},
],
currentForm: "form-create-basic-info",
networksSettings: column.find((el) => el.name === "networks")?.settings,
};
},
computed: {
getNetworksList() {
let contacts = [];
this.patientData.basic.contacts.forEach((elem) =>
contacts.push(elem.kind.id)
);
let filteredNetworks = this.networksSettings.filter(
({ id }) => !contacts.includes(id)
);
return filteredNetworks;
},
}, },
methods: { methods: {
changePhoto() { changePhoto() {
this.isPhoto = true; this.isPhoto = true;
}, },
selectForm(componentName) {
this.currentForm = this.forms.find(
(elem) => elem.component === componentName
)?.component;
},
saveDocFile(e) {
this.patientData.doc = e.target.files;
},
addNewNetwork() {
const newNetwork = this.getNetworksList;
if (newNetwork[0])
this.patientData.basic.contacts.push({
kind: {
id: newNetwork[0].id,
icon: newNetwork[0].icon,
},
username: "",
});
},
choiceStatus(e) {
this.currentStatus = e;
},
closeModalTime() {
this.isShowTime = false;
},
}, },
}; };
</script> </script>
@@ -102,4 +251,27 @@ export default {
border-radius: 6px border-radius: 6px
height: 28px height: 28px
width: 560px width: 560px
.title-info
color: var(--font-grey-color)
border-bottom: 1.5px solid var(--font-grey-color)
&:hover
color: var(--btn-blue-color)
border-bottom: 1.5px solid var(--btn-blue-color)
&.active
color: var(--btn-blue-color)
border-bottom: 1.5px solid var(--btn-blue-color)
.footer
border-top: 1px solid var(--border-light-grey-color)
margin: 40px -32px 0px
padding: 16px 32px 0px 32px
.status
border-radius: 4px
height: 28px
padding: 8px 8px 8px 5px
&:hover
background: var(--bg-light-grey)
cursor: pointer
</style> </style>

View File

@@ -136,3 +136,65 @@ export const patientList = [
choice: false, choice: false,
}, },
]; ];
export const patientData = {
basic: {
full_name: "",
birth_date: null,
priority: {
id: null,
label: "",
},
contacts: [
{
kind: {
id: "TELEGRAM",
icon: "app:icon-tg",
},
username: "",
},
],
},
identity_document: {
pass: {
series_number: "",
issued_by_org: "",
issued_by_date: null,
issued_by_org_code: "",
},
snils: {
kind: "СНИЛС",
number: "",
},
inn: {
kind: "ИНН",
number: "",
},
},
phone: { username: "" },
email: { username: "" },
addresses: {},
priorityList: [
{
id: 1,
label: "Высокий",
},
{
id: 2,
label: "Средний",
},
{
id: 3,
label: "Низкий",
},
{
id: 4,
label: "-",
},
],
statuses: [
{ name: "Отказ", icon: rejected, check: false },
{ name: "Не принят", icon: not_accepted, check: true },
{ name: "На приеме", icon: reception, check: false },
{ name: "Принят", icon: accepted, check: false },
],
};