From 2b60501980a8262aa1367370dd7985f96a37183c Mon Sep 17 00:00:00 2001 From: Joseph Le Date: Wed, 12 Jun 2024 16:21:42 +0700 Subject: [PATCH 1/2] update timekeeping --- .../src/pages/Timekeeping/Timekeeping.tsx | 85 ++++++++++++------- 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/FRONTEND/src/pages/Timekeeping/Timekeeping.tsx b/FRONTEND/src/pages/Timekeeping/Timekeeping.tsx index da00545..1670c77 100644 --- a/FRONTEND/src/pages/Timekeeping/Timekeeping.tsx +++ b/FRONTEND/src/pages/Timekeeping/Timekeeping.tsx @@ -1,6 +1,6 @@ import { getTheTimesheet } from '@/api/Admin' import { get } from '@/rtk/helpers/apiService' -import { Box, Image, Select, Table, Text, Tooltip } from '@mantine/core' +import { Box, Image, Select, Table, Text, TextInput, Tooltip } from '@mantine/core' import { IconCheck, IconExclamationMark, IconX } from '@tabler/icons-react' import { useEffect, useState } from 'react' import classes from './Timekeeping.module.css' @@ -44,6 +44,7 @@ const Timekeeping = () => { const [daysInMonth, setDaysInMonth] = useState( Array.from({ length: 31 }, (_, index) => index + 1), ) + const [workingDays, setWorkingDays] = useState(30) const [data, setData] = useState([]) const [date, setDate] = useState({ month: (new Date().getMonth() + 1).toString(), @@ -65,6 +66,8 @@ const Timekeeping = () => { setDaysInMonth( Array.from({ length: getDaysInMonth() }, (_, index) => index + 1), ) + + localStorage.getItem('workingdays') ? setWorkingDays(parseFloat(localStorage.getItem('workingdays')!)) : setWorkingDays(getDaysInMonth()) } } catch (error: any) { console.log(error) @@ -111,34 +114,42 @@ const Timekeeping = () => { - - - + + + + + + + { + setWorkingDays(parseFloat(e.target.value)) + localStorage.setItem('workingdays', e.target.value) + }}/> + - + { Day + + {daysInMonth.map((d) => { return ( @@ -214,9 +227,11 @@ const Timekeeping = () => { + Total + Off {daysInMonth.map((d) => { return ( - + {getDayName(`${date.year}-${date.month}-${d}`)} ) @@ -225,16 +240,19 @@ const Timekeeping = () => { {data.map((user) => { + let totalDays = user.history.filter((h) => h.total / 60 / 60 >= 7).length + (user.history.filter((h) => h.total / 60 / 60 < 7 && h.total / 60 / 60 >= 3.5).length / 2) return ( {user.user.name} + {totalDays} + {workingDays-totalDays} {daysInMonth.map((d) => { var total = user.history.find((h) => h.day === d)?.total ?? 0 return ( - + {total / 60 / 60 < 7 && user.history.find((h) => h.day === d) ? - total / 60 / 60 >= 3.5 ? + total / 60 / 60 >= 3.5 ? { alignItems: 'center', justifyContent: 'space-between', }} + key={v.id} >

{v.status + ': ' + v.time_string}

{' '} {v.image && ( @@ -291,7 +310,7 @@ const Timekeeping = () => { : +
{`Total: ${(total / 60 / 60).toFixed(1)}h`} {user.history .find((h) => h.day === d) @@ -303,6 +322,7 @@ const Timekeeping = () => { alignItems: 'center', justifyContent: 'space-between', }} + key={v.id} >

{v.status + ': ' + v.time_string}

{' '} {v.image && ( @@ -357,6 +377,7 @@ const Timekeeping = () => { alignItems: 'center', justifyContent: 'space-between', }} + key={v.id} >

{v.status + ': ' + v.time_string}

{' '} {v.image && ( From 0151d29450194277c1561fe88056dcc8a2ce9866 Mon Sep 17 00:00:00 2001 From: Joseph Le Date: Wed, 12 Jun 2024 21:37:38 +0700 Subject: [PATCH 2/2] update add multiple record --- .../Controllers/TimekeepingController.php | 41 +++++++++++++++-- BACKEND/Modules/Admin/routes/api.php | 1 + FRONTEND/src/api/Admin.ts | 3 +- .../src/pages/Timekeeping/Timekeeping.tsx | 44 ++++++++++++++++--- 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/TimekeepingController.php b/BACKEND/Modules/Admin/app/Http/Controllers/TimekeepingController.php index 3c667f0..9137bc1 100644 --- a/BACKEND/Modules/Admin/app/Http/Controllers/TimekeepingController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/TimekeepingController.php @@ -43,10 +43,12 @@ class TimekeepingController extends Controller $date = Carbon::create($now->year, $now->month, $i)->setTimezone(env('TIME_ZONE'))->format('Y-m-d'); // Kiểm tra xem có mục nào trong $history có created_at trùng với $date $hasEntry = $history->filter(function ($entry) use ($date, $admin) { + // echo($hasEntry); return Carbon::parse($entry->created_at)->setTimezone(env('TIME_ZONE'))->format('Y-m-d') === $date && $entry->user_id == $admin->id; - }); - - if (count($hasEntry) > 0) { + }); + // echo($hasEntry); + + if (count($hasEntry) > 0) { $values = array_values($hasEntry->toArray()); $last_checkin = null; $total = 0; @@ -71,4 +73,37 @@ class TimekeepingController extends Controller } return response()->json(['status'=> true, 'data'=>$result]); } + + public function addWorkingTimeForMultipleUser(Request $request) + { + $user_ids = $request->users; + $year = $request->year; + $month = $request->month; + $day = $request->day; + $type = $request->type; + foreach($user_ids as $id){ + $user = Admin::find($id); + $date = Carbon::create($year, $month, $day)->setTimezone(env('TIME_ZONE')); + $start = $date->copy()->setTime(7, 31, 11); + $end = $type == 'half' ? $date->copy()->setTime(11, 31, 11) : $date->copy()->setTime(17, 1, 11); + Tracking::insert([ + [ + 'name' => $user->name, + 'user_id' => $user->id, + 'status' => 'check in', + 'time_string' => $start ->format('Y-m-d H:i:s'), + 'created_at' => $start->setTimezone('UTC') + ], + [ + 'name' => $user->name, + 'user_id' => $user->id, + 'status' => 'check out', + 'time_string' => $end->format('Y-m-d H:i:s'), + 'created_at' => $end->setTimezone('UTC') + ] + ]); + } + + return response()->json(['status'=> true, 'message'=> 'Add successfully']); + } } diff --git a/BACKEND/Modules/Admin/routes/api.php b/BACKEND/Modules/Admin/routes/api.php index b5ac71d..1133977 100755 --- a/BACKEND/Modules/Admin/routes/api.php +++ b/BACKEND/Modules/Admin/routes/api.php @@ -107,6 +107,7 @@ Route::middleware('api') 'prefix' => 'timekeeping', ], function () { Route::get('/', [TimekeepingController::class, 'get'])->middleware('check.permission:admin.hr.staff'); + Route::post('/addMutilple', [TimekeepingController::class, 'addWorkingTimeForMultipleUser'])->middleware('check.permission:admin.hr'); }); Route::group([ diff --git a/FRONTEND/src/api/Admin.ts b/FRONTEND/src/api/Admin.ts index eda18e0..feaaa77 100755 --- a/FRONTEND/src/api/Admin.ts +++ b/FRONTEND/src/api/Admin.ts @@ -65,4 +65,5 @@ export const getAllIssuesByProject = API_URL + 'v1/admin/jira/all-issue-by-proje export const getAllUserWorklogs = API_URL + 'v1/admin/jira/worklogs' //Timekeeping -export const getTheTimesheet = API_URL + 'v1/admin/timekeeping' \ No newline at end of file +export const getTheTimesheet = API_URL + 'v1/admin/timekeeping' +export const updateMultipleUserWorkingTime = API_URL + 'v1/admin/timekeeping/addMutilple' \ No newline at end of file diff --git a/FRONTEND/src/pages/Timekeeping/Timekeeping.tsx b/FRONTEND/src/pages/Timekeeping/Timekeeping.tsx index 1670c77..c6662cc 100644 --- a/FRONTEND/src/pages/Timekeeping/Timekeeping.tsx +++ b/FRONTEND/src/pages/Timekeeping/Timekeeping.tsx @@ -1,11 +1,12 @@ -import { getTheTimesheet } from '@/api/Admin' +import { getTheTimesheet, updateMultipleUserWorkingTime } from '@/api/Admin' import { get } from '@/rtk/helpers/apiService' -import { Box, Image, Select, Table, Text, TextInput, Tooltip } from '@mantine/core' +import { Box, Image, Menu, Select, Table, Text, TextInput, Tooltip } from '@mantine/core' import { IconCheck, IconExclamationMark, IconX } from '@tabler/icons-react' import { useEffect, useState } from 'react' import classes from './Timekeeping.module.css' import { notifications } from '@mantine/notifications' import moment from 'moment' +import { update } from '@/rtk/helpers/CRUD' interface User { id: number @@ -60,7 +61,7 @@ const Timekeeping = () => { if (res.status) { setData( res.data.filter((u: UserData) => - !u.user.email.includes('admin'), + u.user.permission.includes('staff'), ), ) setDaysInMonth( @@ -101,6 +102,20 @@ const Timekeeping = () => { return days.getDate() } + const updateMultipleUser = async(users:number[], day:number, type:string)=>{ + try { + await update(updateMultipleUserWorkingTime, { + users: users, + year: date.year, + month: date.month, + day:day, + type: type + }, getTimeSheet) + } catch (error) { + console.log(error) + } + } + useEffect(() => { getTimeSheet() }, [date]) @@ -149,7 +164,7 @@ const Timekeeping = () => { }}/> - + { {daysInMonth.map((d) => { return ( - - {d} - + + + + {d} + + + + + updateMultipleUser(data.map((u)=>u.user.id), d, 'half')}> + + Add half a day's work + + updateMultipleUser(data.map((u)=>u.user.id), d, 'one')} + > + + Add 1 day of work + + + ) })}