[WIP] Разделил компоненты календаря
This commit is contained in:
645
src/pages/oldCalendar/components/CalendarFormAddEvent.vue
Normal file
645
src/pages/oldCalendar/components/CalendarFormAddEvent.vue
Normal 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>
|
||||
Reference in New Issue
Block a user