Update view detail Working review
This commit is contained in:
parent
5cfd78d2c0
commit
f5e4d7b405
|
|
@ -289,33 +289,32 @@ class TrackingController extends Controller
|
||||||
$lateMorning = 0;
|
$lateMorning = 0;
|
||||||
$onTimeAfternoon = 0;
|
$onTimeAfternoon = 0;
|
||||||
$lateAfternoon = 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();
|
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) {
|
$morningCheck = $records->filter(function ($record) {
|
||||||
return Carbon::parse($record->time_string)->hour < 12;
|
return Carbon::parse($record->time_string)->hour < 12;
|
||||||
})->sortBy('time_string')->first();
|
})->sortBy('time_string')->first();
|
||||||
|
|
||||||
$afternoonCheck = $records->filter(function ($record) {
|
$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();
|
})->sortBy('time_string')->first();
|
||||||
|
|
||||||
$morningTime = Carbon::parse($date)->setTime(7, 40, 0);
|
$morningTime = Carbon::parse($date)->setTime(7, 40, 0);
|
||||||
$afternoonTime = Carbon::parse($date)->setTime(13, 10, 0);
|
$afternoonTime = Carbon::parse($date)->setTime(13, 10, 0);
|
||||||
$checkOutAfternoonTime = Carbon::parse($date)->setTime(15, 00, 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) {
|
if ($morningCheck) {
|
||||||
$checkInTime = Carbon::parse($morningCheck->time_string);
|
$checkInTime = Carbon::parse($morningCheck->time_string);
|
||||||
if ($checkInTime->lessThanOrEqualTo($morningTime)) {
|
if ($checkInTime->lessThanOrEqualTo($morningTime)) {
|
||||||
$onTimeMorning++;
|
$onTimeMorning++;
|
||||||
} else {
|
} else {
|
||||||
|
array_push($listLate, $morningCheck->id);
|
||||||
$lateMorning++;
|
$lateMorning++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -325,22 +324,40 @@ class TrackingController extends Controller
|
||||||
if ($checkInTime->lessThanOrEqualTo($afternoonTime)) {
|
if ($checkInTime->lessThanOrEqualTo($afternoonTime)) {
|
||||||
$onTimeAfternoon++;
|
$onTimeAfternoon++;
|
||||||
} else {
|
} else {
|
||||||
|
array_push($listLate, $afternoonCheck->id);
|
||||||
$lateAfternoon++;
|
$lateAfternoon++;
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
// check if not check-in afternoon but has check out
|
||||||
if ($checkOutAfternoon && $checkOutAfternoonTime->lessThanOrEqualTo(Carbon::parse($checkOutAfternoon->time_string))) {
|
if ($checkOutAfternoon) {
|
||||||
$onTimeAfternoon++;
|
$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([
|
return AbstractController::ResultSuccess([
|
||||||
'on_time_morning' => $onTimeMorning,
|
'on_time_morning' => $onTimeMorning,
|
||||||
'late_morning' => $lateMorning,
|
'late_morning' => $lateMorning,
|
||||||
'on_time_afternoon' => $onTimeAfternoon,
|
'on_time_afternoon' => $onTimeAfternoon,
|
||||||
'late_afternoon' => $lateAfternoon,
|
'late_afternoon' => $lateAfternoon,
|
||||||
'value' => $valueTracking
|
'value' => $returnTracking
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
MultiSelect,
|
MultiSelect,
|
||||||
Pagination,
|
Pagination,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
|
ScrollArea,
|
||||||
Select,
|
Select,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Table,
|
Table,
|
||||||
|
|
@ -85,6 +86,8 @@ export const DataTableAll = ({
|
||||||
size,
|
size,
|
||||||
infoTotal,
|
infoTotal,
|
||||||
componentRight,
|
componentRight,
|
||||||
|
height = 600,
|
||||||
|
keyHighlight = '',
|
||||||
}: {
|
}: {
|
||||||
data: any[]
|
data: any[]
|
||||||
columns: Column[]
|
columns: Column[]
|
||||||
|
|
@ -94,6 +97,8 @@ export const DataTableAll = ({
|
||||||
size: string
|
size: string
|
||||||
infoTotal?: React.ReactNode // Set the type to ReactNode to allow JSX elements
|
infoTotal?: React.ReactNode // Set the type to ReactNode to allow JSX elements
|
||||||
componentRight?: React.ReactNode
|
componentRight?: React.ReactNode
|
||||||
|
height?: number
|
||||||
|
keyHighlight?: string
|
||||||
}) => {
|
}) => {
|
||||||
const [Tdata, setTData] = useState<any[]>(data)
|
const [Tdata, setTData] = useState<any[]>(data)
|
||||||
// const [tempData, setTempData] = useState<any[]>([])
|
// const [tempData, setTempData] = useState<any[]>([])
|
||||||
|
|
@ -206,6 +211,9 @@ export const DataTableAll = ({
|
||||||
? 'var(--mantine-color-blue-light)'
|
? 'var(--mantine-color-blue-light)'
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
style={{
|
||||||
|
backgroundColor: element[keyHighlight] ? '#ff70704d' : 'transparent',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Table.Td display={checkBox ? 'block' : 'none'}>
|
<Table.Td display={checkBox ? 'block' : 'none'}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
|
@ -369,43 +377,45 @@ export const DataTableAll = ({
|
||||||
</Box>
|
</Box>
|
||||||
{componentRight}
|
{componentRight}
|
||||||
</Box>
|
</Box>
|
||||||
<Box className={classes.box}>
|
<Box className={classes.box} style={{ height: height + 50 }}>
|
||||||
<Table
|
<ScrollArea h={height}>
|
||||||
stickyHeader
|
<Table
|
||||||
stickyHeaderOffset={-1}
|
stickyHeader
|
||||||
striped
|
stickyHeaderOffset={-1}
|
||||||
highlightOnHover
|
striped
|
||||||
withTableBorder
|
highlightOnHover
|
||||||
withColumnBorders
|
withTableBorder
|
||||||
>
|
withColumnBorders
|
||||||
<Table.Thead className={classes.headers}>
|
>
|
||||||
<Table.Tr>
|
<Table.Thead className={classes.headers}>
|
||||||
<Table.Th display={checkBox ? 'block' : 'none'}>
|
<Table.Tr>
|
||||||
<Checkbox
|
<Table.Th display={checkBox ? 'block' : 'none'}>
|
||||||
aria-label="Select row"
|
<Checkbox
|
||||||
checked={
|
aria-label="Select row"
|
||||||
checkSubArray(Tdata, selectedRows) &&
|
checked={
|
||||||
Tdata.length === selectedRows.length
|
checkSubArray(Tdata, selectedRows) &&
|
||||||
}
|
Tdata.length === selectedRows.length
|
||||||
onChange={(event) =>
|
}
|
||||||
setSelectedRows(
|
onChange={(event) =>
|
||||||
event.currentTarget.checked
|
setSelectedRows(
|
||||||
? (pre) => [...pre, ...Tdata]
|
event.currentTarget.checked
|
||||||
: selectedRows.filter(
|
? (pre) => [...pre, ...Tdata]
|
||||||
(item) =>
|
: selectedRows.filter(
|
||||||
!Tdata.some((removeItem) =>
|
(item) =>
|
||||||
areObjectsEqual(item, removeItem),
|
!Tdata.some((removeItem) =>
|
||||||
),
|
areObjectsEqual(item, removeItem),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
}
|
)
|
||||||
/>
|
}
|
||||||
</Table.Th>
|
/>
|
||||||
{headers}
|
</Table.Th>
|
||||||
</Table.Tr>
|
{headers}
|
||||||
</Table.Thead>
|
</Table.Tr>
|
||||||
<Table.Tbody>{rows}</Table.Tbody>
|
</Table.Thead>
|
||||||
</Table>
|
<Table.Tbody>{rows}</Table.Tbody>
|
||||||
|
</Table>
|
||||||
|
</ScrollArea>
|
||||||
</Box>
|
</Box>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
const handleCreate = async (values: DataProjectReview) => {
|
||||||
try {
|
try {
|
||||||
const res = await post(projectReviewAdd, {
|
const res = await post(projectReviewAdd, {
|
||||||
|
|
@ -1054,71 +1083,104 @@ const StaffEvaluation = () => {
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Box>
|
<Box>
|
||||||
<Box className={classes.chartContainer} display="flex">
|
<Tabs defaultValue="overview" orientation="vertical">
|
||||||
<PieChart
|
<Tabs.List justify="center">
|
||||||
withLabelsLine
|
<Tabs.Tab value="overview">Overview</Tabs.Tab>
|
||||||
labelsPosition="outside"
|
<Tabs.Tab value="detail">Detail</Tabs.Tab>
|
||||||
labelsType="value"
|
</Tabs.List>
|
||||||
withLabels={dataSummaryTracking.value.length > 0}
|
|
||||||
withTooltip
|
<Tabs.Panel value="overview">
|
||||||
data={
|
<Box style={{ height: 350, marginTop: 8 }}>
|
||||||
dataSummaryTracking.value.length > 0
|
<Box className={classes.chartContainer} display="flex">
|
||||||
? [
|
<PieChart
|
||||||
{
|
withLabelsLine
|
||||||
name: 'On time morning',
|
labelsPosition="outside"
|
||||||
value: dataSummaryTracking?.on_time_morning ?? 0,
|
labelsType="value"
|
||||||
color: 'lime',
|
withLabels={dataSummaryTracking.value.length > 0}
|
||||||
},
|
withTooltip
|
||||||
{
|
data={
|
||||||
name: 'Late morning',
|
dataSummaryTracking.value.length > 0
|
||||||
value: dataSummaryTracking?.late_morning ?? 0,
|
? [
|
||||||
color: 'red',
|
{
|
||||||
},
|
name: 'On time morning',
|
||||||
{
|
value:
|
||||||
name: 'On time afternoon',
|
dataSummaryTracking?.on_time_morning ?? 0,
|
||||||
value: dataSummaryTracking?.on_time_afternoon ?? 0,
|
color: 'lime',
|
||||||
color: 'teal',
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'Late morning',
|
||||||
name: 'Late afternoon',
|
value: dataSummaryTracking?.late_morning ?? 0,
|
||||||
value: dataSummaryTracking?.late_afternoon ?? 0,
|
color: 'red',
|
||||||
color: 'orange',
|
},
|
||||||
},
|
{
|
||||||
]
|
name: 'On time afternoon',
|
||||||
: [
|
value:
|
||||||
{
|
dataSummaryTracking?.on_time_afternoon ?? 0,
|
||||||
name: 'No data',
|
color: 'teal',
|
||||||
value: 1,
|
},
|
||||||
color: 'gray.6',
|
{
|
||||||
},
|
name: 'Late afternoon',
|
||||||
]
|
value:
|
||||||
}
|
dataSummaryTracking?.late_afternoon ?? 0,
|
||||||
/>
|
color: 'orange',
|
||||||
</Box>
|
},
|
||||||
<Box className={classes.boxContainer} display="flex">
|
]
|
||||||
<Box className={classes.boxContainer} display="flex">
|
: [
|
||||||
<div className={classes.boxColorLime}></div>
|
{
|
||||||
<div style={{ paddingLeft: '10px', paddingRight: '20px' }}>
|
name: 'No data',
|
||||||
On time morning
|
value: 1,
|
||||||
</div>
|
color: 'gray.6',
|
||||||
</Box>
|
},
|
||||||
<Box className={classes.boxContainer} display="flex">
|
]
|
||||||
<div className={classes.boxColorRed}></div>
|
}
|
||||||
<div style={{ paddingLeft: '10px', paddingRight: '20px' }}>
|
/>
|
||||||
Late morning
|
</Box>
|
||||||
</div>
|
<Box className={classes.boxContainer} display="flex">
|
||||||
</Box>
|
<Box className={classes.boxContainer} display="flex">
|
||||||
<Box className={classes.boxContainer} display="flex">
|
<div className={classes.boxColorLime}></div>
|
||||||
<div className={classes.boxColorTeal}></div>
|
<div
|
||||||
<div style={{ paddingLeft: '10px', paddingRight: '20px' }}>
|
style={{ paddingLeft: '10px', paddingRight: '20px' }}
|
||||||
On time afternoon
|
>
|
||||||
</div>
|
On time morning
|
||||||
</Box>
|
</div>
|
||||||
<Box className={classes.boxContainer} display="flex">
|
</Box>
|
||||||
<div className={classes.boxColorOrange}></div>
|
<Box className={classes.boxContainer} display="flex">
|
||||||
<div style={{ paddingLeft: '10px' }}>Late afternoon</div>
|
<div className={classes.boxColorRed}></div>
|
||||||
</Box>
|
<div
|
||||||
</Box>
|
style={{ paddingLeft: '10px', paddingRight: '20px' }}
|
||||||
|
>
|
||||||
|
Late morning
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
<Box className={classes.boxContainer} display="flex">
|
||||||
|
<div className={classes.boxColorTeal}></div>
|
||||||
|
<div
|
||||||
|
style={{ paddingLeft: '10px', paddingRight: '20px' }}
|
||||||
|
>
|
||||||
|
On time afternoon
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
<Box className={classes.boxContainer} display="flex">
|
||||||
|
<div className={classes.boxColorOrange}></div>
|
||||||
|
<div style={{ paddingLeft: '10px' }}>
|
||||||
|
Late afternoon
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Tabs.Panel>
|
||||||
|
<Tabs.Panel value="detail">
|
||||||
|
<Box style={{ marginTop: 8 }}>
|
||||||
|
<DataTableAll
|
||||||
|
data={dataSummaryTracking.value}
|
||||||
|
columns={columnsDetailWorking}
|
||||||
|
size=""
|
||||||
|
height={300}
|
||||||
|
keyHighlight={'isLate'}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Tabs.Panel>
|
||||||
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<Box className={classes.pjParticipatingContainer}>
|
<Box className={classes.pjParticipatingContainer}>
|
||||||
|
|
@ -1150,6 +1212,7 @@ const StaffEvaluation = () => {
|
||||||
data={dataPJParticipating}
|
data={dataPJParticipating}
|
||||||
columns={columnsPJParticipating}
|
columns={columnsPJParticipating}
|
||||||
size=""
|
size=""
|
||||||
|
height={300}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import {
|
||||||
Modal,
|
Modal,
|
||||||
MultiSelect,
|
MultiSelect,
|
||||||
Text,
|
Text,
|
||||||
TextInput
|
TextInput,
|
||||||
} from '@mantine/core'
|
} from '@mantine/core'
|
||||||
import { useForm } from '@mantine/form'
|
import { useForm } from '@mantine/form'
|
||||||
import { IconEdit, IconX } from '@tabler/icons-react'
|
import { IconEdit, IconX } from '@tabler/icons-react'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue