Merge pull request 'Sprint-4/MS-37-FE-Evaluation' (#56) from Sprint-4/MS-37-FE-Evaluation into master
Reviewed-on: #56
This commit is contained in:
commit
5bc84a10b8
|
|
@ -33,22 +33,33 @@ class EvaluationController extends Controller
|
||||||
|
|
||||||
$projects = $this->jiraService->getAllProjects();
|
$projects = $this->jiraService->getAllProjects();
|
||||||
|
|
||||||
$query = UserCriteria::where('user_email', $userEmail);
|
$startDate = $request->input('fromDate');
|
||||||
|
$endDate = $request->input('toDate');
|
||||||
// Date filter
|
|
||||||
if ($request->filled('fromDate')) {
|
|
||||||
$fromDate = Carbon::parse($request->input('fromDate'));
|
|
||||||
$query->where('created_at', '>=', $fromDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->filled('toDate')) {
|
|
||||||
$toDate = Carbon::parse($request->input('toDate'));
|
|
||||||
$query->where('created_at', '<=', $toDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// End query
|
|
||||||
$userCriterias = $query->with(['sprint', 'criteria'])->get();
|
|
||||||
|
|
||||||
|
$userCriterias = UserCriteria::with([
|
||||||
|
'sprint' => function ($query) use ($startDate, $endDate) {
|
||||||
|
if ($startDate && $endDate) {
|
||||||
|
$query->whereBetween('complete_date', [$startDate, $endDate]);
|
||||||
|
} elseif ($startDate) {
|
||||||
|
$query->where('complete_date', '>=', $startDate);
|
||||||
|
} elseif ($endDate) {
|
||||||
|
$query->where('complete_date', '<=', $endDate);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'criteria',
|
||||||
|
])->where('user_email', $userEmail)
|
||||||
|
->whereHas('sprint', function ($query) use ($startDate, $endDate) {
|
||||||
|
if ($startDate && $endDate) {
|
||||||
|
$query->whereBetween('complete_date', [$startDate, $endDate]);
|
||||||
|
} elseif ($startDate) {
|
||||||
|
$query->where('complete_date', '>=', $startDate);
|
||||||
|
} elseif ($endDate) {
|
||||||
|
$query->where('complete_date', '<=', $endDate);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->get();
|
||||||
|
// dd($userCriterias);
|
||||||
|
// Xử lý dữ liệu thành cấu trúc mong muốn
|
||||||
$projectsData = $userCriterias->groupBy('sprint.project_id')->map(function ($userCriteriasByProject, $projectId) use ($projects) {
|
$projectsData = $userCriterias->groupBy('sprint.project_id')->map(function ($userCriteriasByProject, $projectId) use ($projects) {
|
||||||
$result = self::getProjectById($projects, $projectId);
|
$result = self::getProjectById($projects, $projectId);
|
||||||
return [
|
return [
|
||||||
|
|
@ -57,12 +68,13 @@ class EvaluationController extends Controller
|
||||||
$sprint = $userCriteriasBySprint->first()->sprint;
|
$sprint = $userCriteriasBySprint->first()->sprint;
|
||||||
return [
|
return [
|
||||||
'name' => $sprint->name,
|
'name' => $sprint->name,
|
||||||
|
'complete_date' => $sprint->complete_date ?? '',
|
||||||
'criterias' => $userCriteriasBySprint->map(function ($userCriteria) {
|
'criterias' => $userCriteriasBySprint->map(function ($userCriteria) {
|
||||||
$criteria = $userCriteria->criteria;
|
$criteria = $userCriteria->criteria;
|
||||||
return [
|
return [
|
||||||
'criteria' => $criteria->name,
|
'criteria' => $criteria->name,
|
||||||
'note' => $userCriteria->note ?? '',
|
'note' => $userCriteria->note ?? '',
|
||||||
'createdBy' => $userCriteria->created_by ?? '',
|
'createdBy' => $userCriteria->created_by ?? '', // Lấy tên user từ auth
|
||||||
'point' => $userCriteria->point ?? '',
|
'point' => $userCriteria->point ?? '',
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
|
|
@ -71,6 +83,7 @@ class EvaluationController extends Controller
|
||||||
];
|
];
|
||||||
})->values();
|
})->values();
|
||||||
|
|
||||||
|
// Trả về kết quả
|
||||||
return AbstractController::ResultSuccess($projectsData);
|
return AbstractController::ResultSuccess($projectsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,25 +86,36 @@ class TechnicalController extends Controller
|
||||||
{
|
{
|
||||||
$technicals = TechnicalUser::with('technical')
|
$technicals = TechnicalUser::with('technical')
|
||||||
->where('user_id', $userId)
|
->where('user_id', $userId)
|
||||||
|
->orderBy('point', 'desc')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
if ($technicals->isEmpty()) {
|
// Lấy tất cả các technical
|
||||||
return AbstractController::ResultError("No technicals found for this user.");
|
$allTechnicals = Technical::all();
|
||||||
|
|
||||||
|
if ($technicals->isEmpty() && $allTechnicals->isEmpty()) {
|
||||||
|
return AbstractController::ResultError("No technicals found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chuẩn bị dữ liệu để trả về
|
// Chuẩn bị dữ liệu để trả về
|
||||||
$technicalData = $technicals->map(function ($technicalUser) {
|
$technicalData = $allTechnicals->map(function ($technical) use ($technicals) {
|
||||||
|
// Tìm kiếm kỹ thuật từ bảng technical_users
|
||||||
|
$technicalUser = $technicals->firstWhere('technical_id', $technical->id);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => $technicalUser->technical->id,
|
'id' => $technical->id,
|
||||||
'name' => $technicalUser->technical->name,
|
'name' => $technical->name,
|
||||||
'level' => $technicalUser->technical->level,
|
'level' => $technical->level,
|
||||||
'point' => $technicalUser->point,
|
'point' => $technicalUser ? $technicalUser->point : 0, // Nếu không tồn tại, điểm mặc định là 0
|
||||||
'updated_at' => $technicalUser->updated_at
|
'updated_at' => $technicalUser ? $technicalUser->updated_at : null // Nếu không tồn tại, updated_at là null
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
return AbstractController::ResultSuccess($technicalData);
|
$sortedTechnicalData = $technicalData->sortByDesc('point')->values(); // values() để giữ lại chỉ số
|
||||||
|
|
||||||
|
|
||||||
|
return AbstractController::ResultSuccess($sortedTechnicalData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getTechnicalsOfUser()
|
public function getTechnicalsOfUser()
|
||||||
{
|
{
|
||||||
$userInfo = auth('admins')->user();
|
$userInfo = auth('admins')->user();
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,12 @@ export const createTestCase = API_URL + 'v1/admin/criterias/test-cases'
|
||||||
|
|
||||||
//Profile
|
//Profile
|
||||||
export const getProfilesData = API_URL + 'v1/admin/criterias/profiles-data'
|
export const getProfilesData = API_URL + 'v1/admin/criterias/profiles-data'
|
||||||
export const updateProfilesData = API_URL + 'v1/admin/criterias/profiles-data/update'
|
export const updateProfilesData =
|
||||||
|
API_URL + 'v1/admin/criterias/profiles-data/update'
|
||||||
|
|
||||||
|
export const getAllUser = API_URL + 'v1/admin/technical/get-all-user'
|
||||||
|
export const getAllTechByUserId =
|
||||||
|
API_URL + 'v1/admin/technical/get-tech-by-user-id'
|
||||||
|
|
||||||
export const evaluation = API_URL + 'v1/admin/evaluation/report'
|
export const evaluation = API_URL + 'v1/admin/evaluation/report'
|
||||||
|
export const sprintReview = API_URL + 'v1/admin/evaluation/sprint-review'
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,15 @@
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.totalBox {
|
||||||
|
width: 60%;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
align-items: end;
|
||||||
|
justify-content: right;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.headers {
|
.headers {
|
||||||
height: 6vh;
|
height: 6vh;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,7 @@ export const DataTableAll = ({
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
className={classes.paginationBox}
|
className={classes.totalBox}
|
||||||
display={infoTotal ? 'flex' : 'none'}
|
display={infoTotal ? 'flex' : 'none'}
|
||||||
>
|
>
|
||||||
<Text fz={'sm'} ta={'right'}>
|
<Text fz={'sm'} ta={'right'}>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Box, Table, Text } from '@mantine/core'
|
import { Box, Table, Text } from '@mantine/core'
|
||||||
import { IconCornerDownRight } from '@tabler/icons-react'
|
import { IconCornerDownRight } from '@tabler/icons-react'
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import classes from './ProjectInvolvement.module.css'
|
import classes from './ProjectInvolvement.module.css'
|
||||||
|
|
||||||
interface Project {
|
interface Project {
|
||||||
|
|
@ -81,6 +81,23 @@ const ProjectInvolvement = ({ dataProfile, page }: ProjectInvolvementProps) => {
|
||||||
const [expandedProjects, setExpandedProjects] = useState<ExpandedProjects>({})
|
const [expandedProjects, setExpandedProjects] = useState<ExpandedProjects>({})
|
||||||
const [expandedSprints, setExpandedSprints] = useState<ExpandedSprints>({})
|
const [expandedSprints, setExpandedSprints] = useState<ExpandedSprints>({})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const initialProjectState: ExpandedProjects = {}
|
||||||
|
const initialSprintState: ExpandedSprints = {}
|
||||||
|
|
||||||
|
dataProfile.forEach((project) => {
|
||||||
|
initialProjectState[project.name] = true // Expand all projects by default
|
||||||
|
initialSprintState[project.name] = {}
|
||||||
|
|
||||||
|
project.sprints.forEach((sprint) => {
|
||||||
|
initialSprintState[project.name][sprint.name] = true // Expand all sprints by default
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
setExpandedProjects(initialProjectState)
|
||||||
|
setExpandedSprints(initialSprintState)
|
||||||
|
}, [dataProfile])
|
||||||
|
|
||||||
const handleProjectToggle = (projectName: string) => {
|
const handleProjectToggle = (projectName: string) => {
|
||||||
setExpandedProjects((prev) => ({
|
setExpandedProjects((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
import { evaluation, getProfilesData } from '@/api/Admin'
|
import {
|
||||||
|
evaluation,
|
||||||
|
getAllTechByUserId,
|
||||||
|
getAllUser,
|
||||||
|
sprintReview
|
||||||
|
} from '@/api/Admin'
|
||||||
import DataTableAll from '@/components/DataTable/DataTable'
|
import DataTableAll from '@/components/DataTable/DataTable'
|
||||||
import ProjectInvolvement from '@/components/ProjectInvolvement/ProjectInvolvement'
|
import ProjectInvolvement from '@/components/ProjectInvolvement/ProjectInvolvement'
|
||||||
import { get } from '@/rtk/helpers/apiService'
|
import { get } from '@/rtk/helpers/apiService'
|
||||||
import { Box, Button, Select, Text, Title } from '@mantine/core'
|
import { Box, Button, Loader, Select, Text, Title } from '@mantine/core'
|
||||||
import { DateInput } from '@mantine/dates'
|
import { DateInput } from '@mantine/dates'
|
||||||
import { notifications } from '@mantine/notifications'
|
import { notifications } from '@mantine/notifications'
|
||||||
|
import axios from 'axios'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import classes from './StaffEvaluation.module.css'
|
import classes from './StaffEvaluation.module.css'
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
id: number
|
id: number
|
||||||
|
|
@ -28,8 +33,19 @@ interface Filter {
|
||||||
// other properties of the filter object
|
// other properties of the filter object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DataTechnical {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
level: number
|
||||||
|
point: number
|
||||||
|
updated_at: string
|
||||||
|
}
|
||||||
|
|
||||||
const StaffEvaluation = () => {
|
const StaffEvaluation = () => {
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [loadingTechnical, setLoadingTechnical] = useState(false)
|
||||||
const [dataProfile, setDataProfile] = useState<any>([])
|
const [dataProfile, setDataProfile] = useState<any>([])
|
||||||
|
const [dataTechnical, setDataTechnical] = useState<DataTechnical[]>([])
|
||||||
const [listUsers, setListUsers] = useState<User[]>([])
|
const [listUsers, setListUsers] = useState<User[]>([])
|
||||||
const [filter, setFilter] = useState<Filter>({
|
const [filter, setFilter] = useState<Filter>({
|
||||||
userID: '',
|
userID: '',
|
||||||
|
|
@ -39,36 +55,10 @@ const StaffEvaluation = () => {
|
||||||
|
|
||||||
console.log(filter, 'filter')
|
console.log(filter, 'filter')
|
||||||
|
|
||||||
// const getAllTracking = async () => {
|
const getListUser = async () => {
|
||||||
// try {
|
|
||||||
// const searchParams = new URLSearchParams(window.location.search)
|
|
||||||
// const params = {}
|
|
||||||
|
|
||||||
// for (const [key, value] of searchParams.entries()) {
|
|
||||||
// if (key === 'page' && value === '') {
|
|
||||||
// Object.assign(params, { [`${key}`]: 1 })
|
|
||||||
// } else {
|
|
||||||
// Object.assign(params, { [`${key}`]: value })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const res = await get(getListTracking, params)
|
|
||||||
// if (res.status) {
|
|
||||||
// setListTracking(res)
|
|
||||||
// }
|
|
||||||
// } catch (error:any) {
|
|
||||||
// notifications.show({
|
|
||||||
// title: 'Error',
|
|
||||||
// message: error.message??error,
|
|
||||||
// color: 'red',
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const getListProfilesData = async () => {
|
|
||||||
try {
|
try {
|
||||||
const params = {}
|
const params = {}
|
||||||
const res = await get(getProfilesData, params)
|
const res = await get(getAllUser, params)
|
||||||
if (res.status) {
|
if (res.status) {
|
||||||
return res.data
|
return res.data
|
||||||
}
|
}
|
||||||
|
|
@ -115,18 +105,96 @@ const StaffEvaluation = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
const result = await getListProfilesData()
|
const result = await getListUser()
|
||||||
setDataProfile(result ?? [])
|
|
||||||
setListUsers(result ?? [])
|
setListUsers(result ?? [])
|
||||||
}
|
}
|
||||||
fetchData()
|
fetchData()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const getListProfilesData = async (filterSearch: Filter) => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
userID: filterSearch.userID ?? '',
|
||||||
|
fromDate: filterSearch.fromDate
|
||||||
|
? moment(filterSearch.fromDate).format('YYYY-MM-DD')
|
||||||
|
: null,
|
||||||
|
toDate: filterSearch.toDate
|
||||||
|
? moment(filterSearch.toDate).format('YYYY-MM-DD')
|
||||||
|
: null,
|
||||||
|
}
|
||||||
|
const res = await get(sprintReview, params)
|
||||||
|
if (res.status) {
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
notifications.show({
|
||||||
|
title: 'Error',
|
||||||
|
message: error.message ?? error,
|
||||||
|
color: 'red',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const getListTechnicalByUserId = async (id: string) => {
|
||||||
|
try {
|
||||||
|
const params = {}
|
||||||
|
const res = await get(`${getAllTechByUserId}/${id}`, params)
|
||||||
|
if (res.status) {
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
notifications.show({
|
||||||
|
title: 'Error',
|
||||||
|
message: error.message ?? error,
|
||||||
|
color: 'red',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (filter?.userID) {
|
||||||
|
setLoading(true)
|
||||||
|
const fetchData = async () => {
|
||||||
|
const result = await getListProfilesData(filter)
|
||||||
|
setDataProfile(result ?? [])
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
}, [filter])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (filter?.userID) {
|
||||||
|
setLoadingTechnical(true)
|
||||||
|
const fetchData = async () => {
|
||||||
|
const result = await getListTechnicalByUserId(filter?.userID)
|
||||||
|
setDataTechnical(result ?? [])
|
||||||
|
setLoadingTechnical(false)
|
||||||
|
}
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
}, [filter?.userID])
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'level',
|
name: 'level',
|
||||||
size: '20%',
|
size: '10%',
|
||||||
header: 'Level',
|
header: 'Level',
|
||||||
|
render: (row: any) => {
|
||||||
|
if (row.level)
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{row?.level}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
|
@ -138,16 +206,17 @@ const StaffEvaluation = () => {
|
||||||
size: '10%',
|
size: '10%',
|
||||||
header: 'Point',
|
header: 'Point',
|
||||||
render: (row: any) => {
|
render: (row: any) => {
|
||||||
return (
|
if (row?.point > 0)
|
||||||
<div
|
return (
|
||||||
style={{
|
<div
|
||||||
display: 'flex',
|
style={{
|
||||||
justifyContent: 'center',
|
display: 'flex',
|
||||||
}}
|
justifyContent: 'center',
|
||||||
>
|
}}
|
||||||
{row?.point}
|
>
|
||||||
</div>
|
{row?.point}
|
||||||
)
|
</div>
|
||||||
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -162,31 +231,33 @@ const StaffEvaluation = () => {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{moment(row?.updated_at).format('HH:mm:ss DD/MM/YYYY')}
|
{moment(row?.updated_at).format('DD/MM/YYYY HH:mm:ss')}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const users = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
level: 'Level 1',
|
|
||||||
name: 'React JS',
|
|
||||||
point: 3,
|
|
||||||
created_at: null,
|
|
||||||
updated_at: '2024-09-19T09:08:48.000000Z',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const infoTotal = () => {
|
const infoTotal = () => {
|
||||||
|
// Tính tổng point và số lượng point > 0
|
||||||
|
let totalPoint = 0
|
||||||
|
let count = 0
|
||||||
|
|
||||||
|
dataTechnical.forEach((item) => {
|
||||||
|
if (item.point > 0) {
|
||||||
|
totalPoint += item.point
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const averagePoint = count > 0 ? (totalPoint / count).toFixed(2) : '0.00'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<Text mr={20} fs={'italic'}>
|
<Text mr={20} fs={'italic'}>
|
||||||
Avg:{users.length}
|
Avg: {averagePoint}
|
||||||
</Text>
|
</Text>
|
||||||
<Text fs={'italic'}>Total: {users.length}</Text>
|
<Text fs={'italic'}>Total: {totalPoint}</Text>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -198,6 +269,7 @@ const StaffEvaluation = () => {
|
||||||
Staff Evaluation
|
Staff Evaluation
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Box w="100%" display={'flex'} mt={15} ml={10}>
|
<Box w="100%" display={'flex'} mt={15} ml={10}>
|
||||||
<Box w="50%" display={'flex'}>
|
<Box w="50%" display={'flex'}>
|
||||||
<Text
|
<Text
|
||||||
|
|
@ -209,11 +281,16 @@ const StaffEvaluation = () => {
|
||||||
User:
|
User:
|
||||||
</Text>
|
</Text>
|
||||||
<Select
|
<Select
|
||||||
|
style={{ width: '50%' }}
|
||||||
label={''}
|
label={''}
|
||||||
placeholder="Select user"
|
placeholder="Select user"
|
||||||
maxLength={255}
|
maxLength={255}
|
||||||
required
|
required
|
||||||
data={listUsers.map((i: User) => i.name)}
|
data={listUsers.map((i: User) => ({
|
||||||
|
value: i.id.toString(),
|
||||||
|
label: i.name,
|
||||||
|
}))}
|
||||||
|
value={filter.userID}
|
||||||
onChange={(e) => setFilter({ ...filter, userID: e! })}
|
onChange={(e) => setFilter({ ...filter, userID: e! })}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -280,20 +357,63 @@ const StaffEvaluation = () => {
|
||||||
></DateInput>
|
></DateInput>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<ProjectInvolvement dataProfile={dataProfile} page="admin" />
|
<Box
|
||||||
|
style={{
|
||||||
|
marginTop: '10%',
|
||||||
|
textAlign: 'center',
|
||||||
|
display: loading ? 'block' : 'none',
|
||||||
|
// display: 'none',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Loader size={'sm'} color="green" type="bars" m={'0 auto'} />
|
||||||
|
<Text fw={600} c={'gray'}>
|
||||||
|
Loading . . .
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
{!loading && dataProfile.length == 0 && (
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
marginTop: '10%',
|
||||||
|
textAlign: 'center',
|
||||||
|
display: 'block',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text fw={600} c={'gray'}>
|
||||||
|
No Data Sprint
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{!loading && (
|
||||||
|
<ProjectInvolvement dataProfile={dataProfile} page="admin" />
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box className={classes.sidebar}>
|
<Box className={classes.sidebar}>
|
||||||
<Title order={3} className={classes.titleSidebar}>
|
<Title order={3} className={classes.titleSidebar}>
|
||||||
Technicals
|
Technicals
|
||||||
</Title>
|
</Title>
|
||||||
<DataTableAll
|
{loadingTechnical ? (
|
||||||
data={users}
|
<Box
|
||||||
columns={columns}
|
style={{
|
||||||
size=""
|
marginTop: '10%',
|
||||||
searchInput
|
textAlign: 'center',
|
||||||
infoTotal={infoTotal()}
|
display: 'block',
|
||||||
/>
|
}}
|
||||||
|
>
|
||||||
|
<Loader size={'sm'} color="green" type="bars" m={'0 auto'} />
|
||||||
|
<Text fw={600} c={'gray'}>
|
||||||
|
Loading . . .
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<DataTableAll
|
||||||
|
data={dataTechnical}
|
||||||
|
columns={columns}
|
||||||
|
size=""
|
||||||
|
searchInput
|
||||||
|
infoTotal={infoTotal()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue