task_ui/components/TaskGroupReport.vue
2025-04-21 11:49:42 +03:30

773 lines
20 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class=" container-fluid">
<div class="all-selects justify-content-between col-12">
<div class="selects col-md-4 justify-content-start align-items-center">
<div>
<label class="teams-label"> ماه: </label>
<select
id="month-select"
class="form-control ms-1"
v-model="selectedMonth"
@change="getMainList"
>
<option v-for="month in months" :key="month" :value="month">
{{ getPersianMonthName(month) }}
</option>
</select>
</div>
<div class="me-3 ms-3">
<label class="teams-label"> سال: </label>
<select
id="year-select"
class="form-select form-control"
v-model="selectedYear"
@change="getMainList"
>
<option v-for="year in years" :key="year" :value="year">
{{ year }}
</option>
</select>
</div>
<div>
<label class="teams-label">تیم ها:</label>
<select v-model="group_id" @change="getMainList" class="form-select form-control">
<option selected value="">همه</option>
<option v-for="item in groups" :value="item.id">
{{ item.title }}
</option>
</select>
</div>
<!-- <div>
<button
title="شروع"
type="button"
class="btn btn-primary btn-start"
@click.prevent="setActiveTab(navItem)"
>
شروع
</button>
</div> -->
</div>
<div
class="d-flex align-items-center grouping col-md-8 justify-content-end"
>
<div class="select-teams">
<label class="teams-label-Grouping"> گروه بندی:</label>
<select
v-model="groupType"
@change="getsorting()"
class="form-control"
>
<option selected value="nogroup">بدون گروه بندی</option>
<option value="day">روز</option>
<option value="category">دسته</option>
<option value="title">عنوان</option>
<option value="organ">سازمان</option>
</select>
</div>
<div class="switch-component">
<switch-component
name="switch-view-mode"
@change-mode="showchart($event)"
class="task-admin-switch"
texts1="Normal"
texts2="Chartical"
></switch-component>
</div>
</div>
</div>
<main
class="pages-content-container"
:class="{ expanded: !isSidebarCollapsed }"
>
<div class="pages-content pt-3">
<div class="" :class="{ 'd-flex': showPanel || showPanelTeams }">
<template v-if="canView">
<my-table
class="p-0 ms-3 col-4"
:tableActions="tableActions"
height="calc(100vh + -14em)"
minHeight="25em"
maxHeight="calc(100dvh + -13em)"
:paginationInfo="pagination"
:sortingInfo="sorting"
:items="mainList"
:fetchingData="fetchingData"
:tableColumns="tableColumns"
:totalPages="pagination.pages"
:showActions="false"
@search="searchUsers"
@reset-form="searchUsers"
@edit-table-item="toggleUsersPanel"
@page-changed="pageChanged"
@page-limit-changed="pageLimitChanged"
@sort-changed="sortChanged"
>
</my-table>
</template>
<no-data v-else>
<the-content-loading v-if="fetchingData"></the-content-loading>
<div
v-else
class="d-flex justify-content-center align-items-center"
>
<div
class="alert alert-warning d-flex justify-content-center align-items-center"
>
<span
class="tavasi tavasi-warning-circle color-inherit ms-1 text__32"
></span>
عدم دسترسی
</div>
</div>
</no-data>
<div class="col-md-8 form-sorting_group">
<component
v-if="showcomponent"
:is="changeSorting()"
:listItem="listItem"
:columns="columnGroup"
:workList="workList"
:userId="userId"
></component>
<pie-donut
class="mt-5"
v-if="showChart"
:dataPie="dataPie"
:PieOptions="PieOptions"
width="90%"
height="300px"
></pie-donut>
</div>
</div>
</div>
</main>
</div>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
import HttpService from "@services/httpService";
import menu from "@task/json/menu.json";
import adminApi from "@apis/adminApi";
import taskApi from "@apis/taskApi";
import { p2e } from "@plugins/persianNumber";
export default {
beforeMount() {
this.httpService = new HttpService( this.taskMicroServiceName
);
},
mounted() {
this.checkPermisionBeforGetList();
var d = new Date().toLocaleDateString("fa-IR");
let items = d.split("/");
this.selectedYear = p2e(items[0]);
this.selectedMonth = p2e(items[1]);
this.getWorkingHoursInformation();
this.getTaskGroups();
},
data() {
return {
PieOptions: {
radius: ["40%", "70%"],
selectedMode: "single",
},
showChart: false,
showcomponent: true,
listItem: [],
group_id: "",
groupType: "nogroup",
userId: "",
tasks: [{ category: "", title: "", duration: "" }],
groups: [],
months: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
years: ["1400", "1401", "1402", "1403", "1404", "1405"],
selectedYear: "",
selectedMonth: "",
mainList: [],
menu: menu,
firstTimeSearching: false,
httpService: undefined,
tableActions: [
{
showOutside: true,
show: true,
icon: "Component-242--1",
title: "تعیین مدیر",
to: {
name: "undefined",
},
selected: false,
disabled: false,
howToOpen: "",
href: "",
class: "edit-btn",
action: "edit-table-item",
},
{
showOutside: true,
show: true,
icon: "Component-295--1",
title: "حذف",
to: {
name: "undefined",
},
selected: false,
disabled: false,
howToOpen: "",
href: "",
class: "delete-btn",
action: "delete-table-item",
},
],
canView: false,
fetchingData: false,
tableColumns: [
{
isLink: true,
key: "firstName",
title: "نام",
width: "2",
},
{
isLink: true,
key: "lastname",
title: "نام خانوادگی",
width: "2",
},
{
isLink: true,
key: "team",
title: "تیم",
width: "2",
},
{
isLink: true,
key: "useTime",
title: "خالص ماهانه",
width: "2",
},
],
sorting: {
sortby: "",
sortorder: "", // asc | desc | none
},
selectedItem: {},
selectedItemClone: {},
cloneItems: [],
prevSelectedItemIndex: undefined,
users: [],
loading: false,
showPanel: true,
showPanelTeams: false,
workList: [],
rotated: false,
dataPie: [],
allUserId: "",
};
},
computed: {
columnGroup() {
if (this.groupType == "category")
return [
{ label: "دسته", key: "category", class: "col-6" },
{ label: "تعداد روز", key: "day_count", class: "col-2" },
{ label: "تعداد فرآیند", key: "task_count", class: "col-2" },
{ label: "مدت", key: "duration", class: "col-2" },
];
else if (this.groupType == "organ")
return [
{ label: "سازمان", key: "organ", class: "col-6" },
{ label: "تعداد روز", key: "day_count", class: "col-2" },
{ label: "تعداد فرآیند", key: "task_count", class: "col-2" },
{ label: "مدت", key: "duration", class: "col-2" },
];
else if (this.groupType == "title")
return [
{ label: "عنوان", key: "title", class: "col-6" },
{ label: "تعداد روز", key: "day_count", class: "col-2" },
{ label: "تعداد فرآیند", key: "category_count", class: "col-2" },
{ label: "مدت", key: "duration", class: "col-2" },
];
else return [
{ label: "تاریخ", key: "normalDate", class: "col-2" },
{ label: "دسته", key: "category", class: "col-3" },
{ label: "عنوان", key: "title", class: "col-6" },
{ label: "مدت", key: "duration", class: "col-1" },
];
},
buildName() {
return process.env.VUE_APP_BUILD_NAME + "-sidebar";
},
},
methods: {
...mapGetters(["isSidebarCollapsed"]),
...mapActions(["checkPermissions"]),
checkPermisionBeforGetList() {
if (this.fetchingData) return;
this.fetchingData = true;
this.checkPermissions({ _this: this, permission: "admin_list" })
.then(() => {
this.getMainList()
.then(() => {
this.canView = true;
this.fetchingData = false;
})
.catch(() => {
this.canView = false;
this.fetchingData = false;
});
})
.catch(() => {
this.canView = false;
this.fetchingData = false;
});
},
async getMainList() {
let url = taskApi.taskReport.getList;
let payload = {
group_id: this.group_id,
year: this.selectedYear,
month: this.selectedMonth,
...this.sorting,
...this.pagination,
};
return await this.httpService
.postRequest(url, payload)
.then((res) => {
// console.log("mainList", res.data);
this.mainList = res.data;
this.allUserId = this.mainList.map((item) => item.user_id).join(",");
this.pagination = { ...this.pagination, ...res.pagination };
// this.onLinkedTitleClick({
// rowItem: this.markActive(0),
// tableColumn: {},
// index: 0,
// });
})
.catch((err) => {
console.info(err);
})
.finally(() => {
this.getsorting();
if (this.showChart) {
this.getvalueChartDonut();
}
});
},
markActive(index) {
if (this.prevSelectedItemIndex !== undefined) {
this.$set(this.mainList[this.prevSelectedItemIndex], "active", false);
}
this.prevSelectedItemIndex = index;
this.$set(this.mainList[index], "active", true);
this.selectedItemClone = structuredClone(this.mainList[index]);
return this.selectedItemClone;
},
// onLinkedTitleClick({ rowItem, tableColumn, index }) {
// // console.log(this.group_id)
// this.userId = rowItem.user_id;
// let payload = {
// user_id: this.userId,
// year: this.selectedYear,
// month: this.selectedMonth,
// };
// const url = taskApi.workingHours.load;
// this.httpService
// .postRequest(url, payload)
// .then((res) => {
// this.workList = res.data;
// this.showPanel = true;
// this.markActive(index);
// })
// .finally(() => {
// if (this.showChart) {
// this.getvalueChartDonut();
// }
// this.getsorting();
// });
// },
getWorkingHoursInformation() {
// console.log(this.currentUser);
const payload = {
user_id: this.currentUser.user_id,
// offset: 0,
// limit: 50,
sortby: "taskDate",
sortorder: "desc",
year: this.selectedYear,
month: this.selectedMonth,
};
const url = taskApi.workingHours.load;
this.httpService
.postRequest(url, payload)
.then((res) => {
this.workList = res.data;
})
.finally(() => {
this.getsorting();
if (this.showChart) {
this.getvalueChartDonut();
}
});
},
datefa(item) {
let m = item * 1000;
let d = new Date(m).toLocaleDateString("fa-IR");
return d;
},
selectDate(items) {
if (items.oldDate) {
let item = items.oldDate.split("-");
let date = {};
date.day = item[2];
date.month = item[1];
date.year = item[0];
this.$emit("select-day", date);
}
},
updateUrl(url, query = "") {
url = url.replace("@offset", this.pagination.offset);
url = url.replace("@limit", this.pagination.limit);
url = url.replace("@sortby", this.sorting.sortby);
url = url.replace("@sortorder", this.sorting.sortorder);
// for searching groups.
if (query?.length) url = url.replace("@query", query);
else url = url.replace("/@query", query);
return url;
},
searchUsers(query = "") {
this.resetPagination();
this[groupType](query);
// this.getGroupsWithoutAdmin(query);
},
toggleUsersPanel(index = undefined) {
if (index !== undefined) {
if (this.prevSelectedItemIndex !== undefined)
this.mainList[this.prevSelectedItemIndex].active = false;
this.prevSelectedItemIndex = index;
this.$set(this.mainList[index], "active", true);
this.selectedItemClone = structuredClone(this.mainList[index]);
this.showPanel = true;
this.showPanelTeams = false;
} else {
this.resetForm();
}
},
resetForm() {
this.selectedItemClone = undefined;
this.users = [];
this.showPanel = false;
},
// pagination and sorting
resetPagination() {
this.pagination = {
pages: 0,
total: 0,
page: 1,
offset: 0,
limit: 10,
};
},
pageLimitChanged(paging) {
this.resetPagination();
this.pagination.limit = paging.limit;
this.getMainList();
// this[this.searchType]();
},
pageChanged(paging) {
let page = paging.pageNumber;
page -= 1;
this.pagination.offset = page * paging.limit;
this.pagination.limit = paging.limit;
this.pagination.page = paging.pageNumber;
this.getMainList();
// this[this.searchType]();
},
sortChanged(sorting) {
this.pagination.page = this.pagination.offset = 0;
this.sorting = sorting;
this.getMainList();
// this[this.searchType]();
},
updateList() {
this.resetPagination();
this.getMainList();
},
openCreatePanel() {
if (this.showPanelTeams) {
this.showPanelTeams = false;
} else {
this.showPanelTeams = true;
this.showPanel = false;
}
},
closeShowPanelTeams() {
this.showPanelTeams = false;
},
save(formData = undefined) {
if (this.loading) return;
this.loading = true;
const url = formData.id ? apis.users.update : apis.users.create;
formData;
this.httpService
.postRequest(url, formData)
.then((res) => {
this.getUsers().then(() => {
this.loading = false;
});
this.mySwalToast({
html: res.message,
});
this.showPanel = false;
this.resetForm();
})
.finally(() => {
this.loading = false;
});
},
getPersianMonthName(month) {
const monthNames = [
"فروردین",
"اردیبهشت",
"خرداد",
"تیر",
"مرداد",
"شهریور",
"مهر",
"آبان",
"آذر",
"دی",
"بهمن",
"اسفند",
];
return monthNames[parseInt(month) - 1];
},
getTaskGroups() {
const payload = {
organ: "",
sortby: "title",
sortorder: "asc",
};
const url = taskApi.taskReport.groupList;
this.httpService
.postRequest(url, payload)
.then((res) => {
this.groups = res.data;
});
},
changeSorting() {
if (this.groupType == "day") {
return "SortingByDayTasksAdmin";
} else {
return "SortingTasksAdmin";
}
},
getsorting() {
let payload = {
users_id: this.allUserId,
year: this.selectedYear,
month: this.selectedMonth,
group: this.groupType,
};
const url = taskApi.taskReport.sortgroup;
this.httpService
.postRequest(url, payload)
.then((res) => {
this.listItem = res.data;
// console.log("listItem:", res.data);
})
.finally(() => {
return "SortingTasksAdmin";
});
},
showchart(value) {
if (!value) {
this.showChart = true;
this.showcomponent = false;
this.getvalueChartDonut();
return "PieDonut";
} else {
this.showChart = false;
this.showcomponent = true;
}
},
getvalueChartDonut() {
let payload = {
users_id: this.allUserId,
year: this.selectedYear,
month: this.selectedMonth,
};
let url = taskApi.taskChart.donut;
var vm = this;
this.httpService.postRequest(url, payload).then((res) => {
// console.log("chart", res.data);
vm.dataPie = [];
res.data.forEach((element) => {
vm.dataPie.push({
y: element.Percent,
name: element.category,
// color: colors[5],
drilldown: {
categories: [element.category],
data: [element.Total],
},
});
});
});
},
},
components: {
UsersSearch: () =>
import(
"@admin/components/UsersSearch"
),
TeamForm: () =>
import( "@task/components/TeamForm"),
SortingTasksAdmin: () =>
import(
"@task/components/SortingTasksAdmin"
),
SortingByDayTasksAdmin: () =>
import(
"@task/components/SortingByDayTasksAdmin"
),
PieDonut: () => import("@components/charts/PieDonut.vue"),
SwitchComponent: () => import("@components/SwitchComponent.vue"),
},
};
</script>
<style lang="scss">
.task-system {
.table-container {
.table-responsive {
height: calc(100vh + -15em) !important;
.table {
font-size: 1rem;
}
}
}
}
</style>
<style scoped lang="scss">
.form-control {
border-radius: 0.5em;
height: 2.5em;
text-align: end;
}
// .side-panel {
// padding: 1em;
// width: 30em;
// max-width: 100%;
// background-color: #fafafa;
// border-right: 1px solid #eee;
// }
// .pages-content-container {
// margin-right: 6em;
// }
.selects {
display: flex;
// margin-right: 4em;
}
.all-selects {
display: flex;
width: 96%;
}
.select-teams {
display: flex;
align-items: center;
// width: 13em;
margin-top: 1em;
}
.teams-label {
// min-width: 3em;
margin-top: 0.5em;
position: relative;
top: 1.4em;
font-size: 0.8em;
right: 1em;
background-color: white;
z-index: 99;
}
.teams-label-Grouping {
// min-width: 5em;
width: 47%;
margin-top: 0.5em;
position: relative;
bottom: 1.3em;
font-size: 0.8em;
right: 6em;
background-color: white;
z-index: 99;
}
.card-header,
.card {
border-radius: 0.25em !important;
}
.card-body {
border-bottom: 1px rgb(223 223 223) solid;
font-size: 0.9rem;
}
.component {
padding-left: 5em !important;
z-index: 99;
}
.btn-start {
margin-top: 2em;
margin-right: 1em;
}
.form-control{
width: 6em;
}
</style>