Update view detail  Working review #109
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -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
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<any[]>(data)
 | 
			
		||||
  // const [tempData, setTempData] = useState<any[]>([])
 | 
			
		||||
| 
						 | 
				
			
			@ -206,6 +211,9 @@ export const DataTableAll = ({
 | 
			
		|||
            ? 'var(--mantine-color-blue-light)'
 | 
			
		||||
            : undefined
 | 
			
		||||
        }
 | 
			
		||||
        style={{
 | 
			
		||||
          backgroundColor: element[keyHighlight] ? '#ff70704d' : 'transparent',
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <Table.Td display={checkBox ? 'block' : 'none'}>
 | 
			
		||||
          <Checkbox
 | 
			
		||||
| 
						 | 
				
			
			@ -369,43 +377,45 @@ export const DataTableAll = ({
 | 
			
		|||
        </Box>
 | 
			
		||||
        {componentRight}
 | 
			
		||||
      </Box>
 | 
			
		||||
      <Box className={classes.box}>
 | 
			
		||||
        <Table
 | 
			
		||||
          stickyHeader
 | 
			
		||||
          stickyHeaderOffset={-1}
 | 
			
		||||
          striped
 | 
			
		||||
          highlightOnHover
 | 
			
		||||
          withTableBorder
 | 
			
		||||
          withColumnBorders
 | 
			
		||||
        >
 | 
			
		||||
          <Table.Thead className={classes.headers}>
 | 
			
		||||
            <Table.Tr>
 | 
			
		||||
              <Table.Th display={checkBox ? 'block' : 'none'}>
 | 
			
		||||
                <Checkbox
 | 
			
		||||
                  aria-label="Select row"
 | 
			
		||||
                  checked={
 | 
			
		||||
                    checkSubArray(Tdata, selectedRows) &&
 | 
			
		||||
                    Tdata.length === selectedRows.length
 | 
			
		||||
                  }
 | 
			
		||||
                  onChange={(event) =>
 | 
			
		||||
                    setSelectedRows(
 | 
			
		||||
                      event.currentTarget.checked
 | 
			
		||||
                        ? (pre) => [...pre, ...Tdata]
 | 
			
		||||
                        : selectedRows.filter(
 | 
			
		||||
                            (item) =>
 | 
			
		||||
                              !Tdata.some((removeItem) =>
 | 
			
		||||
                                areObjectsEqual(item, removeItem),
 | 
			
		||||
                              ),
 | 
			
		||||
                          ),
 | 
			
		||||
                    )
 | 
			
		||||
                  }
 | 
			
		||||
                />
 | 
			
		||||
              </Table.Th>
 | 
			
		||||
              {headers}
 | 
			
		||||
            </Table.Tr>
 | 
			
		||||
          </Table.Thead>
 | 
			
		||||
          <Table.Tbody>{rows}</Table.Tbody>
 | 
			
		||||
        </Table>
 | 
			
		||||
      <Box className={classes.box} style={{ height: height + 50 }}>
 | 
			
		||||
        <ScrollArea h={height}>
 | 
			
		||||
          <Table
 | 
			
		||||
            stickyHeader
 | 
			
		||||
            stickyHeaderOffset={-1}
 | 
			
		||||
            striped
 | 
			
		||||
            highlightOnHover
 | 
			
		||||
            withTableBorder
 | 
			
		||||
            withColumnBorders
 | 
			
		||||
          >
 | 
			
		||||
            <Table.Thead className={classes.headers}>
 | 
			
		||||
              <Table.Tr>
 | 
			
		||||
                <Table.Th display={checkBox ? 'block' : 'none'}>
 | 
			
		||||
                  <Checkbox
 | 
			
		||||
                    aria-label="Select row"
 | 
			
		||||
                    checked={
 | 
			
		||||
                      checkSubArray(Tdata, selectedRows) &&
 | 
			
		||||
                      Tdata.length === selectedRows.length
 | 
			
		||||
                    }
 | 
			
		||||
                    onChange={(event) =>
 | 
			
		||||
                      setSelectedRows(
 | 
			
		||||
                        event.currentTarget.checked
 | 
			
		||||
                          ? (pre) => [...pre, ...Tdata]
 | 
			
		||||
                          : selectedRows.filter(
 | 
			
		||||
                              (item) =>
 | 
			
		||||
                                !Tdata.some((removeItem) =>
 | 
			
		||||
                                  areObjectsEqual(item, removeItem),
 | 
			
		||||
                                ),
 | 
			
		||||
                            ),
 | 
			
		||||
                      )
 | 
			
		||||
                    }
 | 
			
		||||
                  />
 | 
			
		||||
                </Table.Th>
 | 
			
		||||
                {headers}
 | 
			
		||||
              </Table.Tr>
 | 
			
		||||
            </Table.Thead>
 | 
			
		||||
            <Table.Tbody>{rows}</Table.Tbody>
 | 
			
		||||
          </Table>
 | 
			
		||||
        </ScrollArea>
 | 
			
		||||
      </Box>
 | 
			
		||||
    </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) => {
 | 
			
		||||
    try {
 | 
			
		||||
      const res = await post(projectReviewAdd, {
 | 
			
		||||
| 
						 | 
				
			
			@ -1054,71 +1083,104 @@ const StaffEvaluation = () => {
 | 
			
		|||
            </Box>
 | 
			
		||||
          ) : (
 | 
			
		||||
            <Box>
 | 
			
		||||
              <Box className={classes.chartContainer} display="flex">
 | 
			
		||||
                <PieChart
 | 
			
		||||
                  withLabelsLine
 | 
			
		||||
                  labelsPosition="outside"
 | 
			
		||||
                  labelsType="value"
 | 
			
		||||
                  withLabels={dataSummaryTracking.value.length > 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',
 | 
			
		||||
                          },
 | 
			
		||||
                        ]
 | 
			
		||||
                  }
 | 
			
		||||
                />
 | 
			
		||||
              </Box>
 | 
			
		||||
              <Box className={classes.boxContainer} display="flex">
 | 
			
		||||
                <Box className={classes.boxContainer} display="flex">
 | 
			
		||||
                  <div className={classes.boxColorLime}></div>
 | 
			
		||||
                  <div style={{ paddingLeft: '10px', paddingRight: '20px' }}>
 | 
			
		||||
                    On time morning
 | 
			
		||||
                  </div>
 | 
			
		||||
                </Box>
 | 
			
		||||
                <Box className={classes.boxContainer} display="flex">
 | 
			
		||||
                  <div className={classes.boxColorRed}></div>
 | 
			
		||||
                  <div 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>
 | 
			
		||||
              <Tabs defaultValue="overview" orientation="vertical">
 | 
			
		||||
                <Tabs.List justify="center">
 | 
			
		||||
                  <Tabs.Tab value="overview">Overview</Tabs.Tab>
 | 
			
		||||
                  <Tabs.Tab value="detail">Detail</Tabs.Tab>
 | 
			
		||||
                </Tabs.List>
 | 
			
		||||
 | 
			
		||||
                <Tabs.Panel value="overview">
 | 
			
		||||
                  <Box style={{ height: 350, marginTop: 8 }}>
 | 
			
		||||
                    <Box className={classes.chartContainer} display="flex">
 | 
			
		||||
                      <PieChart
 | 
			
		||||
                        withLabelsLine
 | 
			
		||||
                        labelsPosition="outside"
 | 
			
		||||
                        labelsType="value"
 | 
			
		||||
                        withLabels={dataSummaryTracking.value.length > 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',
 | 
			
		||||
                                },
 | 
			
		||||
                              ]
 | 
			
		||||
                        }
 | 
			
		||||
                      />
 | 
			
		||||
                    </Box>
 | 
			
		||||
                    <Box className={classes.boxContainer} display="flex">
 | 
			
		||||
                      <Box className={classes.boxContainer} display="flex">
 | 
			
		||||
                        <div className={classes.boxColorLime}></div>
 | 
			
		||||
                        <div
 | 
			
		||||
                          style={{ paddingLeft: '10px', paddingRight: '20px' }}
 | 
			
		||||
                        >
 | 
			
		||||
                          On time morning
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </Box>
 | 
			
		||||
                      <Box className={classes.boxContainer} display="flex">
 | 
			
		||||
                        <div className={classes.boxColorRed}></div>
 | 
			
		||||
                        <div
 | 
			
		||||
                          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 className={classes.pjParticipatingContainer}>
 | 
			
		||||
| 
						 | 
				
			
			@ -1150,6 +1212,7 @@ const StaffEvaluation = () => {
 | 
			
		|||
                data={dataPJParticipating}
 | 
			
		||||
                columns={columnsPJParticipating}
 | 
			
		||||
                size=""
 | 
			
		||||
                height={300}
 | 
			
		||||
              />
 | 
			
		||||
            )}
 | 
			
		||||
          </Box>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue