[WIP] Добавил отображение сотрудников на графике, поправил стили, изменил запросы логина
This commit is contained in:
@@ -21,14 +21,14 @@
|
||||
) Создать событие
|
||||
calendar-sidebar-event(:is-open="isOpen", :event-statuses="eventStatuses")
|
||||
calendar-sidebar-teammate(:team-data="teamData", :is-open="isOpen", :url="url")
|
||||
.button-wrapper.flex.justify-center.mb-23px
|
||||
base-button(
|
||||
left-icon="icon-long-arrow",
|
||||
rounded, :size="40",
|
||||
:icon-left-size="18",
|
||||
secondary,
|
||||
:style="{ transform: `rotate(${turnButton})`}",
|
||||
@click="changeSize"
|
||||
//- .button-wrapper.flex.justify-center.mb-23px
|
||||
//- base-button(
|
||||
//- left-icon="icon-long-arrow",
|
||||
//- rounded, :size="40",
|
||||
//- :icon-left-size="18",
|
||||
//- secondary,
|
||||
//- :style="{ transform: `rotate(${turnButton})`}",
|
||||
//- @click="changeSize"
|
||||
)
|
||||
</template>
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fetchWrapper } from "@/shared/fetchWrapper";
|
||||
import BaseInput from "@/components/base/BaseInput";
|
||||
import BaseButton from "@/components/base/BaseButton";
|
||||
import viewPasswordIcon from "@/assets/icons/eye.svg";
|
||||
@@ -84,46 +85,28 @@ export default {
|
||||
localStorage.username = this.user.username;
|
||||
localStorage.password = this.user.password;
|
||||
},
|
||||
async auth(token) {
|
||||
let res = await fetch("https://astra-dev.dopcore.com/auth/users/me/", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
res = await res.json();
|
||||
let data = await fetch(
|
||||
`https://astra-dev.dopcore.com/accounts/users/${res.id}/detail`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
data = await data.json();
|
||||
async auth() {
|
||||
let res = await fetchWrapper.get("auth/users/me/");
|
||||
res = await res;
|
||||
let data = await fetchWrapper.get(`accounts/users/${res.id}/detail`);
|
||||
data = await data;
|
||||
this.userData = data;
|
||||
localStorage.setItem("userData", JSON.stringify(this.userData));
|
||||
},
|
||||
login() {
|
||||
const requestOptions = {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(this.user),
|
||||
};
|
||||
fetch("https://astra-dev.dopcore.com/auth/jwt/create/", requestOptions)
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
return result.json();
|
||||
fetchWrapper
|
||||
.post("auth/jwt/create/", {
|
||||
username: this.user.username,
|
||||
password: this.user.password,
|
||||
})
|
||||
.then((token) => {
|
||||
if (token.access) {
|
||||
localStorage.setItem("tokenAccess", token.access);
|
||||
this.auth().then(() => this.$router.push("/"));
|
||||
} else {
|
||||
this.authorized = false;
|
||||
this.user.username = "";
|
||||
this.user.password = "";
|
||||
}
|
||||
})
|
||||
.then((token) => {
|
||||
if (token) {
|
||||
localStorage.setItem("tokenAccess", token.access);
|
||||
this.auth(token.access).then(() => this.$router.push("/"));
|
||||
} else {
|
||||
this.$router.push("/login");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
schedule-body(
|
||||
:employee-list="employeeList",
|
||||
:schedules-employee="fetchSchedulesEmployee",
|
||||
:schedule-list="scheduleList"
|
||||
:schedule-list="scheduleList",
|
||||
:serialized="serialized"
|
||||
)
|
||||
schedule-bar
|
||||
</template>
|
||||
@@ -22,21 +23,64 @@ export default {
|
||||
return {
|
||||
employeeList: [],
|
||||
scheduleList: [],
|
||||
serialized: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
fetchSchedules() {
|
||||
fetchWrapper
|
||||
.get("general/employee/")
|
||||
.then((res) => (this.employeeList = res.results));
|
||||
.then((res) => {
|
||||
this.employeeList = res.results;
|
||||
})
|
||||
.then(() => this.fetchSchedulesEmployee());
|
||||
},
|
||||
fetchSchedulesEmployee(id) {
|
||||
fetchSchedulesEmployee() {
|
||||
this.employeeList.forEach((e) => {
|
||||
fetchWrapper
|
||||
.get(`accounts/schedules/?employee=${id}`, "api")
|
||||
.get(`accounts/schedules/?employee=${e.id}`)
|
||||
.then((data) => {
|
||||
this.scheduleList = data.results;
|
||||
this.scheduleList.push(...data.results);
|
||||
})
|
||||
.then(() => this.filterScheduleEmployee());
|
||||
});
|
||||
},
|
||||
filterScheduleEmployee() {
|
||||
let serialized = [];
|
||||
this.scheduleList.forEach((e) => {
|
||||
let foundedElem = serialized.find((elem) => elem.id === e.employee.id);
|
||||
if (!foundedElem) {
|
||||
serialized.push({
|
||||
first_name: e.employee.first_name,
|
||||
id: e.employee.id,
|
||||
last_name: e.employee.last_name,
|
||||
patronymic: e.employee.patronymic,
|
||||
schedules: [
|
||||
{
|
||||
date: e.date,
|
||||
end_time: e.end_time,
|
||||
start_time: e.start_time,
|
||||
status: e.status,
|
||||
id: e.id,
|
||||
title: e.title,
|
||||
name: e.name,
|
||||
},
|
||||
],
|
||||
});
|
||||
} else {
|
||||
foundedElem.schedules.push({
|
||||
date: e.date,
|
||||
end_time: e.end_time,
|
||||
start_time: e.start_time,
|
||||
status: e.status,
|
||||
id: e.id,
|
||||
title: e.title,
|
||||
name: e.name,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.serialized = serialized;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchSchedules();
|
||||
|
||||
@@ -2,25 +2,22 @@
|
||||
.wrapper-bar.flex.flex-col.gap-y-4
|
||||
.flex.px-5.py-5.w-full.justify-around
|
||||
.time-wrapper.flex.justify-between
|
||||
.flex.flex-col.py-14px.px-4.gap-y-14px
|
||||
.text.text-smm Начало рабочего дня
|
||||
base-input-time.item-input.text-base.select(:width-input="40")
|
||||
.flex.flex-col.py-14px.px-4.gap-y-14px
|
||||
.text.span.text-smm Конец рабочего дня
|
||||
base-input-time.item-input.text-base.select(:width-input="40")
|
||||
.flex.flex-col.items-center.py-14px.px-4.gap-y-14px
|
||||
.text.text-smm Начало
|
||||
base-input-date.select(v-model:value="dataSchedule.endTime")
|
||||
.flex.flex-col.items-center.py-14px.px-4.gap-y-14px
|
||||
.text.span.text-smm Конец
|
||||
base-input-date.select(v-model:value="dataSchedule.startTime")
|
||||
.status-wrapper.flex.flex-col
|
||||
.flex.justify-center.items-center.h-10
|
||||
span.font-semibold Статусы
|
||||
.flex.justify-around(class="py-2.5")
|
||||
base-button.button-work.font-semibold(
|
||||
:style="{minWidth: '190px', minHeight: '43px'}"
|
||||
) Работает
|
||||
base-button.button-status.font-semibold(
|
||||
:style="{minWidth: '190px', minHeight: '43px'}"
|
||||
) Отпуск/больничный
|
||||
base-button.button-free.font-semibold(
|
||||
:style="{minWidth: '190px', minHeight: '43px'}"
|
||||
) Выходной
|
||||
base-button.font-semibold(
|
||||
v-for="item in buttons",
|
||||
:class="item.work" ,
|
||||
:style="{minWidth: '190px', minHeight: '43px', border: item.active ? '1.5px solid #5E5E5E' : 'none'}",
|
||||
@click="choiceSchedule(item.work)"
|
||||
) {{item.name}}
|
||||
.graph-template.flex
|
||||
base-custom-select(
|
||||
:items="scheduleList",
|
||||
@@ -36,9 +33,10 @@
|
||||
import BaseButton from "@/components/base/BaseButton.vue";
|
||||
import BaseCustomSelect from "@/components/base/BaseCustomSelect.vue";
|
||||
import BaseInputTime from "@/components/base/BaseInputTime.vue";
|
||||
import BaseInputDate from "@/components/base/BaseInputDate.vue";
|
||||
export default {
|
||||
name: "ScheduleBar",
|
||||
components: { BaseButton, BaseCustomSelect, BaseInputTime },
|
||||
components: { BaseButton, BaseCustomSelect, BaseInputTime, BaseInputDate },
|
||||
data() {
|
||||
return {
|
||||
scheduleList: [
|
||||
@@ -48,8 +46,24 @@ export default {
|
||||
{ label: "5/2", id: 4 },
|
||||
],
|
||||
schedule: {},
|
||||
dataSchedule: {
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
status: "",
|
||||
},
|
||||
buttons: [
|
||||
{ work: "button-work", name: "Работает", active: false },
|
||||
{ work: "button-status", name: "Отпуск/больничный", active: false },
|
||||
{ work: "button-free", name: "Статусы", active: false },
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
choiceSchedule(item) {
|
||||
this.buttons.forEach((e) => (e.active = false));
|
||||
this.buttons.find((e) => e.work === item).active = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -60,7 +74,7 @@ export default {
|
||||
border-radius: 4px
|
||||
|
||||
.time-wrapper
|
||||
width: 350px
|
||||
width: 420px
|
||||
height: 102px
|
||||
border: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-radius: 4px
|
||||
@@ -128,4 +142,9 @@ export default {
|
||||
.graph-template
|
||||
width: 218px
|
||||
height: 40px
|
||||
|
||||
.select
|
||||
height: 40px
|
||||
border: 1.5px solid var(--border-light-grey-color)
|
||||
border-radius: 4px
|
||||
</style>
|
||||
|
||||
@@ -14,40 +14,40 @@
|
||||
.text.flex.font-bold(
|
||||
:style="{opacity: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? '0.6' : '1'}"
|
||||
) {{day.format("ddd")}}
|
||||
.schedule-body.flex.w-full(v-if="this.scheduleList[0]?.id")
|
||||
.schedule-body.flex.w-full(v-for="schedule in serialized")
|
||||
.edit.flex.items-center.justify-center.h-9.w-9
|
||||
.flex.icon-edit
|
||||
.name-employee.flex.justify-center.items-center.cursor-pointer(@click="openSelect")
|
||||
span {{trimOwnerName(this.scheduleList[0]?.employee.last_name, this.scheduleList[0]?.employee.first_name, this.scheduleList[0]?.employee.patronymic)}}
|
||||
span {{trimOwnerName(schedule.last_name, schedule.first_name, schedule.patronymic)}}
|
||||
.flex
|
||||
.cell.flex.flex-col.items-center.justify-center.w-11(
|
||||
v-for="day in result",
|
||||
:style="{backgroundColor: day.format('YYYY-MM-DD') === choiceDay(day.format('YYYY-MM-DD')) ? choiceColor(day.format('YYYY-MM-DD')) : ''}"
|
||||
:style="{backgroundColor: day.format('YYYY-MM-DD') === choiceDay(day.format('YYYY-MM-DD'), schedule.id) ? choiceColor(day.format('YYYY-MM-DD')) : ''}"
|
||||
)
|
||||
.flex {{day.format("YYYY-MM-DD") === choiceDay(day.format("YYYY-MM-DD")) ? choiceWorks(day.format('YYYY-MM-DD')) : ''}}
|
||||
.schedule-body.flex.w-full
|
||||
.edit.flex.items-center.justify-center.h-9.w-9
|
||||
.flex.items-center.gap-x-8
|
||||
base-button(
|
||||
confirm,
|
||||
rounded,
|
||||
outlined,
|
||||
:size="20",
|
||||
@click="saveEmployee",
|
||||
v-if="currentEmployee.label"
|
||||
)
|
||||
.icon-ok.text-xsm(class="pt-[3px]")
|
||||
.name.flex.justify-center.items-center.cursor-pointer(
|
||||
v-if="currentEmployee.label",
|
||||
@click="openSelect"
|
||||
)
|
||||
span {{currentEmployee.label}}
|
||||
.name.flex(v-if="!currentEmployee.label")
|
||||
base-custom-select(
|
||||
:items="ownersList",
|
||||
v-model="currentEmployee",
|
||||
placeholder="Добавить сотрудника",
|
||||
:style="{border: 'none'}"
|
||||
.flex {{day.format("YYYY-MM-DD") === choiceDay(day.format("YYYY-MM-DD"), schedule.id) ? choiceWorks(day.format('YYYY-MM-DD')) : ''}}
|
||||
//- .schedule-body.flex.w-full
|
||||
//- .edit.flex.items-center.justify-center.h-9.w-9
|
||||
//- .flex.items-center.gap-x-8
|
||||
//- base-button(
|
||||
//- confirm,
|
||||
//- rounded,
|
||||
//- outlined,
|
||||
//- :size="20",
|
||||
//- @click="saveEmployee",
|
||||
//- v-if="currentEmployee.label"
|
||||
//- )
|
||||
//- .icon-ok.text-xsm(class="pt-[3px]")
|
||||
//- .name.flex.justify-center.items-center.cursor-pointer(
|
||||
//- v-if="currentEmployee.label",
|
||||
//- @click="openSelect"
|
||||
//- )
|
||||
//- span {{currentEmployee.label}}
|
||||
//- .name.flex(v-if="!currentEmployee.label")
|
||||
//- base-custom-select(
|
||||
//- :items="ownersList",
|
||||
//- v-model="currentEmployee",
|
||||
//- placeholder="Добавить сотрудника",
|
||||
//- :style="{border: 'none'}"
|
||||
)
|
||||
</template>
|
||||
|
||||
@@ -66,8 +66,8 @@ export default {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
schedulesEmployee: Function,
|
||||
scheduleList: Array,
|
||||
serialized: Array,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -85,6 +85,7 @@ export default {
|
||||
{ work: "VACATION", color: "#D7D9FF", text: "О" },
|
||||
{ work: "DAY_OFF", color: "#9294A7", text: "В" },
|
||||
],
|
||||
curWork: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -108,7 +109,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
saveEmployee() {
|
||||
this.schedulesEmployee(this.currentEmployee.id);
|
||||
this.currentEmployee.label = "";
|
||||
this.currentEmployee.id = null;
|
||||
},
|
||||
@@ -140,8 +140,10 @@ export default {
|
||||
this.employee.push(this.employeeList[index]);
|
||||
}
|
||||
},
|
||||
choiceDay(day) {
|
||||
return this.scheduleList.find((e) => day === e.date)?.date;
|
||||
choiceDay(day, employee) {
|
||||
return this.scheduleList.find(
|
||||
(e) => day === e.date && e.employee.id === employee
|
||||
)?.date;
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -5,11 +5,6 @@ function prepareUrl(url) {
|
||||
return `https://astra-dev.dopcore.com/api/${url}`;
|
||||
}
|
||||
|
||||
function prepareUrlApi(url) {
|
||||
if (url.startsWith("http")) return url;
|
||||
return `https://astra-dev.dopcore.com/${url}`;
|
||||
}
|
||||
|
||||
function handleRequest(method, url, headers, attempts, body, type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
(function internalRequest() {
|
||||
@@ -72,9 +67,7 @@ function request(method, url, headers = {}, body, type = "") {
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
}
|
||||
if (type === "api") {
|
||||
return fetch(prepareUrlApi(url), requestOptions);
|
||||
} else return fetch(prepareUrl(url), requestOptions);
|
||||
return fetch(prepareUrl(url), requestOptions);
|
||||
}
|
||||
|
||||
function get(url, type, headers, attempts = 3) {
|
||||
|
||||
Reference in New Issue
Block a user