Merge branch 'master' into 'feature/создание-договора'

# Conflicts:
#   src/components/base/BaseInputDate.vue
This commit is contained in:
Dmitriy Derbentsov
2022-12-26 22:12:44 +00:00
20 changed files with 893 additions and 2062 deletions

View File

@@ -4,7 +4,7 @@ WORKDIR /front
COPY . . COPY . .
RUN npm install RUN npm ci
RUN npm run build RUN npm run build
FROM nginx:1.21.6-alpine as runner FROM nginx:1.21.6-alpine as runner

2363
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@
"@babel/eslint-parser": "^7.12.16", "@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0", "@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0", "@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-vuex": "~4.5.12", "@vue/cli-plugin-vuex": "^5.0.8",
"@vue/cli-service": "~5.0.0", "@vue/cli-service": "~5.0.0",
"@webdiscus/pug-loader": "^2.9.4", "@webdiscus/pug-loader": "^2.9.4",
"eslint": "^8.25.0", "eslint": "^8.25.0",

View File

@@ -18,10 +18,10 @@
) )
.item.py-2.px-4.cursor-pointer( .item.py-2.px-4.cursor-pointer(
v-for="item in items", v-for="item in items",
:key="item.id", :key="item?.id",
:class="{'center': center}", :class="{'center': center}",
@click="clickItem(item.id, item.label)" @click="clickItem(item?.id, item?.label)"
) {{ item.label }} ) {{ item?.label }}
</template> </template>
<script> <script>

View File

@@ -18,6 +18,7 @@
</template> </template>
<script> <script>
//TODO: Переписать v-model:value, убрать лишнии пропсы, добавить label или вынести в отдельную компоненту
export default { export default {
name: "BaseInput", name: "BaseInput",
props: { props: {
@@ -32,9 +33,7 @@ export default {
iconPosition: { iconPosition: {
default: "right", default: "right",
}, },
placeholder: { placeholder: String,
default: "Поиск",
},
widthInput: Number, widthInput: Number,
borderNone: Boolean, borderNone: Boolean,
disabled: Boolean, disabled: Boolean,
@@ -49,6 +48,7 @@ export default {
order: -1 order: -1
.right .right
order: 1 order: 1
//TODO: Вынести grey borders в taiwindConfig
.input-wrapper .input-wrapper
border: 1.5px solid var(--border-light-grey-color) border: 1.5px solid var(--border-light-grey-color)
border-radius: 4px border-radius: 4px

View File

@@ -26,9 +26,7 @@ export default {
iconPosition: { iconPosition: {
default: "right", default: "right",
}, },
placeholder: { placeholder: String,
default: "Поиск",
},
widthInput: Number, widthInput: Number,
}, },
}; };

View File

@@ -0,0 +1,47 @@
<template lang="pug">
.container.flex.flex-col.gap-y-2
.label.font-semibold.text-smm(v-if="radioButtonsLabel") {{ radioButtonsLabel }}
.group.flex.gap-x-4.text-base(:class="{'flex-col gap-y-1': direction === 'col'}")
.option(v-for="item in items")
input.mr-2(
type="radio",
:id="item?.id",
:value="item?.value",
v-model="value"
)
span {{item?.label}}
</template>
<script>
export default {
name: "BaseRadioButtonsGroup",
emits: ["update:modelValue"],
props: {
modelValue: String,
radioButtonsLabel: String,
items: {
type: Array,
default: () => [],
},
direction: {
type: String,
default: "row",
},
},
computed: {
value: {
get() {
return this.modelValue;
},
set(value) {
this.$emit("update:modelValue", value);
},
},
},
};
</script>
<style lang="sass" scoped>
.label
color: var(--font-grey-color)
</style>

View File

@@ -48,6 +48,7 @@
</template> </template>
<script> <script>
//TODO: Вынести emits в массив
import { fetchWrapper } from "../../shared/fetchWrapper.js"; import { fetchWrapper } from "../../shared/fetchWrapper.js";
import * as moment from "moment/moment"; import * as moment from "moment/moment";
import CalendarSchedule from "./components/CalendarSchedule.vue"; import CalendarSchedule from "./components/CalendarSchedule.vue";
@@ -83,6 +84,7 @@ export default {
isOpenForm: false, isOpenForm: false,
WORKING_STATUS: "WORKS", WORKING_STATUS: "WORKS",
changeFormWasClosed: false, changeFormWasClosed: false,
//TODO: Вынести eventStatuses в config
eventStatuses: [ eventStatuses: [
{ {
id: 0, id: 0,

View File

@@ -170,6 +170,7 @@
</template> </template>
<script> <script>
//TODO: Разбить на несколько компонент
import ClientDetailInput from "@/pages/clients/components/ClientDetailInput"; import ClientDetailInput from "@/pages/clients/components/ClientDetailInput";
import BaseButton from "@/components/base/BaseButton"; import BaseButton from "@/components/base/BaseButton";
import TableAddingNewDoc from "@/pages/clients/components/TableAddingNewDoc"; import TableAddingNewDoc from "@/pages/clients/components/TableAddingNewDoc";

View File

@@ -1,6 +1,6 @@
<template lang="pug"> <template lang="pug">
.flex.flex-col.mb-1.mt-4 .flex.flex-col.mb-1.mt-4
span.font-medium.text-base.modal-text Вы действительно хотите удалить клиента? span.font-medium.text-base.modal-text {{ bodyText }}
.flex.gap-x-3.mt-6.font-semibold .flex.gap-x-3.mt-6.font-semibold
base-button( base-button(
outlined, outlined,
@@ -10,26 +10,22 @@
base-button( base-button(
outlined-red, outlined-red,
:size=40, :size=40,
@click="transmitDeleteClient" @click="clickConfirm"
) Удалить ) {{ confirmTitle }}
</template> </template>
<script> <script>
import BaseButton from "@/components/base/BaseButton.vue"; import BaseButton from "@/components/base/BaseButton.vue";
export default { export default {
name: "ClientTableDeleteModal", name: "ClientTableModal",
components: { components: {
BaseButton, BaseButton,
}, },
props: { props: {
confirmTitle: String,
bodyText: String,
closeModal: Function, closeModal: Function,
deletedClientId: String, clickConfirm: Function,
},
methods: {
transmitDeleteClient() {
this.$emit("delete-client", this.deletedClientId);
this.closeModal();
},
}, },
}; };
</script> </script>

View File

@@ -32,7 +32,7 @@
:update-data-client="updateDataClient", :update-data-client="updateDataClient",
:fetch-data-clients="fetchDataClients", :fetch-data-clients="fetchDataClients",
:fetch-created-client-data="fetchCreatedClientData", :fetch-created-client-data="fetchCreatedClientData",
:create-medical-card="createMedicalCard", :create-medical-card="medicalCardHandler",
:created-client-name="createdClientName", :created-client-name="createdClientName",
@delete-client="deleteClientHandler", @delete-client="deleteClientHandler",
@recover-client="clearDeletedRowId", @recover-client="clearDeletedRowId",
@@ -46,12 +46,15 @@
) )
base-modal( base-modal(
v-model="showModal", v-model="showModal",
title="Удалить клиента" :title="titleModal",
) )
client-table-delete-modal( client-table-modal(
v-for="modal in modalConfig"
v-show="modal.view"
:close-modal="closeModal", :close-modal="closeModal",
:deleted-client-id="deletedClientId", :click-confirm="modal.clickConfirm"
@delete-client="writeDeletedRowId" :confirm-title="modal.titleConfirm"
:body-text="modal.bodyText"
) )
</template> </template>
@@ -64,7 +67,7 @@ import ClientsTableCheckbox from "@/pages/clients/components/ClientsTableCheckbo
import BaseClientFormCreate from "@/components/base/BaseClientFormCreate"; import BaseClientFormCreate from "@/components/base/BaseClientFormCreate";
import ClientTablePagination from "./ClientTablePagination.vue"; import ClientTablePagination from "./ClientTablePagination.vue";
import BaseModal from "@/components/base/BaseModal.vue"; import BaseModal from "@/components/base/BaseModal.vue";
import ClientTableDeleteModal from "./ClientTableDeleteModal.vue"; import ClientTableModal from "./ClientTableModal.vue";
import FormCreateMedicalCard from "@/pages/clients/components/FormCreateMedicalCard"; import FormCreateMedicalCard from "@/pages/clients/components/FormCreateMedicalCard";
import BaseLoader from "@/components/Loader/BaseLoader.vue"; import BaseLoader from "@/components/Loader/BaseLoader.vue";
export default { export default {
@@ -77,7 +80,7 @@ export default {
BaseClientFormCreate, BaseClientFormCreate,
ClientTablePagination, ClientTablePagination,
BaseModal, BaseModal,
ClientTableDeleteModal, ClientTableModal,
FormCreateMedicalCard, FormCreateMedicalCard,
BaseLoader, BaseLoader,
}, },
@@ -91,6 +94,23 @@ export default {
data() { data() {
return { return {
modalConfig: [
{
name: "delete",
bodyText: "Вы действительно хотите удалить клиента?",
titleConfirm: "Удалить",
clickConfirm: this.writeDeletedRowId,
view: false,
},
{
name: "medical",
bodyText: "Медицинская карта отсутствует. Создать мед.карту?",
titleConfirm: "Создать",
clickConfirm: this.createMedicalCard,
view: false,
},
],
titleModal: "",
selectAll: false, selectAll: false,
marked: [], marked: [],
dataClients: [ dataClients: [
@@ -108,7 +128,7 @@ export default {
length: 0, length: 0,
}, },
showModal: false, showModal: false,
deletedClientId: "", clientId: "",
deletedRowId: "", deletedRowId: "",
clearingTextSearch: false, clearingTextSearch: false,
showMedicalCard: false, showMedicalCard: false,
@@ -233,21 +253,38 @@ export default {
openModal() { openModal() {
this.showModal = true; this.showModal = true;
}, },
createMedicalCard() { medicalCardHandler() {
this.showMedicalCard = true; this.modalConfig = this.modalConfig.map((el) => {
}, return el.name === "medical"
deleteClientHandler(id) { ? { ...el, view: true }
this.deletedClientId = id; : { ...el, view: false };
});
this.titleModal = "Создать мед.карту";
this.openModal(); this.openModal();
}, },
writeDeletedRowId(id) { createMedicalCard() {
this.deletedRowId = id; this.showMedicalCard = true;
this.closeModal();
},
deleteClientHandler(id) {
this.clientId = id;
this.modalConfig = this.modalConfig.map((el) => {
return el.name === "delete"
? { ...el, view: true }
: { ...el, view: false };
});
this.titleModal = "Удалить клиента";
this.openModal();
},
writeDeletedRowId() {
this.deletedRowId = this.clientId;
this.closeModal();
}, },
clearDeletedRowId() { clearDeletedRowId() {
this.deletedRowId = ""; this.deletedRowId = "";
}, },
clearDeletedClientId() { clearDeletedClientId() {
this.deletedClientId = ""; this.clientId = "";
}, },
changeClearingTextSearch() { changeClearingTextSearch() {
this.clearingTextSearch = false; this.clearingTextSearch = false;

View File

@@ -1,23 +1,32 @@
<template lang="pug"> <template lang="pug">
.wrap.flex.flex-col.gap-y-6 .wrapper.flex.flex-col.gap-y-6.justify-between
.flex.flex.flex-col.gap-y-9 .flex.flex.flex-col.gap-y-6
span.text-center.font-bold.text-xl Создание медицинской карты стоматологического пациента span.text-center.font-bold.text-xl Создание медицинской карты стоматологического пациента
.flex.justify-center.items-center.gap-x-2 .flex.self-center
base-button.button(:size="32", :rounded="true") base-stepper(
span(v-if="isBaseData") 1 :steps="steps",
.icon-ok.text-xs(v-else) :currentStep="currentStep"
span(:style="{color: 'var(--btn-blue-color)'}") Основное )
.line.flex.mx-2 component(v-bind:is="currentTabComponent")
base-button.button(:class="{'active-button': !isIdentityDoc && isBaseData}", :size="32", :rounded="true") .flex.justify-between
span(v-if="isBaseData") 2 .flex
.icon-ok.text-xs(v-else) base-button.font-semibold(
span(:style="{color: !isBaseData ? 'var(--btn-blue-color)' : 'var(--font-dark-blue-color)' }") ДУЛ :size="40",
.line.flex.mx-2 @click="prevStep",
base-button.button(:class="{'active-button': !isPolicyDoc }", :size="32", :rounded="true") 3 v-if="currentStep !== 0",
span(:style="{color: isPolicyDoc ? 'var(--btn-blue-color)' : 'var(--font-dark-blue-color)' }") Полис outlined,
medical-base-data(v-if="isBaseData", :change-base-data="changeBaseData") ) Назад
medical-identity-documents(v-if="isIdentityDoc", :change-identity-doc="changeIdentityDoc") .flex
medical-policy-documents(v-if="isPolicyDoc") base-button.font-semibold(
:size="40",
@click="nextStep",
v-if="currentStep < steps.length-1",
) Далее
base-button.font-semibold(
:size="40",
@click="finish",
v-if="currentStep === steps.length-1"
) Создать медицинскую карту
</template> </template>
<script> <script>
@@ -28,6 +37,7 @@ import BaseSelect from "@/components/base/BaseSelect";
import MedicalBaseData from "@/pages/medicalCard/components/MedicalBaseData"; import MedicalBaseData from "@/pages/medicalCard/components/MedicalBaseData";
import MedicalIdentityDocuments from "@/pages/medicalCard/components/MedicalIdentityDocuments"; import MedicalIdentityDocuments from "@/pages/medicalCard/components/MedicalIdentityDocuments";
import MedicalPolicyDocuments from "@/pages/medicalCard/components/MedicalPolicyDocuments"; import MedicalPolicyDocuments from "@/pages/medicalCard/components/MedicalPolicyDocuments";
import BaseStepper from "@/components/base/BaseStepper.vue";
export default { export default {
name: "FormCreateMedicalCard", name: "FormCreateMedicalCard",
@@ -39,68 +49,54 @@ export default {
MedicalBaseData, MedicalBaseData,
MedicalIdentityDocuments, MedicalIdentityDocuments,
MedicalPolicyDocuments, MedicalPolicyDocuments,
BaseStepper,
}, },
data() { data() {
return { return {
isBaseData: true, isBaseData: true,
isIdentityDoc: false, isIdentityDoc: false,
isPolicyDoc: false, isPolicyDoc: false,
currentStep: 0,
steps: [
{
id: 0,
label: "1",
value: "Основное",
component: "medical-base-data",
},
{
id: 1,
label: "2",
value: "ДУЛ",
component: "medical-identity-documents",
},
{
id: 2,
label: "3",
value: "Полис",
component: "medical-policy-documents",
},
],
}; };
}, },
computed: {
currentTabComponent: function () {
return this.steps[this.currentStep]?.component;
},
},
methods: { methods: {
changeBaseData() { nextStep() {
this.isBaseData = !this.isBaseData; this.currentStep += 1;
this.isIdentityDoc = !this.isIdentityDoc;
}, },
changeIdentityDoc() { prevStep() {
this.isIdentityDoc = !this.isIdentityDoc; this.currentStep -= 1;
this.isPolicyDoc = !this.isPolicyDoc;
}, },
finish() {},
}, },
}; };
</script> </script>
<style lang="sass" scoped> <style lang="sass" scoped>
.wrap .wrapper
width: 570px width: 570px
height: fit-content
min-height: 485px
.services-wrapper
border: 1px solid var(--btn-grey-color)
border-radius: 8px
.list-services
overflow-y: auto
max-height: 280px
.input-date
border: 1.5px solid var(--border-light-grey-color)
border-radius: 4px
.button
&:hover
background-color: var(--btn-blue-color)
border: none
.active-button
background: var(--btn-grey-color)
color: var(--font-dark-blue-color)
border-color: var(--btn-grey-color)
&:hover
background-color: var(--btn-grey-color)
border: none
.line
width: 78px
border: 1.5px solid var(--btn-grey-color)
.place
width: 100%
border: 2px dashed var(--font-grey-color)
border-radius: 4px
color: var(--font-grey-color)
.counter
color: var(--font-grey-color)
</style> </style>

View File

@@ -37,7 +37,7 @@
.flex.flex-col.gap-y-6 .flex.flex-col.gap-y-6
.flex.flex-col.gap-y-2 .flex.flex-col.gap-y-2
.font-bold Услуги .font-bold Услуги
.counter.text-smm Выберите подходищие из списка .counter.text-smm Выберите подходящие из списка
.services-wrapper.flex.flex-col.pt-4.px-4 .services-wrapper.flex.flex-col.pt-4.px-4
.flex.gap-x-2 .flex.gap-x-2
base-input( base-input(

View File

@@ -4,13 +4,22 @@
span.font-bold Основное span.font-bold Основное
.flex.flex-col.gap-y-6 .flex.flex-col.gap-y-6
base-input.w-full(placeholder="ФИО*") base-input.w-full(placeholder="ФИО*")
base-radio-buttons-group(
:items="gendersList",
radioButtonsLabel="Пол",
v-model="gender",
)
.flex.gap-x-4 .flex.gap-x-4
.flex.flex-col.gap-y-2 .flex.flex-col.gap-y-2
.counter.font-semibold.text-smm Дата рождения .counter.font-semibold.text-smm Дата рождения
base-input-date.input-date.h-10(:width-input="277") base-input-date.input-date.h-10(:width-input="277")
.flex.flex-col.gap-y-2 .flex.flex-col.gap-y-2
.counter.font-semibold.text-smm СНИЛС .counter.font-semibold.text-smm СНИЛС
base-input(:width-input="277", placeholder="000000000 00") base-input(
:width-input="277",
placeholder="000000000 00",
v-mask="'###-###-### ##'"
)
.flex.flex-col.gap-y-6 .flex.flex-col.gap-y-6
.flex.flex-col.gap-y-2 .flex.flex-col.gap-y-2
.counter.font-semibold.text-smm Адрес регистрации .counter.font-semibold.text-smm Адрес регистрации
@@ -29,9 +38,6 @@
.flex.flex-col.gap-y-2 .flex.flex-col.gap-y-2
.counter.font-semibold.text-smm Email .counter.font-semibold.text-smm Email
base-input(:width-input="277", placeholder="user@yandex.ru") base-input(:width-input="277", placeholder="user@yandex.ru")
.flex.py-2.justify-between
base-button(:size="40", @click="changeBaseData")
span.font-semibold Далее
</template> </template>
<script> <script>
@@ -40,13 +46,34 @@ import BaseInputDate from "@/components/base/BaseInputDate";
import BaseSelect from "@/components/base/BaseSelect"; import BaseSelect from "@/components/base/BaseSelect";
import BaseButton from "@/components/base/BaseButton"; import BaseButton from "@/components/base/BaseButton";
import { mask } from "vue-the-mask"; import { mask } from "vue-the-mask";
import BaseRadioButtonsGroup from "@/components/base/BaseRadioButtonsGroup.vue";
export default { export default {
name: "MedicalBaseData", name: "MedicalBaseData",
components: { BaseInput, BaseInputDate, BaseSelect, BaseButton }, components: {
BaseInput,
BaseInputDate,
BaseSelect,
BaseButton,
BaseRadioButtonsGroup,
},
directives: { mask }, directives: { mask },
props: { data() {
changeBaseData: Function, return {
gendersList: [
{
id: "1",
label: "Мужской",
value: "male",
},
{
id: "2",
label: "Женский",
value: "woman",
},
],
gender: "",
};
}, },
}; };
</script> </script>

View File

@@ -17,9 +17,6 @@
.flex.flex-col.gap-y-2 .flex.flex-col.gap-y-2
.counter.font-semibold.text-smm Страховая оганизация .counter.font-semibold.text-smm Страховая оганизация
base-input(:width-input="277", placeholder="Введите название организации") base-input(:width-input="277", placeholder="Введите название организации")
.flex.py-2
base-button(:size="40", @click="changeIdentityDoc")
span.font-semibold Далее
</template> </template>
<script> <script>

View File

@@ -23,9 +23,6 @@
:width-input="277", :width-input="277",
placeholder="+7 (915) 6449223" placeholder="+7 (915) 6449223"
) )
.flex.py-2
base-button(:size="40")
span.font-semibold Создать медицинскую карту
</template> </template>
<script> <script>

View File

@@ -1,19 +1,33 @@
<template lang="pug"> <template lang="pug">
.wrapper.flex.w-full.relative.mx-2 .wrapper.flex.w-full.relative.mx-2
.schedule-wrapper.relative.flex.flex-col.px-6.py-6.h-full.w-full.gap-y-5 .schedule-wrapper.relative.flex.flex-col.px-6.py-6.h-full.w-full.gap-y-5
schedule-header schedule-header(
:start-month="startMonth",
@switch-previous-month="switchPreviousMonth",
@switch-next-month="switchNextMonth"
)
schedule-body( schedule-body(
:employee-list="employeeList", :employee-list="employeeList",
:schedules-employee="fetchSchedulesEmployee", :schedules-employee="fetchSchedulesEmployee",
:schedule-list="scheduleList", :schedule-list="scheduleList",
:serialized="serialized", :serialized="serialized",
:data-schedule="dataSchedule", :data-schedule="dataSchedule",
:buttons="buttons" :buttons="buttons",
:start-month="startMonth",
:clear-employee="clearEmployee",
@new-date="createNewDate"
)
schedule-bar(
:data-schedule="dataSchedule",
:buttons="buttons",
:clear-employee="clearEmployee",
:times="times",
:create-schedule="postCreateSchedule"
) )
schedule-bar(:data-schedule="dataSchedule", :select-work="selectWork", :buttons="buttons")
</template> </template>
<script> <script>
import * as moment from "moment";
import ScheduleHeader from "@/pages/schedule/components/ScheduleHeader.vue"; import ScheduleHeader from "@/pages/schedule/components/ScheduleHeader.vue";
import ScheduleBar from "@/pages/schedule/components/ScheduleBar.vue"; import ScheduleBar from "@/pages/schedule/components/ScheduleBar.vue";
import ScheduleBody from "@/pages/schedule/components/ScheduleBody.vue"; import ScheduleBody from "@/pages/schedule/components/ScheduleBody.vue";
@@ -25,6 +39,7 @@ export default {
return { return {
employeeList: [], employeeList: [],
scheduleList: [], scheduleList: [],
clearEmployee: [],
serialized: [], serialized: [],
dataSchedule: { dataSchedule: {
status: "", status: "",
@@ -32,6 +47,7 @@ export default {
startTime: "", startTime: "",
endTime: "", endTime: "",
}, },
times: { start_time: "", end_time: "" },
buttons: [ buttons: [
{ {
class: "button-work", class: "button-work",
@@ -39,7 +55,7 @@ export default {
work: "WORKS", work: "WORKS",
active: false, active: false,
color: "#55CD76", color: "#55CD76",
text: "Р", text: "'Р'",
}, },
{ {
class: "button-status", class: "button-status",
@@ -47,19 +63,25 @@ export default {
work: "VACATION", work: "VACATION",
active: false, active: false,
color: "#D7D9FF", color: "#D7D9FF",
text: "О", text: "'О'",
}, },
{ {
class: "button-free", class: "button-free",
name: "Статусы", name: "Выходной",
work: "DAY_OFF", work: "DAY_OFF",
active: false, active: false,
color: "#9294A7", color: "#9294A7",
text: "В", text: "'В'",
}, },
], ],
startMonth: moment().startOf("month"),
}; };
}, },
computed: {
endMonth() {
return this.startMonth.clone().endOf("month");
},
},
methods: { methods: {
fetchSchedules() { fetchSchedules() {
fetchWrapper fetchWrapper
@@ -70,14 +92,17 @@ export default {
.then(() => this.fetchSchedulesEmployee()); .then(() => this.fetchSchedulesEmployee());
}, },
fetchSchedulesEmployee() { fetchSchedulesEmployee() {
this.employeeList.forEach((e) => { this.scheduleList = [];
fetchWrapper fetchWrapper
.get(`accounts/schedules/?employee=${e.id}`) .get(
`accounts/schedules/?date_after=${this.startMonth.format(
"YYYY-MM-DD"
)}&date_before=${this.endMonth.format("YYYY-MM-DD")}`
)
.then((data) => { .then((data) => {
this.scheduleList.push(...data.results); this.scheduleList.push(...data.results);
}) })
.then(() => this.filterScheduleEmployee()); .then(() => this.filterScheduleEmployee());
});
}, },
filterScheduleEmployee() { filterScheduleEmployee() {
let serialized = []; let serialized = [];
@@ -114,9 +139,45 @@ export default {
} }
}); });
this.serialized = serialized; this.serialized = serialized;
this.filterEmployee();
}, },
selectWork(work) { filterEmployee() {
this.dataSchedule.status = work; this.clearEmployee = [];
this.clearEmployee = this.employeeList.filter((item) =>
this.serialized.every((item2) => item2.id !== item.id)
);
},
postCreateSchedule() {
let currentEmployee = this.clearEmployee.find((e) => e.schedules);
fetchWrapper
.post("accounts/schedules/create/", {
employee: currentEmployee.id,
active_flg: true,
start_date: currentEmployee.schedules.start_date,
end_date: currentEmployee.schedules.end_date,
start_time: this.times.start_time,
end_time: this.times.end_time,
status: this.buttons.find((e) => e.active).work,
})
.then(() => this.fetchSchedules());
},
createNewDate(e) {
let schedules = {
start_date: e.start,
end_date: e.end,
};
this.clearEmployee.find((elem) => elem.id === e.id).schedules = schedules;
},
switchPreviousMonth() {
this.startMonth = this.startMonth.clone().subtract(1, "M");
},
switchNextMonth() {
this.startMonth = this.startMonth.clone().add(1, "M");
},
},
watch: {
startMonth() {
this.fetchSchedulesEmployee();
}, },
}, },
mounted() { mounted() {

View File

@@ -1,20 +1,20 @@
<template lang="pug"> <template lang="pug">
.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.gap-x-4
.time-wrapper.flex.justify-between .time-wrapper.flex.justify-between
.flex.flex-col.items-center.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-date.select(v-model:value="dataSchedule.endTime") base-input-time.select(v-model:value="times.start_time")
.flex.flex-col.items-center.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-date.select(v-model:value="dataSchedule.startTime") base-input-time.select(v-model:value="times.end_time")
.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.font-semibold( base-button.font-semibold(
v-for="item in buttons", v-for="item in buttons",
:class="item.class" , :class="item.class",
:key="item", :key="item",
:style="{minWidth: '190px', minHeight: '43px', border: item.active ? '1.5px solid #5E5E5E' : 'none'}", :style="{minWidth: '190px', minHeight: '43px', border: item.active ? '1.5px solid #5E5E5E' : 'none'}",
@click="choiceSchedule(item.class)" @click="choiceSchedule(item.class)"
@@ -27,7 +27,7 @@
placeholder="Шаблоны графиков" placeholder="Шаблоны графиков"
) )
.flex.justify-center .flex.justify-center
base-button.font-semibold(:size="40") Сохранить base-button.font-semibold(:size="40", @click="createSchedule") Сохранить
</template> </template>
<script> <script>
@@ -38,7 +38,13 @@ import BaseInputDate from "@/components/base/BaseInputDate.vue";
export default { export default {
name: "ScheduleBar", name: "ScheduleBar",
components: { BaseButton, BaseCustomSelect, BaseInputTime, BaseInputDate }, components: { BaseButton, BaseCustomSelect, BaseInputTime, BaseInputDate },
props: { dataSchedule: Object, selectWork: Function, buttons: Array }, props: {
dataSchedule: Object,
buttons: Array,
clearEmployee: Array,
times: Object,
createSchedule: Function,
},
data() { data() {
return { return {
scheduleList: [ scheduleList: [
@@ -66,7 +72,6 @@ export default {
border-radius: 4px border-radius: 4px
.time-wrapper .time-wrapper
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
@@ -90,7 +95,7 @@ export default {
color: var(--font-grey-color) color: var(--font-grey-color)
.status-wrapper .status-wrapper
width: 690px min-width: 690px
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

View File

@@ -1,7 +1,7 @@
<template lang="pug"> <template lang="pug">
.schedule.flex-col(:style="themeCell") .schedule.flex-col(:style="themeCell")
.table-header.flex.w-full .table-header.flex.w-full
.flex.items-center(:style="{padding: '16px 102px'}") .flex.items-center.justify-center.pl-11(:style="{width: 'calc(25% + 44px)'}")
.text.font-bold Сотрудник .text.font-bold Сотрудник
.column-wrapper.flex .column-wrapper.flex
.schedule-column.flex.flex-col.items-center.justify-center.w-11( .schedule-column.flex.flex-col.items-center.justify-center.w-11(
@@ -9,18 +9,17 @@
:style="{backgroundColor: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? 'var(--bg-white-color-1)' : ''}" :style="{backgroundColor: day.format('ddd') === 'сб' || day.format('ddd') === 'вс' ? 'var(--bg-white-color-1)' : ''}"
) )
.text.flex.font-bold( .text.flex.font-bold(
@click="selectDay(day.format('D'))"
:style="{opacity: changeOpacity(day)}" :style="{opacity: changeOpacity(day)}"
) {{day.format("D")}} ) {{day.format("D")}}
.text.flex.font-bold( .text.flex.font-bold(
:style="{opacity: changeOpacity(day)}" :style="{opacity: changeOpacity(day)}"
) {{day.format("ddd")}} ) {{day.format("ddd")}}
.schedule-body.flex.w-full(v-for="schedule in serialized", :key="schedule.id") .schedule-body.flex.w-full(v-for="schedule in serialized", :key="schedule.id")
.edit.flex.items-center.justify-center.h-9.w-9 .edit.flex.items-center.justify-center.h-11.w-11
.flex.icon-edit .flex.icon-edit
.name-employee.flex.justify-center.items-center.cursor-pointer(@click="openSelect(schedule)") .name-employee.flex.justify-center.items-center.cursor-pointer
span {{trimOwnerName(schedule.last_name, schedule.first_name, schedule.patronymic)}} span {{trimOwnerName(schedule.last_name, schedule.first_name, schedule.patronymic)}}
.cell.flex.flex-col.items-center.justify-center.w-11.cursor-pointer( .cell.flex.flex-col.items-center.justify-center.w-11.h-11.cursor-pointer(
v-for="day in result", v-for="day in result",
:key="day", :key="day",
:id="schedule.id + day", :id="schedule.id + day",
@@ -29,9 +28,9 @@
:style="{backgroundColor: day.format('YYYY-MM-DD') === choiceDay(day, schedule.id) ? choiceColor(day) : ''}" :style="{backgroundColor: day.format('YYYY-MM-DD') === choiceDay(day, schedule.id) ? choiceColor(day) : ''}"
) )
.flex {{day.format("YYYY-MM-DD") === choiceDay(day, schedule.id) ? choiceWorks(day) : ''}} .flex {{day.format("YYYY-MM-DD") === choiceDay(day, schedule.id) ? choiceWorks(day) : ''}}
//- .schedule-body.flex.w-full .schedule-body.flex.w-full(v-if="clearEmployee")
//- .edit.flex.items-center.justify-center.h-9.w-9 .edit.flex.items-center.justify-center.h-11.w-11(:style="{borderBottom: 'none'}")
//- .flex.items-center.gap-x-8 .flex.icon-edit(v-if="currentEmployee.label")
//- base-button( //- base-button(
//- confirm, //- confirm,
//- rounded, //- rounded,
@@ -41,17 +40,25 @@
//- 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" )
//- ) 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', justifyContent: 'center'}"
//- :style="{border: 'none'}" )
.cell.flex.flex-col.items-center.justify-center.w-11.h-11.cursor-pointer(
v-if="currentEmployee.label",
v-for="day in result",
:key="day",
:id="currentEmployee.id + day",
@click="choiceCell(day, currentEmployee.id)",
:class="selectTime(day, currentEmployee.id)",
:style="{borderBottom: 'none'}"
) )
</template> </template>
@@ -75,12 +82,13 @@ export default {
serialized: Array, serialized: Array,
dataSchedule: Object, dataSchedule: Object,
buttons: Array, buttons: Array,
startMonth: Object,
clearEmployee: Array,
}, },
data() { data() {
return { return {
days: "", days: "",
result: [], result: [],
startMonth: moment("2022-12-01"),
showSelect: false, showSelect: false,
employee: [], employee: [],
currentEmployee: { currentEmployee: {
@@ -99,9 +107,9 @@ export default {
}, },
computed: { computed: {
ownersList() { ownersList() {
if (this.employeeList) { if (this.clearEmployee) {
let filteredArray = []; let filteredArray = [];
this.employeeList.forEach((elem) => { this.clearEmployee.forEach((elem) => {
filteredArray.push({ filteredArray.push({
id: elem.id, id: elem.id,
label: this.trimOwnerName( label: this.trimOwnerName(
@@ -119,6 +127,7 @@ export default {
this.setActiveButton(); this.setActiveButton();
return { return {
"--bg-color-status": this.activeButton?.color, "--bg-color-status": this.activeButton?.color,
"--text-status": this.activeButton?.text,
}; };
}, },
}, },
@@ -142,6 +151,7 @@ export default {
this.dateInterval.id = id; this.dateInterval.id = id;
} else if (time.isAfter(this.dateInterval.start)) { } else if (time.isAfter(this.dateInterval.start)) {
this.dateInterval.end = formatTime; this.dateInterval.end = formatTime;
this.$emit("new-date", this.dateInterval);
} else this.dateInterval.start = formatTime; } else this.dateInterval.start = formatTime;
}, },
selectTime(day, id) { selectTime(day, id) {
@@ -174,13 +184,13 @@ export default {
}, },
choiceWorks(day) { choiceWorks(day) {
let currentDay = day.format("YYYY-MM-DD"); let currentDay = day.format("YYYY-MM-DD");
let a = this.scheduleList.find((e) => e.date === currentDay).status; let res = this.scheduleList.find((e) => e.date === currentDay).status;
return this.buttons.find((e) => e.work === a).text; return this.buttons.find((e) => e.work === res).text[1];
}, },
choiceColor(day) { choiceColor(day) {
let currentDay = day.format("YYYY-MM-DD"); let currentDay = day.format("YYYY-MM-DD");
let a = this.scheduleList.find((e) => e.date === currentDay).status; let res = this.scheduleList.find((e) => e.date === currentDay).status;
return this.buttons.find((e) => e.work === a).color; return this.buttons.find((e) => e.work === res).color;
}, },
changeDays() { changeDays() {
this.days = moment().daysInMonth(); this.days = moment().daysInMonth();
@@ -196,29 +206,18 @@ export default {
let checkedPatronymic = patronymic !== null ? patronymic[0] + "." : ""; let checkedPatronymic = patronymic !== null ? patronymic[0] + "." : "";
return `${lastName} ${checkedFirstName}${checkedPatronymic}`; return `${lastName} ${checkedFirstName}${checkedPatronymic}`;
}, },
// openSelect() {
// this.showSelect = true;
// for (let index = 0; index < this.employeeList.length; index++) {
// this.employee.push(this.employeeList[index]);
// }
// },
choiceDay(day, employee) { choiceDay(day, employee) {
let currentDay = day.format("YYYY-MM-DD"); let current = day.format("YYYY-MM-DD");
return this.scheduleList.find( return this.scheduleList.find(
(e) => currentDay === e.date && e.employee.id === employee (e) => current === e.date && e.employee.id === employee
)?.date; )?.date;
}, },
changeOpacity(day) { changeOpacity(day) {
return day.format("ddd") === "сб" || day.format("ddd") === "вс" return day.format("ddd") === "сб" || day.format("ddd") === "вс"
? "0.6" ? "0.6"
: "1"; : "1";
}, },
openSelect(schedule) {
console.log(schedule);
},
selectDay(day) {
console.log(day);
},
}, },
mounted() { mounted() {
@@ -232,7 +231,9 @@ export default {
.schedule .schedule
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
border-right: none
min-height: 87px min-height: 87px
width: calc(100vw - 136px)
.schedule-body .schedule-body
&:hover &:hover
@@ -256,14 +257,12 @@ export default {
border-bottom: 1.5px solid var(--border-light-grey-color-1) border-bottom: 1.5px solid var(--border-light-grey-color-1)
.name .name
min-width: 255px width: 25%
max-width: 255px
border-right: 1.5px solid var(--border-light-grey-color-1) border-right: 1.5px solid var(--border-light-grey-color-1)
color: var(--btn-blue-color) color: var(--btn-blue-color)
.name-employee .name-employee
min-width: 255px width: 25%
max-width: 255px
border-right: 1.5px solid var(--border-light-grey-color-1) border-right: 1.5px solid var(--border-light-grey-color-1)
border-bottom: 1.5px solid var(--border-light-grey-color-1) border-bottom: 1.5px solid var(--border-light-grey-color-1)
color: var(--btn-blue-color) color: var(--btn-blue-color)
@@ -281,6 +280,9 @@ export default {
.status .status
background-color: var(--bg-color-status) background-color: var(--bg-color-status)
.status::before
content: var(--text-status)
.from-date .from-date
background: limegreen background: limegreen

View File

@@ -6,6 +6,7 @@
.calendar-header-wrapper.flex.items-center.justify-between.py-3.pl-5.pr-6 .calendar-header-wrapper.flex.items-center.justify-between.py-3.pl-5.pr-6
.flex .flex
base-button.left-arrow.mr-4( base-button.left-arrow.mr-4(
@click="previousHandler",
left-icon="icon-down-arrow", left-icon="icon-down-arrow",
rounded, rounded,
secondary, secondary,
@@ -13,6 +14,7 @@
:size="32" :size="32"
) )
base-button.right-arrow.mr-6( base-button.right-arrow.mr-6(
@click="nextHandler",
left-icon="icon-down-arrow", left-icon="icon-down-arrow",
rounded, rounded,
secondary, secondary,
@@ -20,21 +22,40 @@
:size="32" :size="32"
) )
.text.flex.items-center .text.flex.items-center
.flex.text-xl Жмых Олег Анатольевич span.text.font-medium.text-base {{ dateString }}
span.today.font-bold.text-xxs.ml-2(v-if="isCurrentMonth") Текущий
//.flex.text-xl Жмых Олег Анатольевич
base-button.font-semibold(:size="40", @click="openForm") Замена смен base-button.font-semibold(:size="40", @click="openForm") Замена смен
</template> </template>
<script> <script>
import * as moment from "moment";
import BaseButton from "@/components/base/BaseButton.vue"; import BaseButton from "@/components/base/BaseButton.vue";
import FormChangeShift from "@/pages/schedule/components/FormChangeShift.vue"; import FormChangeShift from "@/pages/schedule/components/FormChangeShift.vue";
export default { export default {
name: "ScheduleHeader", name: "ScheduleHeader",
components: { BaseButton, FormChangeShift }, components: { BaseButton, FormChangeShift },
props: {
startMonth: Object,
},
data() { data() {
return { return {
showForm: false, showForm: false,
isCurrentMonth: true,
}; };
}, },
computed: {
dateString() {
return this.startMonth
.format("MMMM YYYY")
.split(" ")
.map((elem, index) => {
if (index === 0) return elem[0].toUpperCase() + elem.slice(1);
return elem;
})
.join(" ");
},
},
methods: { methods: {
openForm() { openForm() {
this.showForm = true; this.showForm = true;
@@ -42,6 +63,19 @@ export default {
closeForm() { closeForm() {
this.showForm = false; this.showForm = false;
}, },
previousHandler() {
this.$emit("switch-previous-month");
},
nextHandler() {
this.$emit("switch-next-month");
},
},
watch: {
startMonth() {
this.isCurrentMonth =
this.startMonth.format("YYYY-MM-DD") ===
moment().date(1).format("YYYY-MM-DD");
},
}, },
}; };
</script> </script>