[WIP] Добавил стили и форму на страницу расписания
(cherry picked from commit 109c6319a07ae73dc761c8c7fc2ddc7887d27161)
This commit is contained in:
@@ -18,7 +18,8 @@
|
||||
)
|
||||
.item.py-2.px-4.cursor-pointer(
|
||||
v-for="item in items",
|
||||
:key="item.id"
|
||||
:key="item.id",
|
||||
:class="{'center': center}",
|
||||
@click="clickItem(item.id, item.label)"
|
||||
) {{ item.label }}
|
||||
</template>
|
||||
@@ -38,6 +39,7 @@ export default {
|
||||
borderNone: Boolean,
|
||||
separator: Boolean,
|
||||
placeholderOpacity: Boolean,
|
||||
center: Boolean,
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
data() {
|
||||
@@ -117,4 +119,7 @@ export default {
|
||||
height: 24px
|
||||
width: 1px
|
||||
border-radius: 1px
|
||||
.center
|
||||
display: flex
|
||||
justify-content: center
|
||||
</style>
|
||||
|
||||
@@ -1,48 +1,33 @@
|
||||
<template lang="pug">
|
||||
.wrapper.flex.w-full.relative.mx-2
|
||||
.schedule-wrapper.relative.flex.flex-col.px-6.py-6.h-full.w-full
|
||||
.schedule.flex-col
|
||||
.schedule-header.flex.w-full
|
||||
.flex.items-center(:style="{padding: '16px 102px'}")
|
||||
.text.font-bold Сотрудник
|
||||
.column-wrapper.flex
|
||||
.schedule-column.flex.flex-col.items-center.justify-center.px-2(
|
||||
v-for="day in result",
|
||||
:style="{backgroundColor: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? 'var(--bg-white-color-1)' : ''}"
|
||||
)
|
||||
.day.flex {{day.format("D")}}
|
||||
.week.flex {{day.format("ddd")}}
|
||||
.schedule-body.flex.w-full
|
||||
.edit.flex.items-center.justify-center.h-9.w-9
|
||||
.flex.icon-edit
|
||||
.name.flex
|
||||
.schedule-wrapper.relative.flex.flex-col.px-6.py-6.h-full.w-full.gap-y-5
|
||||
schedule-header
|
||||
schedule-body(:employee-list="employeeList")
|
||||
schedule-bar
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as moment from "moment";
|
||||
import ScheduleHeader from "@/pages/schedule/components/ScheduleHeader.vue";
|
||||
import ScheduleBar from "@/pages/schedule/components/ScheduleBar.vue";
|
||||
import ScheduleBody from "@/pages/schedule/components/ScheduleBody.vue";
|
||||
import { fetchWrapper } from "@/shared/fetchWrapper.js";
|
||||
export default {
|
||||
name: "TheSchedule",
|
||||
components: { ScheduleHeader, ScheduleBar, ScheduleBody },
|
||||
data() {
|
||||
return {
|
||||
days: "",
|
||||
result: [],
|
||||
startMonth: moment("2022-12-01"),
|
||||
employeeList: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
changeDays() {
|
||||
this.days = moment().daysInMonth();
|
||||
},
|
||||
pushMonth() {
|
||||
this.result.push(this.startMonth);
|
||||
for (let i = 2; i <= this.days; i++) {
|
||||
this.result.push(this.startMonth.clone().add(i - 1, "d"));
|
||||
}
|
||||
getSchedules() {
|
||||
fetchWrapper
|
||||
.get("general/employee/")
|
||||
.then((res) => (this.employeeList = res.results));
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.changeDays();
|
||||
this.pushMonth();
|
||||
this.getSchedules();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -56,31 +41,4 @@ export default {
|
||||
.schedule-wrapper
|
||||
background-color: var(--default-white)
|
||||
height: calc(100vh - 64px)
|
||||
|
||||
.schedule
|
||||
border: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-radius: 4px
|
||||
min-height: 87px
|
||||
|
||||
.schedule-header
|
||||
height: 50px
|
||||
background-color: #D7D9FF
|
||||
border-bottom: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-top-left-radius: 2px
|
||||
border-top-right-radius: 2px
|
||||
|
||||
.column-wrapper
|
||||
max-width: 1080px
|
||||
overflow: auto
|
||||
|
||||
.text
|
||||
color: var(--btn-blue-color)
|
||||
|
||||
.name
|
||||
min-width: 255px
|
||||
max-width: 255px
|
||||
border-right: 1.5px solid var(--border-light-grey-color-1)
|
||||
|
||||
.edit
|
||||
border-right: 1.5px solid var(--border-light-grey-color-1)
|
||||
</style>
|
||||
|
||||
64
src/pages/schedule/components/FormChangeShift.vue
Normal file
64
src/pages/schedule/components/FormChangeShift.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template lang="pug">
|
||||
.flex.flex-col.gap-y-6.pt-6.pb-7.px-8.event-form.fixed.right-6.bottom-6(
|
||||
v-click-outside="closeForm"
|
||||
)
|
||||
.flex.justify-between
|
||||
span.title.text-xl.font-bold Замена смен
|
||||
.flex.pt-2
|
||||
.icon-cancel.close-icon.tesxt-xs.cursor-pointer(@click="closeForm")
|
||||
.flex.flex-col.gap-y-6
|
||||
.flex.flex-col.gap-y-2
|
||||
span.text-smm.font-semibold Дата
|
||||
base-input-date.input-date
|
||||
.flex.flex-col(class="gap-y-1.5")
|
||||
span.text-smm.font-semibold Текущий сотрудник
|
||||
base-custom-select.h-10(v-model="currentEmployee")
|
||||
.flex.flex-col(class="gap-y-1.5")
|
||||
span.text-smm.font-semibold Замена сотрдника
|
||||
base-custom-select.h-10(v-model="currentEmployee")
|
||||
.time-wrapper.flex.justify-center
|
||||
.flex.flex-col.py-14px.px-4.gap-y-14px.items-center
|
||||
.text-xxs.opacity-40.font-bold Начало
|
||||
base-input-time.item-input.text-base.select(:width-input="40")
|
||||
.flex.flex-col.py-14px.px-4.gap-y-14px.items-center
|
||||
.text-xxs.opacity-40.font-bold Конец
|
||||
base-input-time.item-input.text-base.select(:width-input="40")
|
||||
.flex.justify-center
|
||||
base-button.font-semibold(:size="40") Сохранить
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseCustomSelect from "@/components/base/BaseCustomSelect.vue";
|
||||
import BaseInputDate from "@/components/base/BaseInputDate.vue";
|
||||
import BaseInputTime from "@/components/base/BaseInputTime.vue";
|
||||
import BaseButton from "@/components/base/BaseButton.vue";
|
||||
|
||||
export default {
|
||||
name: "FormChangeShift",
|
||||
components: { BaseCustomSelect, BaseInputDate, BaseInputTime, BaseButton },
|
||||
props: { closeForm: Function },
|
||||
data() {
|
||||
return {
|
||||
currentEmployee: { label: "", id: null },
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.event-form
|
||||
height: fit-content
|
||||
width: 534px
|
||||
background-color: var(--default-white)
|
||||
box-shadow: var(--default-shadow)
|
||||
border-radius: 4px
|
||||
z-index: 5
|
||||
|
||||
.select
|
||||
height: 40px
|
||||
border: 1.5px solid var(--border-light-grey-color)
|
||||
border-radius: 4px
|
||||
|
||||
.input-date
|
||||
border: 1.5px solid var(--border-light-grey-color)
|
||||
</style>
|
||||
131
src/pages/schedule/components/ScheduleBar.vue
Normal file
131
src/pages/schedule/components/ScheduleBar.vue
Normal file
@@ -0,0 +1,131 @@
|
||||
<template lang="pug">
|
||||
.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")
|
||||
.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'}"
|
||||
) Выходной
|
||||
.graph-template.flex
|
||||
base-custom-select(
|
||||
:items="scheduleList",
|
||||
center,
|
||||
v-model="schedule",
|
||||
placeholder="Шаблоны графиков"
|
||||
)
|
||||
.flex.justify-center
|
||||
base-button.font-semibold(:size="40") Сохранить
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseButton from "@/components/base/BaseButton.vue";
|
||||
import BaseCustomSelect from "@/components/base/BaseCustomSelect.vue";
|
||||
import BaseInputTime from "@/components/base/BaseInputTime.vue";
|
||||
export default {
|
||||
name: "ScheduleBar",
|
||||
components: { BaseButton, BaseCustomSelect, BaseInputTime },
|
||||
data() {
|
||||
return {
|
||||
scheduleList: [
|
||||
{ label: "Индивидуальный", id: 1 },
|
||||
{ label: "2/2", id: 2 },
|
||||
{ label: "3/2", id: 3 },
|
||||
{ label: "5/2", id: 4 },
|
||||
],
|
||||
schedule: {},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.wrapper-bar
|
||||
height: 224px
|
||||
border: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-radius: 4px
|
||||
|
||||
.time-wrapper
|
||||
width: 350px
|
||||
height: 102px
|
||||
border: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-radius: 4px
|
||||
|
||||
.select
|
||||
height: 40px
|
||||
border: 1.5px solid var(--border-light-grey-color)
|
||||
border-radius: 4px
|
||||
|
||||
.item-input
|
||||
appearance: none
|
||||
outline: none
|
||||
height: 40px
|
||||
&::-webkit-calendar-picker-indicator
|
||||
display: none
|
||||
-webkit-appearance: none
|
||||
&::placeholder
|
||||
color: var(--font-black-color-1)
|
||||
|
||||
.text
|
||||
color: var(--font-grey-color)
|
||||
|
||||
.status-wrapper
|
||||
width: 690px
|
||||
height: 102px
|
||||
border: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-radius: 4px
|
||||
|
||||
.button-work
|
||||
background: #55CD76
|
||||
border: none
|
||||
&:active
|
||||
background-color: #55CD76
|
||||
opacity: 1
|
||||
border: none
|
||||
&:hover
|
||||
background-color: #55CD76
|
||||
opacity: 0.8
|
||||
border: none
|
||||
|
||||
.button-status
|
||||
background: #D7D9FF
|
||||
border: none
|
||||
&:active
|
||||
background-color: #D7D9FF
|
||||
opacity: 1
|
||||
border: none
|
||||
&:hover
|
||||
background-color: #D7D9FF
|
||||
opacity: 0.8
|
||||
border: none
|
||||
|
||||
.button-free
|
||||
background: #9294A7
|
||||
border: none
|
||||
&:active
|
||||
background-color: #9294A7
|
||||
opacity: 1
|
||||
border: none
|
||||
&:hover
|
||||
background-color: #9294A7
|
||||
opacity: 0.8
|
||||
border: none
|
||||
|
||||
.graph-template
|
||||
width: 218px
|
||||
height: 40px
|
||||
</style>
|
||||
143
src/pages/schedule/components/ScheduleBody.vue
Normal file
143
src/pages/schedule/components/ScheduleBody.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template lang="pug">
|
||||
.schedule.flex-col
|
||||
.table-header.flex.w-full
|
||||
.flex.items-center(:style="{padding: '16px 102px'}")
|
||||
.text.font-bold Сотрудник
|
||||
.column-wrapper.flex
|
||||
.schedule-column.flex.flex-col.items-center.justify-center.px-2(
|
||||
v-for="day in result",
|
||||
:style="{backgroundColor: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? 'var(--bg-white-color-1)' : ''}"
|
||||
)
|
||||
.text.flex.font-bold(
|
||||
:style="{opacity: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? '0.6' : '1'}"
|
||||
) {{day.format("D")}}
|
||||
.text.flex.font-bold(
|
||||
:style="{opacity: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? '0.6' : '1'}"
|
||||
) {{day.format("ddd")}}
|
||||
.schedule-body.flex.w-full
|
||||
.edit.flex.items-center.justify-center.h-9.w-9
|
||||
.flex.icon-edit
|
||||
.name.flex.justify-center.items-center.cursor-pointer(v-if="schedule.employee.label", @click="openSelect")
|
||||
span {{schedule.employee.label}}
|
||||
.name.flex(v-if="!schedule.employee.label")
|
||||
base-custom-select(
|
||||
:items="ownersList",
|
||||
v-model="schedule.employee",
|
||||
placeholder="Добавить сотрудника",
|
||||
:style="{border: 'none'}"
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as moment from "moment";
|
||||
import BaseModal from "@/components/base/BaseModal.vue";
|
||||
import BaseCustomSelect from "@/components/base/BaseCustomSelect.vue";
|
||||
export default {
|
||||
name: "ScheduleBody",
|
||||
components: { BaseModal, BaseCustomSelect },
|
||||
props: {
|
||||
employeeList: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
days: "",
|
||||
result: [],
|
||||
startMonth: moment("2022-12-01"),
|
||||
showSelect: false,
|
||||
employee: [],
|
||||
schedule: {
|
||||
employee: {
|
||||
label: "",
|
||||
id: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
ownersList() {
|
||||
if (this.employeeList) {
|
||||
let filteredArray = [];
|
||||
this.employeeList.forEach((elem) => {
|
||||
filteredArray.push({
|
||||
id: elem.id,
|
||||
label: this.trimOwnerName(
|
||||
elem.last_name,
|
||||
elem.first_name,
|
||||
elem.patronymic
|
||||
),
|
||||
});
|
||||
});
|
||||
return filteredArray;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changeDays() {
|
||||
this.days = moment().daysInMonth();
|
||||
},
|
||||
pushMonth() {
|
||||
this.result.push(this.startMonth);
|
||||
for (let i = 2; i <= this.days; i++) {
|
||||
this.result.push(this.startMonth.clone().add(i - 1, "d"));
|
||||
}
|
||||
},
|
||||
trimOwnerName(lastName, firstName, patronymic) {
|
||||
let checkedFirstName = firstName !== null ? firstName[0] + "." : "";
|
||||
let checkedPatronymic = patronymic !== null ? patronymic[0] + "." : "";
|
||||
return `${lastName} ${checkedFirstName}${checkedPatronymic}`;
|
||||
},
|
||||
openSelect() {
|
||||
this.showSelect = true;
|
||||
for (let index = 0; index < this.employeeList.length; index++) {
|
||||
this.employee.push(this.employeeList[index]);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.changeDays();
|
||||
this.pushMonth();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.schedule
|
||||
border: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-radius: 4px
|
||||
min-height: 87px
|
||||
|
||||
.table-header
|
||||
height: 50px
|
||||
background-color: #D7D9FF
|
||||
border-bottom: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-top-left-radius: 2px
|
||||
border-top-right-radius: 2px
|
||||
|
||||
.column-wrapper
|
||||
max-width: 1080px
|
||||
overflow: auto
|
||||
|
||||
.text
|
||||
color: var(--btn-blue-color)
|
||||
|
||||
.edit
|
||||
border-right: 1.5px solid var(--border-light-grey-color-1)
|
||||
|
||||
.name
|
||||
min-width: 255px
|
||||
max-width: 255px
|
||||
border-right: 1.5px solid var(--border-light-grey-color-1)
|
||||
color: var(--btn-blue-color)
|
||||
|
||||
.modal-wrapper
|
||||
border: 1.5px solid var(--border-light-grey-color-1)
|
||||
border-radius: 4px
|
||||
width: 400px
|
||||
height: 500px
|
||||
</style>
|
||||
70
src/pages/schedule/components/ScheduleHeader.vue
Normal file
70
src/pages/schedule/components/ScheduleHeader.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template lang="pug">
|
||||
.flex.flex-col.gap-y-5
|
||||
.flex.justify-center.pl-8.pr-20.font-bold.text-xl Индивидуальный график
|
||||
form-change-shift(v-if="showForm", :close-form="closeForm")
|
||||
.flex
|
||||
.calendar-header-wrapper.flex.items-center.justify-between.py-3.pl-5.pr-6
|
||||
.flex
|
||||
base-button.left-arrow.mr-4(
|
||||
left-icon="icon-down-arrow",
|
||||
rounded,
|
||||
secondary,
|
||||
:iconLeftSize="16",
|
||||
:size="32"
|
||||
)
|
||||
base-button.right-arrow.mr-6(
|
||||
left-icon="icon-down-arrow",
|
||||
rounded,
|
||||
secondary,
|
||||
:iconLeftSize="16",
|
||||
:size="32"
|
||||
)
|
||||
.text.flex.items-center
|
||||
.flex.text-xl Жмых Олег Анатольевич
|
||||
base-button.font-semibold(:size="40", @click="openForm") Замена смен
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseButton from "@/components/base/BaseButton.vue";
|
||||
import FormChangeShift from "@/pages/schedule/components/FormChangeShift.vue";
|
||||
export default {
|
||||
name: "ScheduleHeader",
|
||||
components: { BaseButton, FormChangeShift },
|
||||
data() {
|
||||
return {
|
||||
showForm: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openForm() {
|
||||
this.showForm = true;
|
||||
},
|
||||
closeForm() {
|
||||
this.showForm = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.calendar-header-wrapper
|
||||
width: 100%
|
||||
background-color: var(--default-white)
|
||||
height: 56px
|
||||
border-radius: 4px
|
||||
z-index: 10
|
||||
|
||||
.left-arrow
|
||||
padding: 3px 4px 0 4px !important
|
||||
transform: rotate(90deg)
|
||||
|
||||
.right-arrow
|
||||
padding: 3px 4px 0 4px !important
|
||||
transform: rotate(270deg)
|
||||
|
||||
.text
|
||||
color: var(--font-dark-blue-color)
|
||||
|
||||
.today
|
||||
opacity: 0.5
|
||||
</style>
|
||||
Reference in New Issue
Block a user