WIP Разделила календари
This commit is contained in:
BIN
src/assets/images/doctor.png
Normal file
BIN
src/assets/images/doctor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
@@ -2,7 +2,10 @@
|
|||||||
.w-full.flex
|
.w-full.flex
|
||||||
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")
|
component.ml-2(
|
||||||
|
v-bind:is="calendarComponent",
|
||||||
|
:open-sidebar="isOpen",
|
||||||
|
)
|
||||||
base-modal(v-model="isShowForm", title="Создание записи", modal-padding)
|
base-modal(v-model="isShowForm", title="Создание записи", modal-padding)
|
||||||
create-event-form(:close-form="closeForm")
|
create-event-form(:close-form="closeForm")
|
||||||
base-modal(v-model="previewVisibility", :hideHeader="true", :modalPadding="true")
|
base-modal(v-model="previewVisibility", :hideHeader="true", :modalPadding="true")
|
||||||
@@ -12,7 +15,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import CalendarSidebar from "@/pages/newCalendar/components/CalendarSidebar";
|
import CalendarSidebar from "@/pages/newCalendar/components/CalendarSidebar";
|
||||||
import CalendarOpenSidebar from "@/pages/newCalendar/components/CalendarOpenSidebar";
|
import CalendarOpenSidebar from "@/pages/newCalendar/components/CalendarOpenSidebar";
|
||||||
import CalendarWrapper from "@/pages/newCalendar/components/CalendarWrapper";
|
import DoctorCalendarWrapper from "@/pages/newCalendar/components/doctorCalendar/CalendarWrapper";
|
||||||
|
import ManagerCalendarWrapper from "@/pages/newCalendar/components/managerCalendar/CalendarWrapper";
|
||||||
import CreateEventForm from "@/pages/newCalendar/components/CreateEventForm";
|
import CreateEventForm from "@/pages/newCalendar/components/CreateEventForm";
|
||||||
import * as moment from "moment/moment";
|
import * as moment from "moment/moment";
|
||||||
import BaseModal from "@/components/base/BaseModal.vue";
|
import BaseModal from "@/components/base/BaseModal.vue";
|
||||||
@@ -23,7 +27,8 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
CalendarSidebar,
|
CalendarSidebar,
|
||||||
CalendarOpenSidebar,
|
CalendarOpenSidebar,
|
||||||
CalendarWrapper,
|
DoctorCalendarWrapper,
|
||||||
|
ManagerCalendarWrapper,
|
||||||
CreateEventForm,
|
CreateEventForm,
|
||||||
BaseModal,
|
BaseModal,
|
||||||
CalendarRecordPreview,
|
CalendarRecordPreview,
|
||||||
@@ -40,7 +45,13 @@ export default {
|
|||||||
...mapState({
|
...mapState({
|
||||||
selectedRecordId: (state) => state.calendar.selectedRecordId,
|
selectedRecordId: (state) => state.calendar.selectedRecordId,
|
||||||
selectedDates: (state) => state.calendar.selectedDates,
|
selectedDates: (state) => state.calendar.selectedDates,
|
||||||
|
calendarShape: (state) => state.calendarShape,
|
||||||
}),
|
}),
|
||||||
|
calendarComponent() {
|
||||||
|
return this.calendarShape === "doctor"
|
||||||
|
? "doctor-calendar-wrapper"
|
||||||
|
: "manager-calendar-wrapper";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openSidebar() {
|
openSidebar() {
|
||||||
@@ -72,11 +83,14 @@ export default {
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true,
|
deep: true,
|
||||||
handler(value) {
|
handler(value) {
|
||||||
|
console.log("отработало в роутинге", this.$route.path === "/calendar");
|
||||||
if (this.$route.path === "/calendar") {
|
if (this.$route.path === "/calendar") {
|
||||||
|
let dateType = this.calendarShape === "doctor" ? "week" : "day";
|
||||||
if (!value?.start || !value?.end) {
|
if (!value?.start || !value?.end) {
|
||||||
|
console.log("тут 1");
|
||||||
this.changeSelectedDates({
|
this.changeSelectedDates({
|
||||||
from: moment().clone().startOf("week"),
|
from: moment().clone().startOf(dateType),
|
||||||
to: moment().clone().endOf("week"),
|
to: moment().clone().endOf(dateType),
|
||||||
});
|
});
|
||||||
this.$router.replace({
|
this.$router.replace({
|
||||||
query: {
|
query: {
|
||||||
@@ -87,12 +101,18 @@ export default {
|
|||||||
} else if (
|
} else if (
|
||||||
value?.start !== this.selectedDates?.from?.format("DD.MM.YYYY") ||
|
value?.start !== this.selectedDates?.from?.format("DD.MM.YYYY") ||
|
||||||
value?.end !== this.selectedDates?.to?.format("DD.MM.YYYY")
|
value?.end !== this.selectedDates?.to?.format("DD.MM.YYYY")
|
||||||
)
|
) {
|
||||||
|
console.log(
|
||||||
|
"тут 2",
|
||||||
|
value?.start !== this.selectedDates?.from?.format("DD.MM.YYYY"),
|
||||||
|
value?.end !== this.selectedDates?.to?.format("DD.MM.YYYY")
|
||||||
|
);
|
||||||
this.changeSelectedDates({
|
this.changeSelectedDates({
|
||||||
from: this.convertDate(value?.start),
|
from: this.convertDate(value?.start),
|
||||||
to: this.convertDate(value?.end),
|
to: this.convertDate(value?.end),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
selectedDates: {
|
selectedDates: {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export default {
|
|||||||
timeCoil: Array,
|
timeCoil: Array,
|
||||||
currentTime: String,
|
currentTime: String,
|
||||||
dayEndTime: Number,
|
dayEndTime: Number,
|
||||||
isCurrentWeek: Boolean,
|
isCurrent: Boolean,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentHour() {
|
currentHour() {
|
||||||
@@ -33,7 +33,7 @@ export default {
|
|||||||
if (
|
if (
|
||||||
convertTime(elem, 0, 3) === this.currentHour &&
|
convertTime(elem, 0, 3) === this.currentHour &&
|
||||||
!this.isEndDay &&
|
!this.isEndDay &&
|
||||||
this.isCurrentWeek
|
this.isCurrent
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
"current-time": true,
|
"current-time": true,
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
<template lang="pug">
|
|
||||||
.calendar-column-wrapper.flex.flex-col
|
|
||||||
.header.flex.flex-col.items-center.justify-center.top-0.pt-3.pb-10px
|
|
||||||
span.font-bold.text-base.color-black {{ date?.format("D MMMM")}}
|
|
||||||
span.text-smm.color-grey {{ transformDayName(date?.format("dddd"))}}
|
|
||||||
.body.h-full.px-1.py-1
|
|
||||||
calendar-record-card(
|
|
||||||
v-for="record in filteredRecords",
|
|
||||||
:key="record?.id",
|
|
||||||
:record="record",
|
|
||||||
:expanded-type="expandedDisplayType",
|
|
||||||
:style="eventCardPosition(record.start, record.end)",
|
|
||||||
@click="changeSelectedRecordId(record?.id)",
|
|
||||||
)
|
|
||||||
.footer.flex.items-center.justify-center.bg-white.h-9(v-if="!expandedDisplayType")
|
|
||||||
span.text-smm.color-grey 0 записей
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import * as moment from "moment/moment";
|
|
||||||
import CalendarRecordCard from "@/pages/newCalendar/components/CalendarRecordCard.vue";
|
|
||||||
import { verifyTime } from "@/pages/newCalendar/utils/calendarFunctions.js";
|
|
||||||
import { mapActions, mapState } from "vuex";
|
|
||||||
export default {
|
|
||||||
name: "CalendarColumn",
|
|
||||||
components: { CalendarRecordCard },
|
|
||||||
props: {
|
|
||||||
date: Object,
|
|
||||||
expandedDisplayType: Boolean,
|
|
||||||
dayEndTime: Number,
|
|
||||||
dayStartTime: Number,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pixelsPerHour: 76,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapState({
|
|
||||||
events: (state) => state.calendar.events || [],
|
|
||||||
}),
|
|
||||||
filteredRecords() {
|
|
||||||
return this.events.filter(
|
|
||||||
(elem) =>
|
|
||||||
moment.parseZone(elem.start).format("YYYY-MM-DD") ===
|
|
||||||
this.date.format("YYYY-MM-DD")
|
|
||||||
);
|
|
||||||
},
|
|
||||||
pixelsPerMinute() {
|
|
||||||
return this.pixelsPerHour / 60;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions({
|
|
||||||
changeSelectedRecordId: "changeSelectedRecordId",
|
|
||||||
}),
|
|
||||||
transformDayName(name) {
|
|
||||||
return name[0]?.toUpperCase() + name?.slice(1);
|
|
||||||
},
|
|
||||||
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`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="sass" scoped>
|
|
||||||
.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)
|
|
||||||
</style>
|
|
||||||
@@ -33,12 +33,12 @@
|
|||||||
.flex.gap-x-14(:class="bodyClass")
|
.flex.gap-x-14(:class="bodyClass")
|
||||||
.flex.gap-x-2.items-center(
|
.flex.gap-x-2.items-center(
|
||||||
v-for="contact in contacts",
|
v-for="contact in contacts",
|
||||||
:key="contact.value",
|
:key="contact?.value",
|
||||||
)
|
)
|
||||||
q-icon.network-icon(:name="contact.icon", size="16px")
|
q-icon.network-icon(:name="contact?.icon", size="16px")
|
||||||
.text-xxs.cursor-default {{ contact.value }}
|
.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(
|
.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
|
) +1
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.calendar-column-wrapper.flex.flex-col
|
||||||
|
.header.flex.flex-col.items-center.justify-center.top-0.pt-3.pb-10px
|
||||||
|
span.font-bold.text-base.color-black {{ date?.format("D MMMM")}}
|
||||||
|
span.text-smm.color-grey {{ transformDayName(date?.format("dddd"))}}
|
||||||
|
.body.h-full.px-1.py-1
|
||||||
|
calendar-record-card(
|
||||||
|
v-for="record in filteredRecords",
|
||||||
|
:key="record?.id",
|
||||||
|
:record="record",
|
||||||
|
:expanded-type="expandedDisplayType",
|
||||||
|
:style="eventCardPosition(record.start, record.end)",
|
||||||
|
@click="changeSelectedRecordId(record?.id)",
|
||||||
|
)
|
||||||
|
.footer.flex.items-center.justify-center.bg-white.h-9(v-if="!expandedDisplayType")
|
||||||
|
span.text-smm.color-grey 0 записей
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as moment from "moment/moment";
|
||||||
|
import { columnMixin } from "@/pages/newCalendar/mixins/columnMixin.js";
|
||||||
|
export default {
|
||||||
|
name: "CalendarColumn",
|
||||||
|
mixins: [columnMixin],
|
||||||
|
props: {
|
||||||
|
date: Object,
|
||||||
|
expandedDisplayType: Boolean,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
filteredRecords() {
|
||||||
|
return this.events.filter(
|
||||||
|
(elem) =>
|
||||||
|
moment.parseZone(elem.start).format("YYYY-MM-DD") ===
|
||||||
|
this.date.format("YYYY-MM-DD")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
transformDayName(name) {
|
||||||
|
return name[0]?.toUpperCase() + name?.slice(1);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="sass" scoped>
|
||||||
|
@import "@/pages/newCalendar/mixins/columnStyle.sass"
|
||||||
|
</style>
|
||||||
@@ -74,15 +74,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import BaseCalendar from "@/components/base/Calendar/BaseCalendar.vue";
|
|
||||||
import { mapState, mapActions } from "vuex";
|
|
||||||
import { v_model } from "@/shared/mixins/v-model";
|
import { v_model } from "@/shared/mixins/v-model";
|
||||||
import DateSwitcherSvg from "@/pages/newCalendar/components/CalendarDateSwitcherSvg.vue";
|
import DateSwitcherSvg from "@/pages/newCalendar/components/CalendarDateSwitcherSvg.vue";
|
||||||
import BaseInput from "@/components/base/BaseInput.vue";
|
import { headerMixin } from "@/pages/newCalendar/mixins/headerMixin.js";
|
||||||
export default {
|
export default {
|
||||||
name: "CalendarHeader",
|
name: "CalendarHeader",
|
||||||
mixins: [v_model],
|
mixins: [v_model, headerMixin],
|
||||||
components: { BaseInput, BaseCalendar, DateSwitcherSvg },
|
components: { DateSwitcherSvg },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
displayTypesList: [
|
displayTypesList: [
|
||||||
@@ -99,7 +97,6 @@ export default {
|
|||||||
from: null,
|
from: null,
|
||||||
to: null,
|
to: null,
|
||||||
},
|
},
|
||||||
calendarVisibility: false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -108,9 +105,6 @@ export default {
|
|||||||
"D MMMM YYYY"
|
"D MMMM YYYY"
|
||||||
)} — ${this.dates?.to?.format("D MMMM YYYY")}`;
|
)} — ${this.dates?.to?.format("D MMMM YYYY")}`;
|
||||||
},
|
},
|
||||||
...mapState({
|
|
||||||
selectedDates: (state) => state.calendar.selectedDates,
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
previousWeek() {
|
previousWeek() {
|
||||||
@@ -123,13 +117,6 @@ export default {
|
|||||||
this.dates.from = this.dates.from.clone().add(diff, "day");
|
this.dates.from = this.dates.from.clone().add(diff, "day");
|
||||||
this.dates.to = this.dates.to.clone().add(diff, "day");
|
this.dates.to = this.dates.to.clone().add(diff, "day");
|
||||||
},
|
},
|
||||||
...mapActions({
|
|
||||||
changeSelectedDates: "changeSelectedDates",
|
|
||||||
getEvents: "getEvents",
|
|
||||||
}),
|
|
||||||
saveDatesChange() {
|
|
||||||
this.calendarVisibility = false;
|
|
||||||
},
|
|
||||||
initializeDates() {
|
initializeDates() {
|
||||||
this.dates = {
|
this.dates = {
|
||||||
from: this.selectedDates.from.clone(),
|
from: this.selectedDates.from.clone(),
|
||||||
@@ -164,50 +151,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass" scoped>
|
<style lang="sass" scoped>
|
||||||
.calendar-header-wrapper
|
@import "@/pages/newCalendar/mixins/headerStyle.sass"
|
||||||
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)
|
|
||||||
|
|
||||||
.active-toggle
|
|
||||||
background: var(--btn-blue-color)
|
|
||||||
|
|
||||||
.border-toggle
|
|
||||||
border: 1px solid var(--gray-secondary)
|
|
||||||
</style>
|
</style>
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
.q-field--outlined.q-field--readonly .q-field__control:before
|
.q-field--outlined.q-field--readonly .q-field__control:before
|
||||||
@@ -18,11 +18,11 @@
|
|||||||
:style="expandedDisplayType ? backgroundWrapperWidth : {}",
|
:style="expandedDisplayType ? backgroundWrapperWidth : {}",
|
||||||
:class="{'border-bottom': expandedDisplayType}"
|
:class="{'border-bottom': expandedDisplayType}"
|
||||||
)
|
)
|
||||||
.time-coil-wrapper.left-0.-mt-12
|
.time-coil-wrapper.left-0.-mt-16
|
||||||
calendar-clock-column(
|
calendar-clock-column(
|
||||||
:time-coil="timeCoil",
|
:time-coil="timeCoil",
|
||||||
:current-time="currentTime",
|
:current-time="currentTime",
|
||||||
:is-current-week="isCurrentWeek",
|
:is-current="isCurrentWeek",
|
||||||
:day-end-time="validateEndTime"
|
:day-end-time="validateEndTime"
|
||||||
)
|
)
|
||||||
.time-circle-indicator.left-74px.h-3.w-3.rounded-full.absolute(
|
.time-circle-indicator.left-74px.h-3.w-3.rounded-full.absolute(
|
||||||
@@ -38,63 +38,39 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CalendarHeader from "@/pages/newCalendar/components/CalendarHeader";
|
import CalendarHeader from "@/pages/newCalendar/components/doctorCalendar/CalendarHeader";
|
||||||
import CalendarBackground from "@/pages/newCalendar/components/CalendarBackground.vue";
|
import CalendarColumn from "@/pages/newCalendar/components/doctorCalendar/CalendarColumn.vue";
|
||||||
import CalendarClockColumn from "@/pages/newCalendar/components/CalendarClockColumn.vue";
|
import { mapState } from "vuex";
|
||||||
import CalendarColumn from "@/pages/newCalendar/components/CalendarColumn.vue";
|
|
||||||
import {
|
|
||||||
convertTime,
|
|
||||||
verifyTime,
|
|
||||||
} from "@/pages/newCalendar/utils/calendarFunctions.js";
|
|
||||||
import { mapState, mapActions } from "vuex";
|
|
||||||
import * as moment from "moment/moment";
|
import * as moment from "moment/moment";
|
||||||
|
import { wrapperMixin } from "@/pages/newCalendar/mixins/wrapperMixin.js";
|
||||||
export default {
|
export default {
|
||||||
name: "CalendarWrapper",
|
name: "CalendarWrapper",
|
||||||
components: {
|
components: {
|
||||||
CalendarHeader,
|
CalendarHeader,
|
||||||
CalendarBackground,
|
|
||||||
CalendarClockColumn,
|
|
||||||
CalendarColumn,
|
CalendarColumn,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
openSidebar: Boolean,
|
openSidebar: Boolean,
|
||||||
},
|
},
|
||||||
|
mixins: [wrapperMixin],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
displayType: "expanded",
|
displayType: "expanded",
|
||||||
currentTime: "",
|
|
||||||
isCurrentWeek: true,
|
isCurrentWeek: true,
|
||||||
isShownIndicator: true,
|
|
||||||
timeCoil: [],
|
|
||||||
timer: null,
|
|
||||||
pixelsPerHour: 76,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
workingHours: (state) => state.calendar.workingHours,
|
|
||||||
selectedDates: (state) => state.calendar.selectedDates,
|
selectedDates: (state) => state.calendar.selectedDates,
|
||||||
}),
|
}),
|
||||||
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;
|
|
||||||
},
|
|
||||||
backgroundHeight() {
|
|
||||||
return (
|
|
||||||
(this.validateEndTime - this.validateStartTime) * this.pixelsPerHour
|
|
||||||
);
|
|
||||||
},
|
|
||||||
expandedDisplayType() {
|
expandedDisplayType() {
|
||||||
return this.displayType === "expanded";
|
return this.displayType === "expanded";
|
||||||
},
|
},
|
||||||
|
backgroundWrapperWidth() {
|
||||||
|
return {
|
||||||
|
width: `${380 * this.dateRange.length + 80}px`,
|
||||||
|
};
|
||||||
|
},
|
||||||
dateRange() {
|
dateRange() {
|
||||||
let diff = this.selectedDates?.to.diff(this.selectedDates?.from, "days");
|
let diff = this.selectedDates?.to.diff(this.selectedDates?.from, "days");
|
||||||
let range = [];
|
let range = [];
|
||||||
@@ -103,12 +79,6 @@ export default {
|
|||||||
}
|
}
|
||||||
return range;
|
return range;
|
||||||
},
|
},
|
||||||
validateStartTime() {
|
|
||||||
return verifyTime(this.workingHours.start);
|
|
||||||
},
|
|
||||||
validateEndTime() {
|
|
||||||
return verifyTime(this.workingHours.end);
|
|
||||||
},
|
|
||||||
columnHeight() {
|
columnHeight() {
|
||||||
return this.expandedDisplayType
|
return this.expandedDisplayType
|
||||||
? {
|
? {
|
||||||
@@ -133,29 +103,9 @@ export default {
|
|||||||
: "calc(100vw - 160px - 80px)",
|
: "calc(100vw - 160px - 80px)",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
backgroundWrapperWidth() {
|
|
||||||
return {
|
|
||||||
width: `${380 * this.dateRange.length + 80}px`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
lineIndicatorLocation() {
|
|
||||||
return {
|
|
||||||
top: `${this.calculateIndicatorLocation()}px`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
circleIndicatorLocation() {
|
|
||||||
return {
|
|
||||||
top: `${this.calculateIndicatorLocation() + 42}px`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions({
|
//вынести в функции
|
||||||
getEvents: "getEvents",
|
|
||||||
}),
|
|
||||||
changeCurrentTime() {
|
|
||||||
this.currentTime = moment().format("HH:mm:ss");
|
|
||||||
},
|
|
||||||
timeCoilInitialization() {
|
timeCoilInitialization() {
|
||||||
this.timeCoil = [];
|
this.timeCoil = [];
|
||||||
for (let i = this.validateStartTime; i < this.validateEndTime; i++) {
|
for (let i = this.validateStartTime; i < this.validateEndTime; i++) {
|
||||||
@@ -168,44 +118,9 @@ export default {
|
|||||||
} else this.timeCoil.push(`${i}:00`);
|
} else this.timeCoil.push(`${i}:00`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
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;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
//вынести в примеси и использовать timeCoilInitialization как функцию
|
||||||
currentTime() {
|
currentTime() {
|
||||||
if (
|
if (
|
||||||
this.hours === this.validateEndTime &&
|
this.hours === this.validateEndTime &&
|
||||||
@@ -220,8 +135,8 @@ export default {
|
|||||||
deep: true,
|
deep: true,
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
this.isCurrentWeek =
|
this.isCurrentWeek =
|
||||||
newValue?.from.isSame(moment().clone().startOf("week")) &&
|
newValue?.from.isSame(moment().clone().startOf("week"), "day") &&
|
||||||
newValue?.to.isSame(moment().clone().endOf("week"));
|
newValue?.to.isSame(moment().clone().endOf("week"), "day");
|
||||||
this.isShownIndicator = this.isCurrentWeek;
|
this.isShownIndicator = this.isCurrentWeek;
|
||||||
if (this.timer) {
|
if (this.timer) {
|
||||||
this.stopTimer();
|
this.stopTimer();
|
||||||
@@ -238,57 +153,10 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.changeCurrentTime();
|
this.changeCurrentTime();
|
||||||
this.timeCoilInitialization();
|
this.timeCoilInitialization();
|
||||||
this.startTimer();
|
|
||||||
},
|
|
||||||
beforeUnmount() {
|
|
||||||
this.stopTimer();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass" scoped>
|
<style lang="sass" scoped>
|
||||||
.schedule-body
|
@import "@/pages/newCalendar/mixins/wrapperStyle.sass"
|
||||||
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: 38px
|
|
||||||
|
|
||||||
.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)
|
|
||||||
</style>
|
</style>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.calendar-column-wrapper.flex.flex-col
|
||||||
|
.header.flex.items-center.justify-between.top-0.py-2.px-6
|
||||||
|
.flex.h-full.items-center.h-11
|
||||||
|
q-avatar.mr-2(
|
||||||
|
size="40px",
|
||||||
|
round
|
||||||
|
)
|
||||||
|
img(:src="employee?.photo || defaultPhoto", alt="doctor")
|
||||||
|
.flex.flex-col.justify-between
|
||||||
|
span.text-dark {{trimName(employee?.last_name, employee?.first_name, employee?.patronymic)}}
|
||||||
|
span.text-xsx.color-grey {{employee?.job || "Терапевт"}}
|
||||||
|
button(@click="locked = !locked")
|
||||||
|
q-icon.lock-icon(
|
||||||
|
:name="locked ? 'app:lock' : 'app:lock-open'",
|
||||||
|
size="24px"
|
||||||
|
)
|
||||||
|
.body.h-full.px-1.py-1
|
||||||
|
calendar-record-card(
|
||||||
|
v-for="record in filteredRecords",
|
||||||
|
:key="record?.id",
|
||||||
|
:record="record",
|
||||||
|
:expanded-type="true",
|
||||||
|
:style="eventCardPosition(record.start, record.end)",
|
||||||
|
@click="changeSelectedRecordId(record?.id)",
|
||||||
|
)
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { columnMixin } from "@/pages/newCalendar/mixins/columnMixin.js";
|
||||||
|
import { trimName } from "@/pages/newCalendar/utils/calendarFunctions.js";
|
||||||
|
import { recordList } from "@/pages/newCalendar/utils/calendarConfig";
|
||||||
|
import doctorAvatar from "@/assets/images/doctor.png";
|
||||||
|
export default {
|
||||||
|
name: "CalendarColumn",
|
||||||
|
mixins: [columnMixin],
|
||||||
|
props: {
|
||||||
|
employee: Object,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
trimName: trimName,
|
||||||
|
configEvents: recordList,
|
||||||
|
defaultPhoto: doctorAvatar,
|
||||||
|
locked: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
filteredRecords() {
|
||||||
|
// return this.configEvents.filter(
|
||||||
|
// (elem) => elem?.employee?.id === this.employee?.id
|
||||||
|
// );
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="sass" scoped>
|
||||||
|
@import "@/pages/newCalendar/mixins/columnStyle.sass"
|
||||||
|
.lock-icon :deep(path)
|
||||||
|
fill: var(--font-grey-color)
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.calendar-header-wrapper.w-full.flex.items-center.p-4.justify-between
|
||||||
|
base-input.search(
|
||||||
|
iconLeft,
|
||||||
|
:width="280",
|
||||||
|
size="M",
|
||||||
|
placeholder="Найти ...",
|
||||||
|
icon-left
|
||||||
|
)
|
||||||
|
template(v-slot:iconLeft)
|
||||||
|
q-icon.search-icon(name="app:search", size="20px")
|
||||||
|
.flex.gap-x-4.items-center.justify-center
|
||||||
|
q-btn(
|
||||||
|
color="secondary",
|
||||||
|
round,
|
||||||
|
size="14px",
|
||||||
|
dense,
|
||||||
|
icon="arrow_back_ios_new",
|
||||||
|
text-color="primary",
|
||||||
|
padding="2px 11px 2px 8px",
|
||||||
|
@click="previousDate"
|
||||||
|
)
|
||||||
|
base-input.search(
|
||||||
|
size="M"
|
||||||
|
:width="332",
|
||||||
|
v-model="currentDate",
|
||||||
|
)
|
||||||
|
.h-5.w-5.flex.items-center.justify-center.ml-3
|
||||||
|
q-icon.calendar-icon.text.cursor-pointer(
|
||||||
|
:name="calendarVisibility ? 'app:cancel-mini' : 'app:calendar'",
|
||||||
|
size="20px",
|
||||||
|
)
|
||||||
|
q-menu(
|
||||||
|
:style="{'margin-top': '8px !important'}"
|
||||||
|
v-model="calendarVisibility",
|
||||||
|
transition-show="scale",
|
||||||
|
transition-hide="scale"
|
||||||
|
self="top middle",
|
||||||
|
:offset="[130, 8]"
|
||||||
|
)
|
||||||
|
base-calendar(
|
||||||
|
v-model="date",
|
||||||
|
:save="saveDatesChange",
|
||||||
|
:start-year="2000"
|
||||||
|
)
|
||||||
|
q-btn(
|
||||||
|
color="secondary",
|
||||||
|
icon="arrow_forward_ios",
|
||||||
|
round,
|
||||||
|
size="14px",
|
||||||
|
text-color="primary",
|
||||||
|
dense,
|
||||||
|
@click="nextDate"
|
||||||
|
)
|
||||||
|
.h-10.p-1.flex.items-center.justify-between.bg-secondary.rounded.text-grey-color.ml-52.border
|
||||||
|
q-btn-toggle(
|
||||||
|
v-model="value",
|
||||||
|
:options="displayTypesList",
|
||||||
|
no-caps,
|
||||||
|
padding="0px 12px"
|
||||||
|
)
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { v_model } from "@/shared/mixins/v-model";
|
||||||
|
import { headerMixin } from "@/pages/newCalendar/mixins/headerMixin.js";
|
||||||
|
export default {
|
||||||
|
name: "CalendarHeader",
|
||||||
|
mixins: [v_model, headerMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
displayTypesList: [
|
||||||
|
{
|
||||||
|
value: "day",
|
||||||
|
label: "День",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "week",
|
||||||
|
label: "Неделя",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
date: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentDate() {
|
||||||
|
return this.date?.format("D MMMM YYYY");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
previousDate() {
|
||||||
|
this.date = this.date?.clone()?.subtract(1, "day");
|
||||||
|
},
|
||||||
|
nextDate() {
|
||||||
|
this.date = this.date?.clone()?.add(1, "day");
|
||||||
|
},
|
||||||
|
initializeDates() {
|
||||||
|
this.date = this.selectedDates.from.clone();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
date: {
|
||||||
|
deep: true,
|
||||||
|
handler(val) {
|
||||||
|
if (!val?.isSame(this.selectedDates?.from, "day"))
|
||||||
|
this.changeSelectedDates({
|
||||||
|
from: val,
|
||||||
|
to: val?.clone()?.endOf("day"),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selectedDates: {
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
console.log(!val?.from.isSame(this.date, "day"), this.date);
|
||||||
|
if (!val?.from.isSame(this.date, "day")) this.initializeDates();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="sass" scoped>
|
||||||
|
@import "@/pages/newCalendar/mixins/headerStyle.sass"
|
||||||
|
.q-btn-toggle :deep(span)
|
||||||
|
font-weight: 500
|
||||||
|
.q-btn-toggle :deep(.q-btn-item)
|
||||||
|
height: 32px
|
||||||
|
</style>
|
||||||
|
<style lang="sass">
|
||||||
|
.q-field--outlined.q-field--readonly .q-field__control:before
|
||||||
|
border-style: solid !important
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.schedule.flex-1.flex.flex-col.relative(
|
||||||
|
:style="{width: openSidebar ? 'calc(100vw - 320px)' : 'calc(100vw - 160px)'}"
|
||||||
|
)
|
||||||
|
calendar-header.w-full.mb-1(v-model="displayType")
|
||||||
|
.schedule-body.h-full.bg-white.w-full
|
||||||
|
.column-wrapper.flex.ml-20(:style="columnWrapperWidth")
|
||||||
|
calendar-column(
|
||||||
|
v-for="employee in filteringEmployees",
|
||||||
|
:key="employee?.id",
|
||||||
|
:employee="employee",
|
||||||
|
:style="columnStyle",
|
||||||
|
:expanded-display-type="true",
|
||||||
|
:day-start-time="validateStartTime"
|
||||||
|
:day-end-time="validateEndTime"
|
||||||
|
)
|
||||||
|
.flex.relative.border-bottom(
|
||||||
|
:style="backgroundWrapperWidth",
|
||||||
|
)
|
||||||
|
.time-coil-wrapper.left-0.-mt-16
|
||||||
|
calendar-clock-column(
|
||||||
|
:time-coil="timeCoil",
|
||||||
|
:current-time="currentTime",
|
||||||
|
:is-current="isCurrentDate",
|
||||||
|
:day-end-time="validateEndTime"
|
||||||
|
)
|
||||||
|
.time-circle-indicator.left-74px.h-3.w-3.rounded-full.absolute(
|
||||||
|
v-if="isShownIndicator",
|
||||||
|
:style="circleIndicatorLocation"
|
||||||
|
)
|
||||||
|
span.time-line-indicator.block.left-20.absolute(
|
||||||
|
v-if="isShownIndicator",
|
||||||
|
:style="lineIndicatorLocation"
|
||||||
|
)
|
||||||
|
calendar-background.flex-1
|
||||||
|
.w-full.h-3.bg-white.footer
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CalendarHeader from "@/pages/newCalendar/components/managerCalendar/CalendarHeader";
|
||||||
|
import CalendarColumn from "@/pages/newCalendar/components/managerCalendar/CalendarColumn.vue";
|
||||||
|
import { mapState } from "vuex";
|
||||||
|
import * as moment from "moment/moment";
|
||||||
|
import { wrapperMixin } from "@/pages/newCalendar/mixins/wrapperMixin.js";
|
||||||
|
import { recordList } from "@/pages/newCalendar/utils/calendarConfig";
|
||||||
|
export default {
|
||||||
|
name: "CalendarWrapper",
|
||||||
|
components: {
|
||||||
|
CalendarHeader,
|
||||||
|
CalendarColumn,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
openSidebar: Boolean,
|
||||||
|
},
|
||||||
|
mixins: [wrapperMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
displayType: "day",
|
||||||
|
isCurrentDate: true,
|
||||||
|
events: recordList,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
selectedDates: (state) => state.calendar.selectedDates,
|
||||||
|
//events: (state) => state.calendar.events,
|
||||||
|
}),
|
||||||
|
filteringEmployees() {
|
||||||
|
let employeesList = [];
|
||||||
|
this.events?.forEach(({ employee }) => {
|
||||||
|
if (!employeesList.includes(JSON.stringify(employee)))
|
||||||
|
employeesList.push(JSON.stringify(employee));
|
||||||
|
});
|
||||||
|
return employeesList?.map((elem) => JSON.parse(elem));
|
||||||
|
},
|
||||||
|
columnStyle() {
|
||||||
|
return this.filteringEmployees?.length > 4
|
||||||
|
? {
|
||||||
|
height: `${this.timeCoil.length * this.pixelsPerHour + 60}px`,
|
||||||
|
width: "380px",
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
height: `${this.timeCoil.length * this.pixelsPerHour + 60}px`,
|
||||||
|
width: `calc(100%/ ${this.filteringEmployees?.length})`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
backgroundWrapperWidth() {
|
||||||
|
return this.filteringEmployees?.length > 4
|
||||||
|
? {
|
||||||
|
width: `${380 * this.filteringEmployees?.length + 80}px`,
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
},
|
||||||
|
columnWrapperWidth() {
|
||||||
|
return this.filteringEmployees?.length > 4
|
||||||
|
? {
|
||||||
|
width: `${380 * this.filteringEmployees?.length}px`,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
width: "calc(100% - 80px)",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//вынести в функции
|
||||||
|
timeCoilInitialization() {
|
||||||
|
this.timeCoil = [];
|
||||||
|
for (let i = this.validateStartTime; i < this.validateEndTime; i++) {
|
||||||
|
if (
|
||||||
|
i === this.hours &&
|
||||||
|
this.hours !== this.validateEndTime &&
|
||||||
|
this.isCurrentDate
|
||||||
|
) {
|
||||||
|
this.timeCoil.push(this.hoursMinutes);
|
||||||
|
} else this.timeCoil.push(`${i}:00`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
//вынести в примеси и использовать timeCoilInitialization как функцию
|
||||||
|
currentTime() {
|
||||||
|
if (
|
||||||
|
this.hours === this.validateEndTime &&
|
||||||
|
this.minutes > 0 &&
|
||||||
|
this.timer
|
||||||
|
) {
|
||||||
|
this.stopTimer();
|
||||||
|
this.timeCoilInitialization();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectedDates: {
|
||||||
|
deep: true,
|
||||||
|
handler(newValue) {
|
||||||
|
this.isCurrentDate = newValue?.from.isSame(moment(), "day");
|
||||||
|
this.isShownIndicator = this.isCurrentDate;
|
||||||
|
if (this.timer) {
|
||||||
|
this.stopTimer();
|
||||||
|
this.timeCoilInitialization();
|
||||||
|
}
|
||||||
|
if (this.isCurrentDate) {
|
||||||
|
this.changeCurrentTime();
|
||||||
|
this.timeCoilInitialization();
|
||||||
|
this.startTimer();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.changeCurrentTime();
|
||||||
|
this.timeCoilInitialization();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="sass" scoped>
|
||||||
|
@import "@/pages/newCalendar/mixins/wrapperStyle.sass"
|
||||||
|
</style>
|
||||||
53
src/pages/newCalendar/mixins/columnMixin.js
Normal file
53
src/pages/newCalendar/mixins/columnMixin.js
Normal file
@@ -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`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
24
src/pages/newCalendar/mixins/columnStyle.sass
Normal file
24
src/pages/newCalendar/mixins/columnStyle.sass
Normal file
@@ -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)
|
||||||
26
src/pages/newCalendar/mixins/headerMixin.js
Normal file
26
src/pages/newCalendar/mixins/headerMixin.js
Normal file
@@ -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;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
41
src/pages/newCalendar/mixins/headerStyle.sass
Normal file
41
src/pages/newCalendar/mixins/headerStyle.sass
Normal file
@@ -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)
|
||||||
111
src/pages/newCalendar/mixins/wrapperMixin.js
Normal file
111
src/pages/newCalendar/mixins/wrapperMixin.js
Normal file
@@ -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();
|
||||||
|
},
|
||||||
|
};
|
||||||
44
src/pages/newCalendar/mixins/wrapperStyle.sass
Normal file
44
src/pages/newCalendar/mixins/wrapperStyle.sass
Normal file
@@ -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)
|
||||||
@@ -779,15 +779,15 @@ export const services = [
|
|||||||
export const recordList = [
|
export const recordList = [
|
||||||
{
|
{
|
||||||
id: "c3df0a95-8093-41f1-9584-5b70ee05e71c",
|
id: "c3df0a95-8093-41f1-9584-5b70ee05e71c",
|
||||||
start: "2023-07-05T10:00:00Z",
|
start: "2023-09-18T10:00:00Z",
|
||||||
end: "2023-07-05T11:00:00Z",
|
end: "2023-09-18T11:00:00Z",
|
||||||
employee: {
|
employee: {
|
||||||
id: "464101e6-b4e6-46a4-8ef6-08ecb2921493",
|
id: "464101e6-b4e6-46a4-8ef6-08ecb2921493",
|
||||||
last_name: "Каневский",
|
last_name: "Каневский",
|
||||||
first_name: "Леонид",
|
first_name: "Леонид",
|
||||||
patronymic: "Семенович",
|
patronymic: "Семенович",
|
||||||
},
|
},
|
||||||
member: {
|
person: {
|
||||||
id: "3e6e54e4-2706-47d3-8b54-b841ee8f0943",
|
id: "3e6e54e4-2706-47d3-8b54-b841ee8f0943",
|
||||||
last_name: "Харитонова",
|
last_name: "Харитонова",
|
||||||
first_name: "Ольга",
|
first_name: "Ольга",
|
||||||
@@ -824,15 +824,15 @@ export const recordList = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "ba931000-7140-4977-bd09-1ac212b8b8e5",
|
id: "ba931000-7140-4977-bd09-1ac212b8b8e5",
|
||||||
start: "2023-07-06T15:00:00Z",
|
start: "2023-09-18T15:00:00Z",
|
||||||
end: "2023-07-06T15:30:00Z",
|
end: "2023-09-18T15:30:00Z",
|
||||||
employee: {
|
employee: {
|
||||||
id: "464101e6-b4e6-46a4-8ef6-08ecb2921493",
|
id: "464101e6-b4e6-46a4-8ef6-08ecb2921493",
|
||||||
last_name: "Каневский",
|
last_name: "Каневский",
|
||||||
first_name: "Леонид",
|
first_name: "Леонид",
|
||||||
patronymic: "Семенович",
|
patronymic: "Семенович",
|
||||||
},
|
},
|
||||||
member: {
|
person: {
|
||||||
id: "d340d344-4fc7-4fbe-9db8-b7562b70438d",
|
id: "d340d344-4fc7-4fbe-9db8-b7562b70438d",
|
||||||
last_name: "Гаранова",
|
last_name: "Гаранова",
|
||||||
first_name: "Наталья",
|
first_name: "Наталья",
|
||||||
@@ -877,16 +877,16 @@ export const recordList = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "4cd94bec-a0df-4a18-879d-f64cd6d7098e",
|
id: "4cd94bec-a0df-4a18-879d-f64cd6d5698e",
|
||||||
start: "2023-07-03T13:00:00Z",
|
start: "2023-09-18T13:00:00Z",
|
||||||
end: "2023-07-03T14:30:00Z",
|
end: "2023-09-18T14:30:00Z",
|
||||||
employee: {
|
employee: {
|
||||||
id: "464101e6-b4e6-46a4-8ef6-08ecb2921493",
|
id: "464101e6-b4e6-46a4-8ef6-08ecb2921493",
|
||||||
last_name: "Каневский",
|
last_name: "Гурцев",
|
||||||
first_name: "Леонид",
|
first_name: "Семен",
|
||||||
patronymic: "Семенович",
|
patronymic: "Семенович",
|
||||||
},
|
},
|
||||||
member: {
|
person: {
|
||||||
id: "0b2d1db1-6aab-4e29-b857-fc7c9777280f",
|
id: "0b2d1db1-6aab-4e29-b857-fc7c9777280f",
|
||||||
last_name: "Харитонова",
|
last_name: "Харитонова",
|
||||||
first_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 = [
|
export const recordPreviewConfig = [
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export default createStore({
|
|||||||
imgUrl: "https://astra-dev.dopcore.com/api/store/",
|
imgUrl: "https://astra-dev.dopcore.com/api/store/",
|
||||||
routingHistory: window.history,
|
routingHistory: window.history,
|
||||||
userData: {},
|
userData: {},
|
||||||
|
calendarShape: "manager",
|
||||||
},
|
},
|
||||||
modules: {
|
modules: {
|
||||||
medical,
|
medical,
|
||||||
|
|||||||
Reference in New Issue
Block a user