diff --git a/src/assets/images/doctor.png b/src/assets/images/doctor.png new file mode 100644 index 0000000..4e4ea59 Binary files /dev/null and b/src/assets/images/doctor.png differ diff --git a/src/pages/newCalendar/TheCalendar.vue b/src/pages/newCalendar/TheCalendar.vue index a0bfc1c..9759040 100644 --- a/src/pages/newCalendar/TheCalendar.vue +++ b/src/pages/newCalendar/TheCalendar.vue @@ -2,7 +2,10 @@ .w-full.flex calendar-sidebar(v-if="!isOpen", :open-sidebar="openSidebar", :create-form="createForm") calendar-open-sidebar(v-else, :open-sidebar="openSidebar", :create-form="createForm") - calendar-wrapper.ml-2(:open-sidebar="isOpen") + component.ml-2( + v-bind:is="calendarComponent", + :open-sidebar="isOpen", + ) base-modal(v-model="isShowForm", title="Создание записи", modal-padding) create-event-form(:close-form="closeForm") base-modal(v-model="previewVisibility", :hideHeader="true", :modalPadding="true") @@ -12,7 +15,8 @@ - - diff --git a/src/pages/newCalendar/components/CalendarRecordCard.vue b/src/pages/newCalendar/components/CalendarRecordCard.vue index 5cdec80..d8602ae 100644 --- a/src/pages/newCalendar/components/CalendarRecordCard.vue +++ b/src/pages/newCalendar/components/CalendarRecordCard.vue @@ -33,12 +33,12 @@ .flex.gap-x-14(:class="bodyClass") .flex.gap-x-2.items-center( v-for="contact in contacts", - :key="contact.value", + :key="contact?.value", ) - q-icon.network-icon(:name="contact.icon", size="16px") - .text-xxs.cursor-default {{ contact.value }} + q-icon.network-icon(:name="contact?.icon", size="16px") + .text-xxs.cursor-default {{ contact?.value }} .h-6.w-6.color-black.background-dark-grey.text-xxs.rounded.flex.items-center.justify-center.cursor-default( - v-if="collapsedDisplayCondition" + v-if="collapsedDisplayCondition && contact" ) +1 diff --git a/src/pages/newCalendar/components/doctorCalendar/CalendarColumn.vue b/src/pages/newCalendar/components/doctorCalendar/CalendarColumn.vue new file mode 100644 index 0000000..2e285b6 --- /dev/null +++ b/src/pages/newCalendar/components/doctorCalendar/CalendarColumn.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/pages/newCalendar/components/CalendarHeader.vue b/src/pages/newCalendar/components/doctorCalendar/CalendarHeader.vue similarity index 74% rename from src/pages/newCalendar/components/CalendarHeader.vue rename to src/pages/newCalendar/components/doctorCalendar/CalendarHeader.vue index 0a3179e..892b4fe 100644 --- a/src/pages/newCalendar/components/CalendarHeader.vue +++ b/src/pages/newCalendar/components/doctorCalendar/CalendarHeader.vue @@ -74,15 +74,13 @@ diff --git a/src/pages/newCalendar/components/managerCalendar/CalendarColumn.vue b/src/pages/newCalendar/components/managerCalendar/CalendarColumn.vue new file mode 100644 index 0000000..e9c5b32 --- /dev/null +++ b/src/pages/newCalendar/components/managerCalendar/CalendarColumn.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/src/pages/newCalendar/components/managerCalendar/CalendarHeader.vue b/src/pages/newCalendar/components/managerCalendar/CalendarHeader.vue new file mode 100644 index 0000000..da16722 --- /dev/null +++ b/src/pages/newCalendar/components/managerCalendar/CalendarHeader.vue @@ -0,0 +1,134 @@ + + + + + + diff --git a/src/pages/newCalendar/components/managerCalendar/CalendarWrapper.vue b/src/pages/newCalendar/components/managerCalendar/CalendarWrapper.vue new file mode 100644 index 0000000..ad34fb3 --- /dev/null +++ b/src/pages/newCalendar/components/managerCalendar/CalendarWrapper.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/src/pages/newCalendar/mixins/columnMixin.js b/src/pages/newCalendar/mixins/columnMixin.js new file mode 100644 index 0000000..0b917b7 --- /dev/null +++ b/src/pages/newCalendar/mixins/columnMixin.js @@ -0,0 +1,53 @@ +import CalendarRecordCard from "@/pages/newCalendar/components/CalendarRecordCard.vue"; +import { verifyTime } from "@/pages/newCalendar/utils/calendarFunctions.js"; +import { mapActions, mapState } from "vuex"; + +export const columnMixin = { + props: { + dayEndTime: Number, + dayStartTime: Number, + }, + emits: [], + components: { CalendarRecordCard }, + data() { + return { + pixelsPerHour: 76, + }; + }, + computed: { + ...mapState({ + events: (state) => state.calendar.events || [], + }), + pixelsPerMinute() { + return this.pixelsPerHour / 60; + }, + }, + methods: { + ...mapActions({ + changeSelectedRecordId: "changeSelectedRecordId", + }), + eventCardPosition(startTime, endTime) { + let start = startTime + .slice(11, -4) + .split(":") + .map((elem) => parseInt(elem, 10)); + let end = endTime.slice(11, -4); + let position = + (start[0] - this.dayStartTime) * this.pixelsPerHour + + start[1] * this.pixelsPerMinute + + 4; + if ( + parseInt(start[0], 10) < this.dayStartTime || + verifyTime(end) > this.dayEndTime + ) { + return { + top: "0px", + visibility: "hidden", + }; + } + return { + top: `${position}px`, + }; + }, + }, +}; diff --git a/src/pages/newCalendar/mixins/columnStyle.sass b/src/pages/newCalendar/mixins/columnStyle.sass new file mode 100644 index 0000000..d298b8e --- /dev/null +++ b/src/pages/newCalendar/mixins/columnStyle.sass @@ -0,0 +1,24 @@ +.calendar-column-wrapper + border-right: 1px solid var(--border-light-grey-color) + &:last-child + border-right: none + +.header + position: sticky + z-index: 5 + background-color: var(--default-white) + +.body + position: relative + z-index: 3 + +.color-black + color: var(--font-dark-blue-color) + +.color-grey + color: var(--font-grey-color) + +.footer + border-top: 1px solid var(--border-light-grey-color) + @media(min-height: 1090px) + border-bottom: 1px solid var(--border-light-grey-color) \ No newline at end of file diff --git a/src/pages/newCalendar/mixins/headerMixin.js b/src/pages/newCalendar/mixins/headerMixin.js new file mode 100644 index 0000000..f23fd9d --- /dev/null +++ b/src/pages/newCalendar/mixins/headerMixin.js @@ -0,0 +1,26 @@ +import BaseCalendar from "@/components/base/Calendar/BaseCalendar.vue"; +import { mapState, mapActions } from "vuex"; +import BaseInput from "@/components/base/BaseInput.vue"; + +export const headerMixin = { + components: { BaseInput, BaseCalendar }, + data() { + return { + calendarVisibility: false, + }; + }, + computed: { + ...mapState({ + selectedDates: (state) => state.calendar.selectedDates, + }), + }, + methods: { + ...mapActions({ + getEvents: "getEvents", + changeSelectedDates: "changeSelectedDates", + }), + saveDatesChange() { + this.calendarVisibility = false; + }, + }, +}; diff --git a/src/pages/newCalendar/mixins/headerStyle.sass b/src/pages/newCalendar/mixins/headerStyle.sass new file mode 100644 index 0000000..08370fa --- /dev/null +++ b/src/pages/newCalendar/mixins/headerStyle.sass @@ -0,0 +1,41 @@ +.calendar-header-wrapper + background-color: var(--default-white) + height: 72px + border-radius: 4px + z-index: 10 + +.text + color: var(--font-dark-blue-color) + +.text-grey-color + color: var(--font-grey-color) + +.text-primary + color: var(--font-dark-blue-color-0) !important + +.bg-secondary + background: var(--bg-light-grey) !important + +.q-btn--round + width: 32px !important + height: 32px !important + min-width: 32px !important + min-height: 32px !important + +.q-btn-group :deep(.q-btn-item) + border-radius: 4px !important + +.search :deep(.q-field__marginal) + height: auto !important + +.search :deep(.q-field__prepend) + padding-right: 6px !important + +.search-icon :deep(path) + fill: var(--font-grey-color) + +.calendar-icon :deep(path) + fill: var(--font-dark-blue-color) + +.border-toggle + border: 1px solid var(--gray-secondary) \ No newline at end of file diff --git a/src/pages/newCalendar/mixins/wrapperMixin.js b/src/pages/newCalendar/mixins/wrapperMixin.js new file mode 100644 index 0000000..b406623 --- /dev/null +++ b/src/pages/newCalendar/mixins/wrapperMixin.js @@ -0,0 +1,111 @@ +import { mapState } from "vuex"; +import * as moment from "moment/moment"; +import CalendarBackground from "@/pages/newCalendar/components/CalendarBackground.vue"; +import CalendarClockColumn from "@/pages/newCalendar/components/CalendarClockColumn.vue"; +import { + convertTime, + verifyTime, +} from "@/pages/newCalendar/utils/calendarFunctions.js"; + +export const wrapperMixin = { + props: { + openSidebar: Boolean, + }, + emits: [], + components: { + CalendarBackground, + CalendarClockColumn, + }, + data() { + return { + currentTime: "", + isShownIndicator: true, + timeCoil: [], + timer: null, + pixelsPerHour: 76, + }; + }, + computed: { + ...mapState({ + workingHours: (state) => state.calendar.workingHours, + }), + hours() { + return convertTime(this.currentTime, 0, -6); + }, + minutes() { + return convertTime(this.currentTime, 3, -3); + }, + hoursMinutes() { + return this.currentTime.slice(0, -3); + }, + pixelsPerMinute() { + return this.pixelsPerHour / 60; + }, + validateStartTime() { + return verifyTime(this.workingHours.start); + }, + validateEndTime() { + return verifyTime(this.workingHours.end); + }, + backgroundHeight() { + return ( + (this.validateEndTime - this.validateStartTime) * this.pixelsPerHour + ); + }, + lineIndicatorLocation() { + return { + top: `${this.calculateIndicatorLocation()}px`, + }; + }, + circleIndicatorLocation() { + return { + top: `${this.calculateIndicatorLocation() + 58}px`, + }; + }, + }, + methods: { + changeCurrentTime() { + this.currentTime = moment().format("HH:mm:ss"); + console.log(this.currentTime); + }, + changeTimeCoil() { + this.timeCoil = this.timeCoil.map((elem) => { + if (convertTime(elem, 0, -3) === this.hours) { + return this.hoursMinutes; + } + return elem.slice(0, -3) + ":00"; + }); + }, + startTimer() { + if ( + this.hours >= this.validateStartTime && + this.hours < this.validateEndTime + ) { + this.timer = setInterval(() => { + this.changeCurrentTime(); + this.changeTimeCoil(); + }, 5000); + } + }, + stopTimer() { + clearInterval(this.timer); + this.timer = null; + }, + calculateIndicatorLocation() { + let newTime = this.currentTime + .split(":") + .map((elem) => parseInt(elem, 10)); + let result = + (newTime[0] - this.validateStartTime) * this.pixelsPerHour + + newTime[1] * this.pixelsPerMinute; + if (result > this.backgroundHeight || result < 0) { + this.isShownIndicator = false; + return 0; + } + return result; + }, + }, + beforeUnmount() { + this.stopTimer(); + }, +}; diff --git a/src/pages/newCalendar/mixins/wrapperStyle.sass b/src/pages/newCalendar/mixins/wrapperStyle.sass new file mode 100644 index 0000000..47883f0 --- /dev/null +++ b/src/pages/newCalendar/mixins/wrapperStyle.sass @@ -0,0 +1,44 @@ +.schedule-body + overflow-x: auto + border-top-left-radius: 4px + border-top-right-radius: 4px + &::-webkit-scrollbar-track:horizontal + margin: 0 24px 0 24px + +.background + background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgba(0,212,255,1) 100%) + +.time-coil-wrapper + position: sticky + z-index: 5 + background-color: var(--default-white) + padding-top: 52px + +.column-wrapper + height: 60px + position: relative + background-color: var(--default-white) + +.footer + border-bottom-left-radius: 4px + border-bottom-right-radius: 4px + +.border-bottom + border-bottom: 4px solid var(--bg-ligth-blue-color) + +.records-count + border-right: 1px solid var(--border-light-grey-color) + &:last-child + border-right: none + +.border-top + border-top: 1px solid var(--border-light-grey-color) + +.time-circle-indicator + background-color: var(--bg-event-red-color) + z-index: 5 + +.time-line-indicator + border-top: 1px solid var(--bg-event-red-color) + z-index: 4 + width: calc(100% - 80px) \ No newline at end of file diff --git a/src/pages/newCalendar/utils/calendarConfig.js b/src/pages/newCalendar/utils/calendarConfig.js index 05c8366..17450df 100644 --- a/src/pages/newCalendar/utils/calendarConfig.js +++ b/src/pages/newCalendar/utils/calendarConfig.js @@ -779,15 +779,15 @@ export const services = [ export const recordList = [ { id: "c3df0a95-8093-41f1-9584-5b70ee05e71c", - start: "2023-07-05T10:00:00Z", - end: "2023-07-05T11:00:00Z", + start: "2023-09-18T10:00:00Z", + end: "2023-09-18T11:00:00Z", employee: { id: "464101e6-b4e6-46a4-8ef6-08ecb2921493", last_name: "Каневский", first_name: "Леонид", patronymic: "Семенович", }, - member: { + person: { id: "3e6e54e4-2706-47d3-8b54-b841ee8f0943", last_name: "Харитонова", first_name: "Ольга", @@ -824,15 +824,15 @@ export const recordList = [ }, { id: "ba931000-7140-4977-bd09-1ac212b8b8e5", - start: "2023-07-06T15:00:00Z", - end: "2023-07-06T15:30:00Z", + start: "2023-09-18T15:00:00Z", + end: "2023-09-18T15:30:00Z", employee: { id: "464101e6-b4e6-46a4-8ef6-08ecb2921493", last_name: "Каневский", first_name: "Леонид", patronymic: "Семенович", }, - member: { + person: { id: "d340d344-4fc7-4fbe-9db8-b7562b70438d", last_name: "Гаранова", first_name: "Наталья", @@ -877,16 +877,16 @@ export const recordList = [ ], }, { - id: "4cd94bec-a0df-4a18-879d-f64cd6d7098e", - start: "2023-07-03T13:00:00Z", - end: "2023-07-03T14:30:00Z", + id: "4cd94bec-a0df-4a18-879d-f64cd6d5698e", + start: "2023-09-18T13:00:00Z", + end: "2023-09-18T14:30:00Z", employee: { id: "464101e6-b4e6-46a4-8ef6-08ecb2921493", - last_name: "Каневский", - first_name: "Леонид", + last_name: "Гурцев", + first_name: "Семен", patronymic: "Семенович", }, - member: { + person: { id: "0b2d1db1-6aab-4e29-b857-fc7c9777280f", last_name: "Харитонова", first_name: "Ольга", @@ -930,6 +930,105 @@ export const recordList = [ }, ], }, + // { + // id: "ba931000-7140-4977-bd09-1ac233b8b8e5", + // start: "2023-09-18T15:00:00Z", + // end: "2023-09-18T15:30:00Z", + // employee: { + // id: "464101e6-b4e6-46a4-8ef6-08ecb2921493", + // last_name: "Лебедев", + // first_name: "Леонид", + // patronymic: "Семенович", + // }, + // person: { + // id: "d340d344-4fc7-4fbe-9db8-b7562b70438d", + // last_name: "Гаранова", + // first_name: "Наталья", + // patronymic: "Романовна", + // birth_date: "1990-04-12", + // photo: personImage, + // contacts: [ + // { + // value: "+7 (910) 424–13–13", + // kind: "PHONE", + // }, + // { + // value: "Haritonich@mail.ru", + // kind: "EMAIL", + // }, + // ], + // }, + // status: "accepted", + // medicalCard: { + // status: "not_filled", + // }, + // }, + // { + // id: "ba931000-7140-4977-bd09-1ac233b8b8e5", + // start: "2023-09-18T15:00:00Z", + // end: "2023-09-18T15:30:00Z", + // employee: { + // id: "464101e6-b4e6-46a4-8ef6-08ecb1121493", + // last_name: "Петров", + // first_name: "Леонид", + // patronymic: "Семенович", + // }, + // person: { + // id: "d340d344-4fc7-4fbe-9db8-b7562b70438d", + // last_name: "Гаранова", + // first_name: "Наталья", + // patronymic: "Романовна", + // birth_date: "1990-04-12", + // photo: personImage, + // contacts: [ + // { + // value: "+7 (910) 424–13–13", + // kind: "PHONE", + // }, + // { + // value: "Haritonich@mail.ru", + // kind: "EMAIL", + // }, + // ], + // }, + // status: "accepted", + // medicalCard: { + // status: "not_filled", + // }, + // }, + // { + // id: "ba931000-7140-4977-bd09-1ac233b8b8e5", + // start: "2023-09-18T15:00:00Z", + // end: "2023-09-18T15:30:00Z", + // employee: { + // id: "464101e6-b4e6-46a4-8ef6-22ecb2921493", + // last_name: "Ленин", + // first_name: "Леонид", + // patronymic: "Семенович", + // }, + // person: { + // id: "d340d344-4fc7-4fbe-9db8-b7562b70438d", + // last_name: "Гаранова", + // first_name: "Наталья", + // patronymic: "Романовна", + // birth_date: "1990-04-12", + // photo: personImage, + // contacts: [ + // { + // value: "+7 (910) 424–13–13", + // kind: "PHONE", + // }, + // { + // value: "Haritonich@mail.ru", + // kind: "EMAIL", + // }, + // ], + // }, + // status: "accepted", + // medicalCard: { + // status: "not_filled", + // }, + // }, ]; export const recordPreviewConfig = [ diff --git a/src/store/index.js b/src/store/index.js index b32e450..b0ecdf5 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -8,6 +8,7 @@ export default createStore({ imgUrl: "https://astra-dev.dopcore.com/api/store/", routingHistory: window.history, userData: {}, + calendarShape: "manager", }, modules: { medical,