[WIP] Разделил компоненты календаря

This commit is contained in:
megavrilinvv
2023-05-25 12:51:06 +03:00
parent 17bf66c00f
commit 34674bd248
19 changed files with 29 additions and 1 deletions

View File

@@ -0,0 +1,645 @@
<template lang="pug">
base-modal(
v-model="value",
:title="!selectedEventData.id ? 'Запись на прием' : 'Изменение записи'",
draggable,
hide-overlay
)
.event-form.flex.flex-col.gap-y-6.pt-8
.flex.flex-col.gap-y-8
base-select(
v-if="selectedEventData.id"
v-model="status",
:items="statusesList",
label="Статус приема"
)
base-input(
v-else,
disabled,
v-model="status.label",
label="Статус приема",
outlined
)
base-select(
:items="ownersList",
v-model="employees.employee",
placeholder="Выберите сотрудника"
label="Сотрудник"
)
base-select(
:items="membersList",
v-model="members.person",
placeholder="Выберите клиента",
label="Клиент"
)
.flex.gap-x-4
base-input(
v-model="eventDate",
label="Дата",
type="date",
outlined
)
.flex.gap-x-2.items-center.justify-between
base-input(
type="time",
v-model="startTime",
label="Начало",
outlined
)
span.mt-4
base-input(
type="time",
v-model="endTime",
label="Конец",
outlined
)
q-btn.create-button(
v-if="!selectedEventData.id",
label="Создать событие",
no-caps,
color="primary",
padding="10px 22px",
:disabled="disabledCreateButton",
@click="sendEventData",
)
q-btn.update-button(
v-else,
label="Сохранить",
no-caps,
color="primary",
padding="10px 22px",
:disabled="disabledUpdateButton",
@click="updateEventData",
)
</template>
<script>
import TheNotificationProvider from "@/components/Notifications/TheNotificationProvider";
import { addNotification } from "@/components/Notifications/notificationContext";
import { fetchWrapper } from "@/shared/fetchWrapper.js";
import BaseInput from "@/components/base/BaseInput.vue";
import BaseSelect from "@/components/base/BaseSelect.vue";
import * as moment from "moment/moment";
import BaseModal from "@/components/base/BaseModal.vue";
import { v_model } from "@/shared/mixins/v-model";
import { statusesConfig } from "@/pages/calendar/utils/statusesConfig";
export default {
name: "FormChangeEvent",
components: {
BaseModal,
BaseSelect,
BaseInput,
TheNotificationProvider,
},
mixins: [v_model],
//emits: ["clear-selected-event-data", "close-change-form"],
emits: ["clear-event-data"],
props: {
//closeForm: Function,
selectedEventData: {
type: Object,
default() {
return {};
},
},
timeInformation: {
type: Object,
default() {
return {};
},
},
currentDate: {
type: Object,
default() {
return {};
},
},
},
data() {
return {
EMPLOYEE_TYPE: "owner",
MEMBER_TYPE: "primary",
EVENT_KIND: "Прием",
eventData: {},
startTime: "",
endTime: "",
members: {},
employees: {},
eventDate: Date,
status: { label: "Планируется прием", id: null },
id: null,
//ifClearedForm: true,
membersData: [],
ownersData: [],
WORKING_STATUS: "WORKS",
};
},
computed: {
ownersList() {
if (this.ownersData) {
let filteredArray = [];
this.ownersData.forEach((elem) => {
filteredArray.push({
id: elem.id,
label: this.trimOwnerName(
elem.last_name,
elem.first_name,
elem.patronymic
),
});
});
return filteredArray;
}
return [];
},
membersList() {
if (this.membersData) {
let filteredArray = [];
this.membersData.forEach((elem) => {
filteredArray.push({
id: elem.id,
label: this.trimMemberName(
elem.last_name,
elem.first_name,
elem.patronymic
),
});
});
return filteredArray;
}
return [];
},
statusesList() {
let filteredArray = [];
statusesConfig.forEach((elem) => {
filteredArray.push({
id: elem.id,
label: elem.label,
});
});
return filteredArray;
},
disabledCreateButton() {
if (
this.eventDate &&
this.startTime &&
this.endTime &&
this.members.person.label &&
this.employees.employee.label &&
this.status.label
) {
return false;
}
return true;
},
disabledUpdateButton() {
let start = moment(this.selectedEventData.start);
let end = moment(this.selectedEventData.end);
if (
moment(this.eventDate).format("YYYY-MM-DD") ===
start.format("YYYY-MM-DD") &&
this.startTime === start.format("HH:mm") &&
this.endTime === end.format("HH:mm") &&
this.findStatus(this.status.label) === this.selectedEventData.status &&
this.employees.employee.id ===
this.personId(this.selectedEventData.employees, "employee") &&
this.members.person.id ===
this.personId(this.selectedEventData.members, "person")
) {
return true;
}
if (!this.eventDate) return true;
return false;
},
startDate() {
return this.selectedEventData.start
? new Date(this.selectedEventData.start)
: this.currentDate.toDate();
},
endDate() {
return this.selectedEventData.end
? new Date(this.selectedEventData.end)
: this.currentDate.toDate();
},
eventEmployee() {
if (this.selectedEventData.employees) {
let foundEmployee = this.selectedEventData.employees.find(
({ role }) => role === this.EMPLOYEE_TYPE
);
let {
employee: { id, last_name, first_name, patronymic },
...rest
} = foundEmployee;
return {
employee: {
id: id,
label: this.trimOwnerName(last_name, first_name, patronymic),
},
id: rest?.id || null,
role: rest?.role || this.EMPLOYEE_TYPE,
};
}
return {
employee: {
id: null,
label: "",
},
role: this.EMPLOYEE_TYPE,
};
},
eventMember() {
if (this.selectedEventData.members) {
let foundMember = {};
if (this.selectedEventData.members.length > 1) {
foundMember = this.selectedEventData.members.find(
({ role }) => role === this.MEMBER_TYPE
);
} else foundMember = this.selectedEventData.members[0];
let {
person: { id, last_name, first_name, patronymic },
...rest
} = foundMember;
return {
person: {
id: id,
label: this.trimMemberName(last_name, first_name, patronymic),
},
id: rest.id,
role: rest?.role || this.MEMBER_TYPE,
};
}
return {
person: {
id: null,
label: "",
},
role: this.MEMBER_TYPE,
};
},
eventId() {
return this.selectedEventData.id ? this.selectedEventData.id : "";
},
eventStatus() {
return this.selectedEventData.status
? {
label: statusesConfig.find(
(e) => e.value === this.selectedEventData.status
).label,
id: statusesConfig.find(
(e) => e.value === this.selectedEventData.status
).id,
}
: {
label: statusesConfig.find((e) => e.value === "PLANNED").label,
id: 0,
};
},
},
methods: {
findStatus(value) {
return statusesConfig.find((e) => e.label === value)?.value;
},
checkTimeLimits(eventTime, scheduleTime, timeType) {
if (timeType === "start")
return (
parseInt(eventTime.split(":")[0]) <
parseInt(scheduleTime.split(":")[0])
);
if (timeType === "end") {
let firstTime = eventTime.split(":").map((elem) => parseInt(elem));
let secondTime = scheduleTime.split(":").map((elem) => parseInt(elem));
if (firstTime[0] === secondTime[0]) return firstTime[1] > secondTime[1];
else return firstTime[0] > secondTime[0];
}
},
checkTime() {
let counter = 0;
let foundedSchedule = {};
let foundedEmployee = this.ownersData.find(
(elem) => elem.id === this.employees.employee.id
);
if (foundedEmployee)
foundedSchedule = foundedEmployee.schedules.find(
(elem) =>
elem.date === moment(this.eventDate).format("YYYY-MM-DD") &&
elem.status === this.WORKING_STATUS
);
if (!foundedSchedule) {
this.addErrorNotification(
"Некорректная дата события",
`В данный день ${this.employees.employee.label} не работает`
);
counter += 1;
return false;
}
if (
this.checkTimeLimits(
this.startTime,
foundedSchedule.start_time,
"start"
)
) {
this.addErrorNotification(
"Некорректное время начала события",
"Время начала события раньше начала рабочего дня"
);
counter += 1;
}
if (this.checkTimeLimits(this.endTime, foundedSchedule.end_time, "end")) {
this.addErrorNotification(
"Некорректное время окончания события",
"Время окончания события позже окончания рабочего дня"
);
counter += 1;
}
if (
this.checkTimeLimits(this.endTime, foundedSchedule.start_time, "start")
) {
this.addErrorNotification(
"Некорректное время окончания события",
"Время окончания события раньше начала рабочего дня"
);
counter += 1;
}
if (
this.checkTimeLimits(this.startTime, foundedSchedule.end_time, "end")
) {
this.addErrorNotification(
"Некорректное время начала события",
"Время начала события позже окончания рабочего дня"
);
counter += 1;
}
return counter === 0;
},
trimOwnerName(lastName, firstName, patronymic) {
let checkedFirstName = firstName !== null ? firstName[0] + "." : "";
let checkedPatronymic = patronymic !== null ? patronymic[0] + "." : "";
return `${lastName} ${checkedFirstName}${checkedPatronymic}`;
},
trimMemberName(lastName, firstName, patronymic) {
return `${lastName} ${firstName ?? ""} ${patronymic ?? ""}`;
},
async sendEventData() {
if (!this.checkTime()) return;
this.eventData = {
start: this.mergeDate(this.eventDate, this.startTime),
end: this.mergeDate(this.eventDate, this.endTime),
status: this.findStatus(this.status.label),
kind: this.EVENT_KIND,
employees: [
this.findPerson(this.ownersData, this.employees, "employee"),
],
members: [this.findPerson(this.membersData, this.members, "person")],
};
await this.postCreateEvent(this.eventData);
this.eventData = {};
this.value = false;
},
async updateEventData() {
if (!this.checkTime()) return;
if (
Object.keys(
this.findPerson(this.ownersData, this.employees, "employee")
).length > 0 &&
Object.keys(this.findPerson(this.membersData, this.members, "person"))
.length > 0
) {
this.eventData = {
start: this.mergeDate(this.eventDate, this.startTime),
end: this.mergeDate(this.eventDate, this.endTime),
status: this.findStatus(this.status.label),
employees: [
this.findPerson(this.ownersData, this.employees, "employee"),
],
members: [this.findPerson(this.membersData, this.members, "person")],
};
await this.postUpdateEvent(this.id, this.eventData);
this.eventData = {};
this.value = false;
} else
this.addErrorNotification(
"Событие не может быть изменено",
"Клиент был удален"
);
},
//clearForm() {
// if (this.selectedEventData.id) this.$emit("close-change-form");
// this.$emit("clear-selected-event-data");
// this.closeForm();
//},
mergeDate(eventDate, time) {
let parseTime = time.split(":");
return moment(eventDate.setHours(parseTime[0], parseTime[1]), 0).format(
"YYYY-MM-DDTHH:mm:ss"
);
},
findPerson(requestedList, object, field) {
let foundPerson = requestedList.find(({ id }) => id === object[field].id);
if (foundPerson) {
let returnedData = {
[field]: {
id: foundPerson.id,
last_name: foundPerson.last_name,
first_name: foundPerson.first_name,
patronymic: foundPerson.patronymic,
color: foundPerson.color,
},
role: object.role,
};
if (object.id) returnedData.id = object.id;
return returnedData;
}
return {};
},
async postCreateEvent(event) {
const response = await fetchWrapper.post("registry/event/create/", event);
if (response.type && response.type === "validation_error") {
this.addErrorNotification(
response.errors[0].code,
response.errors[0].detail
);
} else {
this.addSuccessNotification("Событие успешно создано");
//this.clearForm();
}
},
async postUpdateEvent(id, event) {
const response = await fetchWrapper.post(
`registry/event/${id}/update/`,
event
);
if (response.type && response.type === "validation_error") {
this.addErrorNotification(
response.errors[0].code,
response.errors[0].detail
);
} else {
this.addSuccessNotification("Изменения успешно сохранены");
//this.clearForm();
}
},
personId(object, field) {
if (object) {
let foundPerson = {};
if (field === "employee") {
foundPerson = object.find(({ role }) => role === this.EMPLOYEE_TYPE);
}
if (field === "person") {
if (object.length > 1) {
foundPerson = object.find(({ role }) => role === this.MEMBER_TYPE);
}
foundPerson = object[0];
}
let {
[field]: { id },
} = foundPerson;
return id;
}
},
addErrorNotification(title, message) {
addNotification(title, title, message, "error", 5000);
},
addSuccessNotification(message) {
addNotification(new Date().getTime(), message, "", "success", 5000);
},
fetchMembersData() {
fetchWrapper
.get("general/person/?limit=200")
.then((res) => this.saveMembersData(res));
},
fetchOwnersData() {
fetchWrapper
.get(
`accounts/schedules/?date_after=${this.currentDate
.clone()
.subtract(1, "month")
.format("YYYY-MM-DD")}&date_before=${this.currentDate
.clone()
.add(1, "month")
.format("YYYY-MM-DD")}`
)
.then((res) => this.saveOwnersData(res));
},
saveOwnersData(res) {
let serializedList = [];
if (res.results.length === 0) {
this.ownersData = [];
return;
}
res.results.forEach((elem) => {
let foundedElem = serializedList.find(
(item) => item.id === elem.employee.id
);
if (!foundedElem) {
serializedList.push({
id: elem.employee.id,
last_name: elem.employee.last_name,
first_name: elem.employee.first_name,
patronymic: elem.employee.patronymic,
color: elem.employee.color,
schedules: [
{
date: elem.date,
end_time: elem.end_time?.slice(0, elem.end_time.length - 3),
start_time: elem.start_time?.slice(
0,
elem.start_time.length - 3
),
status: elem.status,
id: elem.id,
},
],
});
} else {
foundedElem.schedules.push({
date: elem.date,
end_time: elem.end_time?.slice(0, elem.end_time.length - 3),
start_time: elem.start_time?.slice(0, elem.start_time.length - 3),
status: elem.status,
id: elem.id,
});
}
});
this.ownersData = serializedList;
},
saveMembersData(res) {
this.membersData = res.results;
},
},
watch: {
startDate: {
immediate: true,
handler(newDate) {
if (newDate) {
this.eventDate = newDate;
this.startTime = moment(newDate).format("HH:mm");
}
},
},
endDate: {
immediate: true,
handler(newDate) {
if (newDate) {
this.endTime = moment(newDate).format("HH:mm");
}
},
},
selectedEventData: {
immediate: true,
handler(newDate) {
if (newDate) {
this.id = this.eventId;
this.status = this.eventStatus;
this.employees = this.eventEmployee;
this.members = this.eventMember;
}
},
},
value(newValue) {
if (newValue === false) this.$emit("clear-event-data");
},
},
mounted() {
this.fetchOwnersData();
this.fetchMembersData();
},
};
</script>
<style lang="sass" scoped>
.event-form
width: 550px
.form-item
border-radius: 4px
width: 344px
background-color: var(--default-white)
.date-input
width: 174px
border-radius: 4px
background-color: var(--default-white)
.icon
width: 24px
height: 24px
color: var(--font-dark-blue-color)
.close-icon
color: var(--font-dark-blue-color)
&:hover
color: var(--btn-blue-color)
.create-button
width: 183px
.select
border: 1.5px solid var(--border-light-grey-color)
border-radius: 4px
.update-button
width: 132px
</style>