diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/TrackingController.php b/BACKEND/Modules/Admin/app/Http/Controllers/TrackingController.php index bfba961..095d5c7 100755 --- a/BACKEND/Modules/Admin/app/Http/Controllers/TrackingController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/TrackingController.php @@ -289,33 +289,32 @@ class TrackingController extends Controller $lateMorning = 0; $onTimeAfternoon = 0; $lateAfternoon = 0; - $valueTracking = $trackingData->get(); + $returnTracking = $trackingData->get(); + $listLate = []; - $trackingData->get()->groupBy(function ($record) { + $returnTracking->groupBy(function ($record) { return Carbon::parse($record->time_string)->toDateString(); - })->each(function ($records, $date) use ($trackingData, &$onTimeMorning, &$lateMorning, &$onTimeAfternoon, &$lateAfternoon, &$datesChecked) { + })->each(function ($records, $date) use ($userID, &$listLate, &$onTimeMorning, &$lateMorning, &$onTimeAfternoon, &$lateAfternoon, &$datesChecked) { $morningCheck = $records->filter(function ($record) { return Carbon::parse($record->time_string)->hour < 12; })->sortBy('time_string')->first(); $afternoonCheck = $records->filter(function ($record) { - return Carbon::parse($record->time_string)->hour >= 12; + $time = Carbon::parse($record->time_string)->hour; + return $time >= 12 && $time <= 14; })->sortBy('time_string')->first(); $morningTime = Carbon::parse($date)->setTime(7, 40, 0); $afternoonTime = Carbon::parse($date)->setTime(13, 10, 0); $checkOutAfternoonTime = Carbon::parse($date)->setTime(15, 00, 0); - $checkOutAfternoon = $trackingData->where( - DB::raw("STR_TO_DATE(time_string, '%Y-%m-%d %H:%i:%s')"), - '<=', - $date . ' 23:59:59' - )->where("status", "check out")->first(); + if ($morningCheck) { $checkInTime = Carbon::parse($morningCheck->time_string); if ($checkInTime->lessThanOrEqualTo($morningTime)) { $onTimeMorning++; } else { + array_push($listLate, $morningCheck->id); $lateMorning++; } } @@ -325,22 +324,40 @@ class TrackingController extends Controller if ($checkInTime->lessThanOrEqualTo($afternoonTime)) { $onTimeAfternoon++; } else { + array_push($listLate, $afternoonCheck->id); $lateAfternoon++; } } else { + // print ($date . "\n"); + $checkOutAfternoon = Tracking::where('user_id', $userID)->whereBetween( + DB::raw("STR_TO_DATE(time_string, '%Y-%m-%d %H:%i:%s')"), + [$date, $date . ' 23:59:59'], + )->where("status", "check out")->first(); // check if not check-in afternoon but has check out - if ($checkOutAfternoon && $checkOutAfternoonTime->lessThanOrEqualTo(Carbon::parse($checkOutAfternoon->time_string))) { - $onTimeAfternoon++; + if ($checkOutAfternoon) { + $timeCheck = Carbon::parse($checkOutAfternoon->time_string); + // print ($timeCheck . "\n"); + if ($checkOutAfternoon && $timeCheck->greaterThanOrEqualTo($checkOutAfternoonTime)) { + $onTimeAfternoon++; + } } } + }); + // ** Add `isLate` flag to each record ** + foreach ($returnTracking as $record) { + if (in_array($record->id, $listLate)) { + $record->isLate = true; + } + } + return AbstractController::ResultSuccess([ 'on_time_morning' => $onTimeMorning, 'late_morning' => $lateMorning, 'on_time_afternoon' => $onTimeAfternoon, 'late_afternoon' => $lateAfternoon, - 'value' => $valueTracking + 'value' => $returnTracking ]); } } diff --git a/FRONTEND/src/components/DataTable/DataTable.tsx b/FRONTEND/src/components/DataTable/DataTable.tsx index 627d18d..06c80fb 100755 --- a/FRONTEND/src/components/DataTable/DataTable.tsx +++ b/FRONTEND/src/components/DataTable/DataTable.tsx @@ -11,6 +11,7 @@ import { MultiSelect, Pagination, RadioGroup, + ScrollArea, Select, Skeleton, Table, @@ -85,6 +86,8 @@ export const DataTableAll = ({ size, infoTotal, componentRight, + height = 600, + keyHighlight = '', }: { data: any[] columns: Column[] @@ -94,6 +97,8 @@ export const DataTableAll = ({ size: string infoTotal?: React.ReactNode // Set the type to ReactNode to allow JSX elements componentRight?: React.ReactNode + height?: number + keyHighlight?: string }) => { const [Tdata, setTData] = useState(data) // const [tempData, setTempData] = useState([]) @@ -206,6 +211,9 @@ export const DataTableAll = ({ ? 'var(--mantine-color-blue-light)' : undefined } + style={{ + backgroundColor: element[keyHighlight] ? '#ff70704d' : 'transparent', + }} > {componentRight} - - - - - - - setSelectedRows( - event.currentTarget.checked - ? (pre) => [...pre, ...Tdata] - : selectedRows.filter( - (item) => - !Tdata.some((removeItem) => - areObjectsEqual(item, removeItem), - ), - ), - ) - } - /> - - {headers} - - - {rows} -
+ + + + + + + + setSelectedRows( + event.currentTarget.checked + ? (pre) => [...pre, ...Tdata] + : selectedRows.filter( + (item) => + !Tdata.some((removeItem) => + areObjectsEqual(item, removeItem), + ), + ), + ) + } + /> + + {headers} + + + {rows} +
+
) diff --git a/FRONTEND/src/pages/StaffEvaluation/StaffEvaluation.tsx b/FRONTEND/src/pages/StaffEvaluation/StaffEvaluation.tsx index 5867c8c..0a431f3 100644 --- a/FRONTEND/src/pages/StaffEvaluation/StaffEvaluation.tsx +++ b/FRONTEND/src/pages/StaffEvaluation/StaffEvaluation.tsx @@ -702,6 +702,35 @@ const StaffEvaluation = () => { }, ] + const columnsDetailWorking = [ + { + name: 'name', + size: '25%', + header: 'Name', + }, + { + name: 'time_string', + size: '25%', + header: 'Time', + render: (row: any) => { + return moment(row.time_string).format('YYYY/MM/DD - HH:mm:ss') + }, + }, + { + name: 'status', + size: '25%', + header: 'Status', + }, + { + name: 'created_at', + size: '25%', + header: 'Created at', + render: (row: any) => { + return moment(row.created_at).format('YYYY/MM/DD - HH:mm:ss') + }, + }, + ] + const handleCreate = async (values: DataProjectReview) => { try { const res = await post(projectReviewAdd, { @@ -1054,71 +1083,104 @@ const StaffEvaluation = () => {
) : ( - - 0} - withTooltip - data={ - dataSummaryTracking.value.length > 0 - ? [ - { - name: 'On time morning', - value: dataSummaryTracking?.on_time_morning ?? 0, - color: 'lime', - }, - { - name: 'Late morning', - value: dataSummaryTracking?.late_morning ?? 0, - color: 'red', - }, - { - name: 'On time afternoon', - value: dataSummaryTracking?.on_time_afternoon ?? 0, - color: 'teal', - }, - { - name: 'Late afternoon', - value: dataSummaryTracking?.late_afternoon ?? 0, - color: 'orange', - }, - ] - : [ - { - name: 'No data', - value: 1, - color: 'gray.6', - }, - ] - } - /> - - - -
-
- On time morning -
-
- -
-
- Late morning -
-
- -
-
- On time afternoon -
-
- -
-
Late afternoon
-
-
+ + + Overview + Detail + + + + + + 0} + withTooltip + data={ + dataSummaryTracking.value.length > 0 + ? [ + { + name: 'On time morning', + value: + dataSummaryTracking?.on_time_morning ?? 0, + color: 'lime', + }, + { + name: 'Late morning', + value: dataSummaryTracking?.late_morning ?? 0, + color: 'red', + }, + { + name: 'On time afternoon', + value: + dataSummaryTracking?.on_time_afternoon ?? 0, + color: 'teal', + }, + { + name: 'Late afternoon', + value: + dataSummaryTracking?.late_afternoon ?? 0, + color: 'orange', + }, + ] + : [ + { + name: 'No data', + value: 1, + color: 'gray.6', + }, + ] + } + /> + + + +
+
+ On time morning +
+
+ +
+
+ Late morning +
+
+ +
+
+ On time afternoon +
+
+ +
+
+ Late afternoon +
+
+
+
+
+ + + + + +
)} @@ -1150,6 +1212,7 @@ const StaffEvaluation = () => { data={dataPJParticipating} columns={columnsPJParticipating} size="" + height={300} /> )} diff --git a/FRONTEND/src/pages/UsersManagement/UsersManagement.tsx b/FRONTEND/src/pages/UsersManagement/UsersManagement.tsx index afe0fee..ba35dc5 100644 --- a/FRONTEND/src/pages/UsersManagement/UsersManagement.tsx +++ b/FRONTEND/src/pages/UsersManagement/UsersManagement.tsx @@ -14,7 +14,7 @@ import { Modal, MultiSelect, Text, - TextInput + TextInput, } from '@mantine/core' import { useForm } from '@mantine/form' import { IconEdit, IconX } from '@tabler/icons-react'