Merge branch 'UC-201' into 'master'

Resolve UC-201

See merge request andrusyakka/urban-couscous!215
This commit is contained in:
Vasiliy Gavrilin
2022-12-22 15:32:23 +00:00
6 changed files with 154 additions and 108 deletions

View File

@@ -21,14 +21,14 @@
) Создать событие ) Создать событие
calendar-sidebar-event(:is-open="isOpen", :event-statuses="eventStatuses") calendar-sidebar-event(:is-open="isOpen", :event-statuses="eventStatuses")
calendar-sidebar-teammate(:team-data="teamData", :is-open="isOpen", :url="url") calendar-sidebar-teammate(:team-data="teamData", :is-open="isOpen", :url="url")
.button-wrapper.flex.justify-center.mb-23px //- .button-wrapper.flex.justify-center.mb-23px
base-button( //- base-button(
left-icon="icon-long-arrow", //- left-icon="icon-long-arrow",
rounded, :size="40", //- rounded, :size="40",
:icon-left-size="18", //- :icon-left-size="18",
secondary, //- secondary,
:style="{ transform: `rotate(${turnButton})`}", //- :style="{ transform: `rotate(${turnButton})`}",
@click="changeSize" //- @click="changeSize"
) )
</template> </template>

View File

@@ -36,6 +36,7 @@
</template> </template>
<script> <script>
import { fetchWrapper } from "@/shared/fetchWrapper";
import BaseInput from "@/components/base/BaseInput"; import BaseInput from "@/components/base/BaseInput";
import BaseButton from "@/components/base/BaseButton"; import BaseButton from "@/components/base/BaseButton";
import viewPasswordIcon from "@/assets/icons/eye.svg"; import viewPasswordIcon from "@/assets/icons/eye.svg";
@@ -84,46 +85,28 @@ export default {
localStorage.username = this.user.username; localStorage.username = this.user.username;
localStorage.password = this.user.password; localStorage.password = this.user.password;
}, },
async auth(token) { async auth() {
let res = await fetch("https://astra-dev.dopcore.com/auth/users/me/", { let res = await fetchWrapper.get("auth/users/me/");
headers: { res = await res;
Authorization: `Bearer ${token}`, let data = await fetchWrapper.get(`accounts/users/${res.id}/detail`);
}, data = await data;
});
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();
this.userData = data; this.userData = data;
localStorage.setItem("userData", JSON.stringify(this.userData)); localStorage.setItem("userData", JSON.stringify(this.userData));
}, },
login() { login() {
const requestOptions = { fetchWrapper
method: "POST", .post("auth/jwt/create/", {
headers: { "Content-Type": "application/json" }, username: this.user.username,
body: JSON.stringify(this.user), password: this.user.password,
}; })
fetch("https://astra-dev.dopcore.com/auth/jwt/create/", requestOptions) .then((token) => {
.then((result) => { if (token.access) {
if (result.status === 200) { localStorage.setItem("tokenAccess", token.access);
return result.json(); this.auth().then(() => this.$router.push("/"));
} else { } else {
this.authorized = false; this.authorized = false;
this.user.username = ""; this.user.username = "";
this.user.password = ""; 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"); this.$router.push("/login");
} }
}); });

View File

@@ -5,7 +5,8 @@
schedule-body( schedule-body(
:employee-list="employeeList", :employee-list="employeeList",
:schedules-employee="fetchSchedulesEmployee", :schedules-employee="fetchSchedulesEmployee",
:schedule-list="scheduleList" :schedule-list="scheduleList",
:serialized="serialized"
) )
schedule-bar schedule-bar
</template> </template>
@@ -22,20 +23,63 @@ export default {
return { return {
employeeList: [], employeeList: [],
scheduleList: [], scheduleList: [],
serialized: [],
}; };
}, },
methods: { methods: {
fetchSchedules() { fetchSchedules() {
fetchWrapper fetchWrapper
.get("general/employee/") .get("general/employee/")
.then((res) => (this.employeeList = res.results)); .then((res) => {
this.employeeList = res.results;
})
.then(() => this.fetchSchedulesEmployee());
}, },
fetchSchedulesEmployee(id) { fetchSchedulesEmployee() {
fetchWrapper this.employeeList.forEach((e) => {
.get(`accounts/schedules/?employee=${id}`, "api") fetchWrapper
.then((data) => { .get(`accounts/schedules/?employee=${e.id}`)
this.scheduleList = data.results; .then((data) => {
}); 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() { mounted() {

View File

@@ -2,25 +2,22 @@
.wrapper-bar.flex.flex-col.gap-y-4 .wrapper-bar.flex.flex-col.gap-y-4
.flex.px-5.py-5.w-full.justify-around .flex.px-5.py-5.w-full.justify-around
.time-wrapper.flex.justify-between .time-wrapper.flex.justify-between
.flex.flex-col.py-14px.px-4.gap-y-14px .flex.flex-col.items-center.py-14px.px-4.gap-y-14px
.text.text-smm Начало рабочего дня .text.text-smm Начало
base-input-time.item-input.text-base.select(:width-input="40") base-input-date.select(v-model:value="dataSchedule.endTime")
.flex.flex-col.py-14px.px-4.gap-y-14px .flex.flex-col.items-center.py-14px.px-4.gap-y-14px
.text.span.text-smm Конец рабочего дня .text.span.text-smm Конец
base-input-time.item-input.text-base.select(:width-input="40") base-input-date.select(v-model:value="dataSchedule.startTime")
.status-wrapper.flex.flex-col .status-wrapper.flex.flex-col
.flex.justify-center.items-center.h-10 .flex.justify-center.items-center.h-10
span.font-semibold Статусы span.font-semibold Статусы
.flex.justify-around(class="py-2.5") .flex.justify-around(class="py-2.5")
base-button.button-work.font-semibold( base-button.font-semibold(
:style="{minWidth: '190px', minHeight: '43px'}" v-for="item in buttons",
) Работает :class="item.work" ,
base-button.button-status.font-semibold( :style="{minWidth: '190px', minHeight: '43px', border: item.active ? '1.5px solid #5E5E5E' : 'none'}",
:style="{minWidth: '190px', minHeight: '43px'}" @click="choiceSchedule(item.work)"
) Отпуск/больничный ) {{item.name}}
base-button.button-free.font-semibold(
:style="{minWidth: '190px', minHeight: '43px'}"
) Выходной
.graph-template.flex .graph-template.flex
base-custom-select( base-custom-select(
:items="scheduleList", :items="scheduleList",
@@ -36,9 +33,10 @@
import BaseButton from "@/components/base/BaseButton.vue"; import BaseButton from "@/components/base/BaseButton.vue";
import BaseCustomSelect from "@/components/base/BaseCustomSelect.vue"; import BaseCustomSelect from "@/components/base/BaseCustomSelect.vue";
import BaseInputTime from "@/components/base/BaseInputTime.vue"; import BaseInputTime from "@/components/base/BaseInputTime.vue";
import BaseInputDate from "@/components/base/BaseInputDate.vue";
export default { export default {
name: "ScheduleBar", name: "ScheduleBar",
components: { BaseButton, BaseCustomSelect, BaseInputTime }, components: { BaseButton, BaseCustomSelect, BaseInputTime, BaseInputDate },
data() { data() {
return { return {
scheduleList: [ scheduleList: [
@@ -48,8 +46,24 @@ export default {
{ label: "5/2", id: 4 }, { label: "5/2", id: 4 },
], ],
schedule: {}, 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> </script>
@@ -60,7 +74,7 @@ export default {
border-radius: 4px border-radius: 4px
.time-wrapper .time-wrapper
width: 350px width: 420px
height: 102px height: 102px
border: 1.5px solid var(--border-light-grey-color-1) border: 1.5px solid var(--border-light-grey-color-1)
border-radius: 4px border-radius: 4px
@@ -128,4 +142,9 @@ export default {
.graph-template .graph-template
width: 218px width: 218px
height: 40px height: 40px
.select
height: 40px
border: 1.5px solid var(--border-light-grey-color)
border-radius: 4px
</style> </style>

View File

@@ -14,40 +14,40 @@
.text.flex.font-bold( .text.flex.font-bold(
:style="{opacity: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? '0.6' : '1'}" :style="{opacity: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? '0.6' : '1'}"
) {{day.format("ddd")}} ) {{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 .edit.flex.items-center.justify-center.h-9.w-9
.flex.icon-edit .flex.icon-edit
.name-employee.flex.justify-center.items-center.cursor-pointer(@click="openSelect") .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(v-for="day in result") .flex
.cell.flex.flex-col.items-center.justify-center.w-11( .cell.flex.flex-col.items-center.justify-center.w-11(
v-for="item in scheduleList", v-for="day in result",
:style="{backgroundColor: day.format('YYYY-MM-DD') === item.date ? choiceColor(item.status) : ''}" :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") === item.date ? choiceWorks(item.status) : ''}} .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 //- .schedule-body.flex.w-full
.edit.flex.items-center.justify-center.h-9.w-9 //- .edit.flex.items-center.justify-center.h-9.w-9
.flex.items-center.gap-x-8 //- .flex.items-center.gap-x-8
base-button( //- base-button(
confirm, //- confirm,
rounded, //- rounded,
outlined, //- outlined,
:size="20", //- :size="20",
@click="saveEmployee", //- @click="saveEmployee",
v-if="currentEmployee.label" //- v-if="currentEmployee.label"
) //- )
.icon-ok.text-xsm(class="pt-[3px]") //- .icon-ok.text-xsm(class="pt-[3px]")
.name.flex.justify-center.items-center.cursor-pointer( //- .name.flex.justify-center.items-center.cursor-pointer(
v-if="currentEmployee.label", //- v-if="currentEmployee.label",
@click="openSelect" //- @click="openSelect"
) //- )
span {{currentEmployee.label}} //- span {{currentEmployee.label}}
.name.flex(v-if="!currentEmployee.label") //- .name.flex(v-if="!currentEmployee.label")
base-custom-select( //- base-custom-select(
:items="ownersList", //- :items="ownersList",
v-model="currentEmployee", //- v-model="currentEmployee",
placeholder="Добавить сотрудника", //- placeholder="Добавить сотрудника",
:style="{border: 'none'}" //- :style="{border: 'none'}"
) )
</template> </template>
@@ -66,8 +66,8 @@ export default {
return []; return [];
}, },
}, },
schedulesEmployee: Function,
scheduleList: Array, scheduleList: Array,
serialized: Array,
}, },
data() { data() {
return { return {
@@ -85,6 +85,7 @@ export default {
{ work: "VACATION", color: "#D7D9FF", text: "О" }, { work: "VACATION", color: "#D7D9FF", text: "О" },
{ work: "DAY_OFF", color: "#9294A7", text: "В" }, { work: "DAY_OFF", color: "#9294A7", text: "В" },
], ],
curWork: "",
}; };
}, },
computed: { computed: {
@@ -108,15 +109,16 @@ export default {
}, },
methods: { methods: {
saveEmployee() { saveEmployee() {
this.schedulesEmployee(this.currentEmployee.id);
this.currentEmployee.label = ""; this.currentEmployee.label = "";
this.currentEmployee.id = null; this.currentEmployee.id = null;
}, },
choiceWorks(work) { choiceWorks(day) {
return this.works.find((e) => e.work === work).text; let a = this.scheduleList.find((e) => e.date === day).status;
return this.works.find((e) => e.work === a).text;
}, },
choiceColor(work) { choiceColor(day) {
return this.works.find((e) => e.work === work).color; let a = this.scheduleList.find((e) => e.date === day).status;
return this.works.find((e) => e.work === a).color;
}, },
changeDays() { changeDays() {
this.days = moment().daysInMonth(); this.days = moment().daysInMonth();
@@ -138,6 +140,11 @@ export default {
this.employee.push(this.employeeList[index]); this.employee.push(this.employeeList[index]);
} }
}, },
choiceDay(day, employee) {
return this.scheduleList.find(
(e) => day === e.date && e.employee.id === employee
)?.date;
},
}, },
mounted() { mounted() {

View File

@@ -5,11 +5,6 @@ function prepareUrl(url) {
return `https://astra-dev.dopcore.com/api/${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) { function handleRequest(method, url, headers, attempts, body, type) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
(function internalRequest() { (function internalRequest() {
@@ -72,9 +67,7 @@ function request(method, url, headers = {}, body, type = "") {
body: JSON.stringify(body), body: JSON.stringify(body),
}; };
} }
if (type === "api") { return fetch(prepareUrl(url), requestOptions);
return fetch(prepareUrlApi(url), requestOptions);
} else return fetch(prepareUrl(url), requestOptions);
} }
function get(url, type, headers, attempts = 3) { function get(url, type, headers, attempts = 3) {