update custom add worklog
This commit is contained in:
		
							parent
							
								
									e7e81dead7
								
							
						
					
					
						commit
						0ea97cb0c5
					
				| 
						 | 
					@ -86,7 +86,7 @@ class TimekeepingController extends Controller
 | 
				
			||||||
                ]
 | 
					                ]
 | 
				
			||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        $this->createOrUpdateRecordForCurrentMonth($month, $year);
 | 
				
			||||||
        return response()->json(['status' => true, 'message' => 'Add successfully']);
 | 
					        return response()->json(['status' => true, 'message' => 'Add successfully']);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,29 @@
 | 
				
			||||||
import { getTheTimesheet, updateMultipleUserWorkingTime, updateWorkingDays } from '@/api/Admin'
 | 
					import {
 | 
				
			||||||
 | 
					  getTheTimesheet,
 | 
				
			||||||
 | 
					  updateMultipleUserWorkingTime,
 | 
				
			||||||
 | 
					  updateWorkingDays,
 | 
				
			||||||
 | 
					} from '@/api/Admin'
 | 
				
			||||||
import { update } from '@/rtk/helpers/CRUD'
 | 
					import { update } from '@/rtk/helpers/CRUD'
 | 
				
			||||||
import { get } from '@/rtk/helpers/apiService'
 | 
					import { get } from '@/rtk/helpers/apiService'
 | 
				
			||||||
import { Box, Button, Image, Menu, Select, Table, Text, TextInput, Tooltip } from '@mantine/core'
 | 
					import {
 | 
				
			||||||
 | 
					  Box,
 | 
				
			||||||
 | 
					  Button,
 | 
				
			||||||
 | 
					  Drawer,
 | 
				
			||||||
 | 
					  Image,
 | 
				
			||||||
 | 
					  Menu,
 | 
				
			||||||
 | 
					  MultiSelect,
 | 
				
			||||||
 | 
					  Select,
 | 
				
			||||||
 | 
					  Table,
 | 
				
			||||||
 | 
					  Text,
 | 
				
			||||||
 | 
					  TextInput,
 | 
				
			||||||
 | 
					  Tooltip
 | 
				
			||||||
 | 
					} from '@mantine/core'
 | 
				
			||||||
 | 
					import { useDisclosure } from '@mantine/hooks'
 | 
				
			||||||
import { notifications } from '@mantine/notifications'
 | 
					import { notifications } from '@mantine/notifications'
 | 
				
			||||||
import { IconCheck, IconExclamationMark, IconX } from '@tabler/icons-react'
 | 
					import { IconCheck, IconExclamationMark, IconX } from '@tabler/icons-react'
 | 
				
			||||||
 | 
					import moment from 'moment'
 | 
				
			||||||
import { useEffect, useState } from 'react'
 | 
					import { useEffect, useState } from 'react'
 | 
				
			||||||
import classes from './Timekeeping.module.css'
 | 
					import classes from './Timekeeping.module.css'
 | 
				
			||||||
import moment from 'moment'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface User {
 | 
					interface User {
 | 
				
			||||||
  id: number
 | 
					  id: number
 | 
				
			||||||
| 
						 | 
					@ -42,9 +59,15 @@ interface UserData {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Timekeeping = () => {
 | 
					const Timekeeping = () => {
 | 
				
			||||||
 | 
					  const [opened, { open, close }] = useDisclosure(false)
 | 
				
			||||||
  const [daysInMonth, setDaysInMonth] = useState(
 | 
					  const [daysInMonth, setDaysInMonth] = useState(
 | 
				
			||||||
    Array.from({ length: 31 }, (_, index) => index + 1),
 | 
					    Array.from({ length: 31 }, (_, index) => index + 1),
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					  const [customAddData, setCustomAddData] = useState<{data:string[], type: string, day: number}>({
 | 
				
			||||||
 | 
					    data: [],
 | 
				
			||||||
 | 
					    type: '',
 | 
				
			||||||
 | 
					    day: 0
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
  const [workingDays, setWorkingDays] = useState(30)
 | 
					  const [workingDays, setWorkingDays] = useState(30)
 | 
				
			||||||
  const [data, setData] = useState<UserData[]>([])
 | 
					  const [data, setData] = useState<UserData[]>([])
 | 
				
			||||||
  const [date, setDate] = useState({
 | 
					  const [date, setDate] = useState({
 | 
				
			||||||
| 
						 | 
					@ -60,9 +83,7 @@ const Timekeeping = () => {
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      if (res.status) {
 | 
					      if (res.status) {
 | 
				
			||||||
        setData(
 | 
					        setData(
 | 
				
			||||||
          res.data.filter((u: UserData) =>
 | 
					          res.data.filter((u: UserData) => u.user.permission.includes('staff')),
 | 
				
			||||||
            u.user.permission.includes('staff'),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        setDaysInMonth(
 | 
					        setDaysInMonth(
 | 
				
			||||||
          Array.from({ length: getDaysInMonth() }, (_, index) => index + 1),
 | 
					          Array.from({ length: getDaysInMonth() }, (_, index) => index + 1),
 | 
				
			||||||
| 
						 | 
					@ -102,27 +123,39 @@ const Timekeeping = () => {
 | 
				
			||||||
    return days.getDate()
 | 
					    return days.getDate()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const updateMultipleUser = async(users:number[], day:number, type:string)=>{
 | 
					  const updateMultipleUser = async (
 | 
				
			||||||
 | 
					    users: number[],
 | 
				
			||||||
 | 
					    day: number,
 | 
				
			||||||
 | 
					    type: string,
 | 
				
			||||||
 | 
					  ) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      await update(updateMultipleUserWorkingTime, {
 | 
					      await update(
 | 
				
			||||||
        users: users, 
 | 
					        updateMultipleUserWorkingTime,
 | 
				
			||||||
        year: date.year, 
 | 
					        {
 | 
				
			||||||
        month: date.month, 
 | 
					          users: users,
 | 
				
			||||||
        day:day, 
 | 
					          year: date.year,
 | 
				
			||||||
        type: type
 | 
					          month: date.month,
 | 
				
			||||||
      }, getTimeSheet)
 | 
					          day: day,
 | 
				
			||||||
 | 
					          type: type,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        getTimeSheet,
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      console.log(error)
 | 
					      console.log(error)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 const handleUpdateWorkingDays = async()=>{
 | 
					  const handleUpdateWorkingDays = async () => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      await update(updateWorkingDays, {
 | 
					      await update(
 | 
				
			||||||
        working_days: workingDays, 
 | 
					        updateWorkingDays,
 | 
				
			||||||
        year: date.year, 
 | 
					        {
 | 
				
			||||||
        month: date.month
 | 
					          working_days: workingDays,
 | 
				
			||||||
      }, getTimeSheet)
 | 
					          year: date.year,
 | 
				
			||||||
 | 
					          month: date.month,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        getTimeSheet,
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      console.log(error)
 | 
					      console.log(error)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -132,6 +165,7 @@ const Timekeeping = () => {
 | 
				
			||||||
    getTimeSheet()
 | 
					    getTimeSheet()
 | 
				
			||||||
  }, [date])
 | 
					  }, [date])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  console.log(customAddData)
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
      <div className={classes.title}>
 | 
					      <div className={classes.title}>
 | 
				
			||||||
| 
						 | 
					@ -140,24 +174,58 @@ const Timekeeping = () => {
 | 
				
			||||||
          Timekeeping
 | 
					          Timekeeping
 | 
				
			||||||
        </h3>
 | 
					        </h3>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					      <Drawer
 | 
				
			||||||
 | 
					        opened={opened}
 | 
				
			||||||
 | 
					        onClose={close}
 | 
				
			||||||
 | 
					        position="right"
 | 
				
			||||||
 | 
					        title={<strong>Add custom worklog</strong>}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <MultiSelect
 | 
				
			||||||
 | 
					          mb={'md'}
 | 
				
			||||||
 | 
					          searchable
 | 
				
			||||||
 | 
					          label="User(s)"
 | 
				
			||||||
 | 
					          data={data.map((user) => {
 | 
				
			||||||
 | 
					            return { value: user.user.id.toString(), label: user.user.name }
 | 
				
			||||||
 | 
					          })}
 | 
				
			||||||
 | 
					          onChange={(e)=>{setCustomAddData({...customAddData, data: e})}}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					        <Select
 | 
				
			||||||
 | 
					          mb={'md'}
 | 
				
			||||||
 | 
					          label="Type"
 | 
				
			||||||
 | 
					          data={[
 | 
				
			||||||
 | 
					            { value: 'half', label: 'Half day' },
 | 
				
			||||||
 | 
					            { value: 'one', label: 'A day' },
 | 
				
			||||||
 | 
					          ]}
 | 
				
			||||||
 | 
					          onChange={(e)=>{setCustomAddData({...customAddData, type: e!})}}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					        <Button onClick={()=>{
 | 
				
			||||||
 | 
					          if(customAddData.type === "" || customAddData.data.length === 0 || customAddData.day === 0){
 | 
				
			||||||
 | 
					            notifications.show({
 | 
				
			||||||
 | 
					              title: 'Error',
 | 
				
			||||||
 | 
					              message: "Input data required",
 | 
				
			||||||
 | 
					              color: 'red',
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					          }else{
 | 
				
			||||||
 | 
					            updateMultipleUser(customAddData.data.map((u)=>parseInt(u)), customAddData.day, customAddData.type)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }}>Submit</Button>
 | 
				
			||||||
 | 
					      </Drawer>
 | 
				
			||||||
      <Box display={'flex'}>
 | 
					      <Box display={'flex'}>
 | 
				
			||||||
        <Box style={{display:"flex", flexFlow:"column"}} w={'30%'}>
 | 
					        <Box style={{ display: 'flex', flexFlow: 'column' }} w={'30%'}>
 | 
				
			||||||
          <Box w="100%" display={'flex'}>
 | 
					          <Box w="100%" display={'flex'}>
 | 
				
			||||||
            <Select
 | 
					            <Select
 | 
				
			||||||
              w="50%"
 | 
					              w="50%"
 | 
				
			||||||
              value={date.month}
 | 
					              value={date.month}
 | 
				
			||||||
              size="xs"
 | 
					              size="xs"
 | 
				
			||||||
              label="Month"
 | 
					              label="Month"
 | 
				
			||||||
              data={Array.from({ length: 12 }, (_, index) =>
 | 
					              data={Array.from({ length: 12 }, (_, index) => {
 | 
				
			||||||
                {
 | 
					                return {
 | 
				
			||||||
                  return {
 | 
					                  value: (1 + index).toString(),
 | 
				
			||||||
                    value: (1 + index).toString(), 
 | 
					                  label: (1 + index).toString(),
 | 
				
			||||||
                    label:(1 + index).toString(),
 | 
					                  disabled:
 | 
				
			||||||
                    disabled: (1 + index) > parseInt(moment(Date.now()).format('MM'))
 | 
					                    1 + index > parseInt(moment(Date.now()).format('MM')),
 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                
 | 
					              })}
 | 
				
			||||||
              )}
 | 
					 | 
				
			||||||
              onChange={(e) => {
 | 
					              onChange={(e) => {
 | 
				
			||||||
                setDate({ ...date, month: e! })
 | 
					                setDate({ ...date, month: e! })
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
| 
						 | 
					@ -168,29 +236,60 @@ const Timekeeping = () => {
 | 
				
			||||||
              size="xs"
 | 
					              size="xs"
 | 
				
			||||||
              ml={'sm'}
 | 
					              ml={'sm'}
 | 
				
			||||||
              label="Year"
 | 
					              label="Year"
 | 
				
			||||||
              data={Array.from({ length: 10 }, (_, index) =>
 | 
					              data={Array.from({ length: 10 }, (_, index) => {
 | 
				
			||||||
                {
 | 
					                return {
 | 
				
			||||||
                  return {
 | 
					                  value: (
 | 
				
			||||||
                    value: (parseInt(moment(Date.now()).format('YYYY')) - 3 + index).toString(), 
 | 
					                    parseInt(moment(Date.now()).format('YYYY')) -
 | 
				
			||||||
                    label:(parseInt(moment(Date.now()).format('YYYY')) - 3 + index).toString(),
 | 
					                    3 +
 | 
				
			||||||
                    disabled: (parseInt(moment(Date.now()).format('YYYY')) - 3 + index) > parseInt(moment(Date.now()).format('YYYY'))
 | 
					                    index
 | 
				
			||||||
                  }
 | 
					                  ).toString(),
 | 
				
			||||||
 | 
					                  label: (
 | 
				
			||||||
 | 
					                    parseInt(moment(Date.now()).format('YYYY')) -
 | 
				
			||||||
 | 
					                    3 +
 | 
				
			||||||
 | 
					                    index
 | 
				
			||||||
 | 
					                  ).toString(),
 | 
				
			||||||
 | 
					                  disabled:
 | 
				
			||||||
 | 
					                    parseInt(moment(Date.now()).format('YYYY')) - 3 + index >
 | 
				
			||||||
 | 
					                    parseInt(moment(Date.now()).format('YYYY')),
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              )}
 | 
					              })}
 | 
				
			||||||
              onChange={(e) => {
 | 
					              onChange={(e) => {
 | 
				
			||||||
                setDate({ ...date, year: e! })
 | 
					                setDate({ ...date, year: e! })
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            ></Select>
 | 
					            ></Select>
 | 
				
			||||||
          </Box>
 | 
					          </Box>
 | 
				
			||||||
            <Box display={'flex'} style={{alignItems:'end'}}>
 | 
					          <Box display={'flex'} style={{ alignItems: 'end' }}>
 | 
				
			||||||
              <TextInput type='number' size='xs' label="Working days" w={"20%"} value={workingDays} onChange={(e)=>{
 | 
					            <TextInput
 | 
				
			||||||
 | 
					              type="number"
 | 
				
			||||||
 | 
					              size="xs"
 | 
				
			||||||
 | 
					              label="Working days"
 | 
				
			||||||
 | 
					              w={'20%'}
 | 
				
			||||||
 | 
					              value={workingDays}
 | 
				
			||||||
 | 
					              onChange={(e) => {
 | 
				
			||||||
                setWorkingDays(parseFloat(e.target.value))
 | 
					                setWorkingDays(parseFloat(e.target.value))
 | 
				
			||||||
              }}/>
 | 
					              }}
 | 
				
			||||||
              <Tooltip label="Save working days"><Button size='xs' ml={'sm'} onClick={()=>handleUpdateWorkingDays()}>Save</Button></Tooltip>
 | 
					            />
 | 
				
			||||||
            </Box>
 | 
					            <Tooltip label="Save working days">
 | 
				
			||||||
 | 
					              <Button
 | 
				
			||||||
 | 
					                size="xs"
 | 
				
			||||||
 | 
					                ml={'sm'}
 | 
				
			||||||
 | 
					                onClick={() => handleUpdateWorkingDays()}
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                Save
 | 
				
			||||||
 | 
					              </Button>
 | 
				
			||||||
 | 
					            </Tooltip>
 | 
				
			||||||
 | 
					          </Box>
 | 
				
			||||||
        </Box>
 | 
					        </Box>
 | 
				
			||||||
        <Box w="70%" pl={200} style={{display:'flex', alignItems:'end', justifyContent:"space-evenly"}}>
 | 
					        <Box
 | 
				
			||||||
        <Box style={{display:'flex', alignItems:'center'}}>
 | 
					          w="70%"
 | 
				
			||||||
 | 
					          pl={200}
 | 
				
			||||||
 | 
					          style={{
 | 
				
			||||||
 | 
					            display: 'flex',
 | 
				
			||||||
 | 
					            alignItems: 'end',
 | 
				
			||||||
 | 
					            justifyContent: 'space-evenly',
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <Box style={{ display: 'flex', alignItems: 'center' }}>
 | 
				
			||||||
            <IconCheck
 | 
					            <IconCheck
 | 
				
			||||||
              size={20}
 | 
					              size={20}
 | 
				
			||||||
              style={{
 | 
					              style={{
 | 
				
			||||||
| 
						 | 
					@ -201,9 +300,11 @@ const Timekeeping = () => {
 | 
				
			||||||
                fontWeight: 700,
 | 
					                fontWeight: 700,
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <Text ml={'sm'} fz='14px'>Work over 7 hours</Text>
 | 
					            <Text ml={'sm'} fz="14px">
 | 
				
			||||||
 | 
					              Work over 7 hours
 | 
				
			||||||
 | 
					            </Text>
 | 
				
			||||||
          </Box>
 | 
					          </Box>
 | 
				
			||||||
          <Box style={{display:'flex', alignItems:'center'}}>
 | 
					          <Box style={{ display: 'flex', alignItems: 'center' }}>
 | 
				
			||||||
            <IconCheck
 | 
					            <IconCheck
 | 
				
			||||||
              size={20}
 | 
					              size={20}
 | 
				
			||||||
              style={{
 | 
					              style={{
 | 
				
			||||||
| 
						 | 
					@ -214,9 +315,11 @@ const Timekeeping = () => {
 | 
				
			||||||
                fontWeight: 700,
 | 
					                fontWeight: 700,
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <Text ml={'sm'} fz='14px'>Work over 3.5 hours</Text>
 | 
					            <Text ml={'sm'} fz="14px">
 | 
				
			||||||
 | 
					              Work over 3.5 hours
 | 
				
			||||||
 | 
					            </Text>
 | 
				
			||||||
          </Box>
 | 
					          </Box>
 | 
				
			||||||
          <Box style={{display:'flex', alignItems:'center'}}>
 | 
					          <Box style={{ display: 'flex', alignItems: 'center' }}>
 | 
				
			||||||
            <IconExclamationMark
 | 
					            <IconExclamationMark
 | 
				
			||||||
              size={20}
 | 
					              size={20}
 | 
				
			||||||
              style={{
 | 
					              style={{
 | 
				
			||||||
| 
						 | 
					@ -227,9 +330,11 @@ const Timekeeping = () => {
 | 
				
			||||||
                fontWeight: 700,
 | 
					                fontWeight: 700,
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <Text ml={'sm'} fz='14px'>Checked in</Text>
 | 
					            <Text ml={'sm'} fz="14px">
 | 
				
			||||||
 | 
					              Checked in
 | 
				
			||||||
 | 
					            </Text>
 | 
				
			||||||
          </Box>
 | 
					          </Box>
 | 
				
			||||||
          <Box style={{display:'flex', alignItems:'center'}}>
 | 
					          <Box style={{ display: 'flex', alignItems: 'center' }}>
 | 
				
			||||||
            <IconX
 | 
					            <IconX
 | 
				
			||||||
              size={20}
 | 
					              size={20}
 | 
				
			||||||
              style={{
 | 
					              style={{
 | 
				
			||||||
| 
						 | 
					@ -240,7 +345,9 @@ const Timekeeping = () => {
 | 
				
			||||||
                fontWeight: 700,
 | 
					                fontWeight: 700,
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <Text ml={'sm'} fz='14px'>Off</Text>
 | 
					            <Text ml={'sm'} fz="14px">
 | 
				
			||||||
 | 
					              Off
 | 
				
			||||||
 | 
					            </Text>
 | 
				
			||||||
          </Box>
 | 
					          </Box>
 | 
				
			||||||
        </Box>
 | 
					        </Box>
 | 
				
			||||||
      </Box>
 | 
					      </Box>
 | 
				
			||||||
| 
						 | 
					@ -260,23 +367,49 @@ const Timekeeping = () => {
 | 
				
			||||||
              {daysInMonth.map((d) => {
 | 
					              {daysInMonth.map((d) => {
 | 
				
			||||||
                return (
 | 
					                return (
 | 
				
			||||||
                  <Menu width={200} shadow="md">
 | 
					                  <Menu width={200} shadow="md">
 | 
				
			||||||
                      <Menu.Target>
 | 
					                    <Menu.Target>
 | 
				
			||||||
                      <Table.Th key={d} ta={'center'} style={{cursor:"pointer"}}>
 | 
					                      <Table.Th
 | 
				
			||||||
 | 
					                        key={d}
 | 
				
			||||||
 | 
					                        ta={'center'}
 | 
				
			||||||
 | 
					                        style={{ cursor: 'pointer' }}
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
                        <span>{d}</span>
 | 
					                        <span>{d}</span>
 | 
				
			||||||
                        </Table.Th>
 | 
					                      </Table.Th>
 | 
				
			||||||
                      </Menu.Target>
 | 
					                    </Menu.Target>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                      <Menu.Dropdown>
 | 
					                    <Menu.Dropdown>
 | 
				
			||||||
                        <Menu.Item onClick={()=>updateMultipleUser(data.map((u)=>u.user.id), d, 'half')}>
 | 
					                      <Menu.Item
 | 
				
			||||||
                          + Add half a day's work
 | 
					                        onClick={() =>
 | 
				
			||||||
                        </Menu.Item>
 | 
					                          updateMultipleUser(
 | 
				
			||||||
                        <Menu.Item
 | 
					                            data.map((u) => u.user.id),
 | 
				
			||||||
                          onClick={()=>updateMultipleUser(data.map((u)=>u.user.id), d, 'one')}
 | 
					                            d,
 | 
				
			||||||
                        >
 | 
					                            'half',
 | 
				
			||||||
                          + Add 1 day of work
 | 
					                          )
 | 
				
			||||||
                        </Menu.Item>
 | 
					                        }
 | 
				
			||||||
                      </Menu.Dropdown>
 | 
					                      >
 | 
				
			||||||
                      </Menu>
 | 
					                        + Add half a day's work
 | 
				
			||||||
 | 
					                      </Menu.Item>
 | 
				
			||||||
 | 
					                      <Menu.Item
 | 
				
			||||||
 | 
					                        onClick={() =>
 | 
				
			||||||
 | 
					                          updateMultipleUser(
 | 
				
			||||||
 | 
					                            data.map((u) => u.user.id),
 | 
				
			||||||
 | 
					                            d,
 | 
				
			||||||
 | 
					                            'one',
 | 
				
			||||||
 | 
					                          )
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        + Add 1 day of work
 | 
				
			||||||
 | 
					                      </Menu.Item>
 | 
				
			||||||
 | 
					                      <Menu.Item>
 | 
				
			||||||
 | 
					                        <Text size="sm" onClick={()=>{
 | 
				
			||||||
 | 
					                          open()
 | 
				
			||||||
 | 
					                          setCustomAddData({...customAddData, day: d})
 | 
				
			||||||
 | 
					                        }}>
 | 
				
			||||||
 | 
					                          + Add custom worklog
 | 
				
			||||||
 | 
					                        </Text>
 | 
				
			||||||
 | 
					                      </Menu.Item>
 | 
				
			||||||
 | 
					                    </Menu.Dropdown>
 | 
				
			||||||
 | 
					                  </Menu>
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
              })}
 | 
					              })}
 | 
				
			||||||
            </Table.Tr>
 | 
					            </Table.Tr>
 | 
				
			||||||
| 
						 | 
					@ -286,7 +419,16 @@ const Timekeeping = () => {
 | 
				
			||||||
              <Table.Th ta={'center'}>Off</Table.Th>
 | 
					              <Table.Th ta={'center'}>Off</Table.Th>
 | 
				
			||||||
              {daysInMonth.map((d) => {
 | 
					              {daysInMonth.map((d) => {
 | 
				
			||||||
                return (
 | 
					                return (
 | 
				
			||||||
                  <Table.Th key={d} ta={'center'} bg={(getDayName(`${date.year}-${date.month}-${d}`)=== "Su" || getDayName(`${date.year}-${date.month}-${d}`) === "Sa") ? 'rgb(251 255 196 / 78%)' : ''}>
 | 
					                  <Table.Th
 | 
				
			||||||
 | 
					                    key={d}
 | 
				
			||||||
 | 
					                    ta={'center'}
 | 
				
			||||||
 | 
					                    bg={
 | 
				
			||||||
 | 
					                      getDayName(`${date.year}-${date.month}-${d}`) === 'Su' ||
 | 
				
			||||||
 | 
					                      getDayName(`${date.year}-${date.month}-${d}`) === 'Sa'
 | 
				
			||||||
 | 
					                        ? 'rgb(251 255 196 / 78%)'
 | 
				
			||||||
 | 
					                        : ''
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
                    {getDayName(`${date.year}-${date.month}-${d}`)}
 | 
					                    {getDayName(`${date.year}-${date.month}-${d}`)}
 | 
				
			||||||
                  </Table.Th>
 | 
					                  </Table.Th>
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
| 
						 | 
					@ -295,19 +437,35 @@ const Timekeeping = () => {
 | 
				
			||||||
          </Table.Thead>
 | 
					          </Table.Thead>
 | 
				
			||||||
          <Table.Tbody>
 | 
					          <Table.Tbody>
 | 
				
			||||||
            {data.map((user) => {
 | 
					            {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)
 | 
					              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 (
 | 
					              return (
 | 
				
			||||||
                <Table.Tr key={user.user.id} className={classes.tableTr}>
 | 
					                <Table.Tr key={user.user.id} className={classes.tableTr}>
 | 
				
			||||||
                  <Table.Td>{user.user.name}</Table.Td>
 | 
					                  <Table.Td>{user.user.name}</Table.Td>
 | 
				
			||||||
                  <Table.Td ta={'center'}>{totalDays}</Table.Td>
 | 
					                  <Table.Td ta={'center'}>{totalDays}</Table.Td>
 | 
				
			||||||
                  <Table.Td ta={'center'}>{workingDays-totalDays}</Table.Td>
 | 
					                  <Table.Td ta={'center'}>{workingDays - totalDays}</Table.Td>
 | 
				
			||||||
                  {daysInMonth.map((d) => {
 | 
					                  {daysInMonth.map((d) => {
 | 
				
			||||||
                    var total =
 | 
					                    var total =
 | 
				
			||||||
                      user.history.find((h) => h.day === d)?.total ?? 0
 | 
					                      user.history.find((h) => h.day === d)?.total ?? 0
 | 
				
			||||||
                    return (
 | 
					                    return (
 | 
				
			||||||
                      <Table.Td key={d} ta={'center'} bg={(getDayName(`${date.year}-${date.month}-${d}`)=== "Su" || getDayName(`${date.year}-${date.month}-${d}`) === "Sa") ? 'rgb(251 255 196 / 78%)' : ''}>
 | 
					                      <Table.Td
 | 
				
			||||||
                        {total / 60 / 60 < 7 && user.history.find((h) => h.day === d) ?
 | 
					                        key={d}
 | 
				
			||||||
                          total / 60 / 60 >= 3.5 ?  
 | 
					                        ta={'center'}
 | 
				
			||||||
 | 
					                        bg={
 | 
				
			||||||
 | 
					                          getDayName(`${date.year}-${date.month}-${d}`) ===
 | 
				
			||||||
 | 
					                            'Su' ||
 | 
				
			||||||
 | 
					                          getDayName(`${date.year}-${date.month}-${d}`) === 'Sa'
 | 
				
			||||||
 | 
					                            ? 'rgb(251 255 196 / 78%)'
 | 
				
			||||||
 | 
					                            : ''
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        {total / 60 / 60 < 7 &&
 | 
				
			||||||
 | 
					                        user.history.find((h) => h.day === d) ? (
 | 
				
			||||||
 | 
					                          total / 60 / 60 >= 3.5 ? (
 | 
				
			||||||
                            <Tooltip
 | 
					                            <Tooltip
 | 
				
			||||||
                              multiline
 | 
					                              multiline
 | 
				
			||||||
                              label={
 | 
					                              label={
 | 
				
			||||||
| 
						 | 
					@ -325,7 +483,9 @@ const Timekeeping = () => {
 | 
				
			||||||
                                          }}
 | 
					                                          }}
 | 
				
			||||||
                                          key={v.id}
 | 
					                                          key={v.id}
 | 
				
			||||||
                                        >
 | 
					                                        >
 | 
				
			||||||
                                          <p>{v.status + ': ' + v.time_string}</p>{' '}
 | 
					                                          <p>
 | 
				
			||||||
 | 
					                                            {v.status + ': ' + v.time_string}
 | 
				
			||||||
 | 
					                                          </p>{' '}
 | 
				
			||||||
                                          {v.image && (
 | 
					                                          {v.image && (
 | 
				
			||||||
                                            <Image
 | 
					                                            <Image
 | 
				
			||||||
                                              w={100}
 | 
					                                              w={100}
 | 
				
			||||||
| 
						 | 
					@ -335,13 +495,13 @@ const Timekeeping = () => {
 | 
				
			||||||
                                                  'local',
 | 
					                                                  'local',
 | 
				
			||||||
                                                )
 | 
					                                                )
 | 
				
			||||||
                                                  ? import.meta.env
 | 
					                                                  ? import.meta.env
 | 
				
			||||||
                                                    .VITE_BACKEND_URL +
 | 
					                                                      .VITE_BACKEND_URL +
 | 
				
			||||||
                                                  'storage/' +
 | 
					                                                    'storage/' +
 | 
				
			||||||
                                                  v.image
 | 
					                                                    v.image
 | 
				
			||||||
                                                  : import.meta.env
 | 
					                                                  : import.meta.env
 | 
				
			||||||
                                                    .VITE_BACKEND_URL +
 | 
					                                                      .VITE_BACKEND_URL +
 | 
				
			||||||
                                                  'image/storage/' +
 | 
					                                                    'image/storage/' +
 | 
				
			||||||
                                                  v.image
 | 
					                                                    v.image
 | 
				
			||||||
                                              }
 | 
					                                              }
 | 
				
			||||||
                                            />
 | 
					                                            />
 | 
				
			||||||
                                          )}
 | 
					                                          )}
 | 
				
			||||||
| 
						 | 
					@ -362,7 +522,8 @@ const Timekeeping = () => {
 | 
				
			||||||
                                }}
 | 
					                                }}
 | 
				
			||||||
                              />
 | 
					                              />
 | 
				
			||||||
                            </Tooltip>
 | 
					                            </Tooltip>
 | 
				
			||||||
                            : <Tooltip
 | 
					                          ) : (
 | 
				
			||||||
 | 
					                            <Tooltip
 | 
				
			||||||
                              multiline
 | 
					                              multiline
 | 
				
			||||||
                              label={
 | 
					                              label={
 | 
				
			||||||
                                <div>
 | 
					                                <div>
 | 
				
			||||||
| 
						 | 
					@ -379,7 +540,9 @@ const Timekeeping = () => {
 | 
				
			||||||
                                          }}
 | 
					                                          }}
 | 
				
			||||||
                                          key={v.id}
 | 
					                                          key={v.id}
 | 
				
			||||||
                                        >
 | 
					                                        >
 | 
				
			||||||
                                          <p>{v.status + ': ' + v.time_string}</p>{' '}
 | 
					                                          <p>
 | 
				
			||||||
 | 
					                                            {v.status + ': ' + v.time_string}
 | 
				
			||||||
 | 
					                                          </p>{' '}
 | 
				
			||||||
                                          {v.image && (
 | 
					                                          {v.image && (
 | 
				
			||||||
                                            <Image
 | 
					                                            <Image
 | 
				
			||||||
                                              w={100}
 | 
					                                              w={100}
 | 
				
			||||||
| 
						 | 
					@ -389,13 +552,13 @@ const Timekeeping = () => {
 | 
				
			||||||
                                                  'local',
 | 
					                                                  'local',
 | 
				
			||||||
                                                )
 | 
					                                                )
 | 
				
			||||||
                                                  ? import.meta.env
 | 
					                                                  ? import.meta.env
 | 
				
			||||||
                                                    .VITE_BACKEND_URL +
 | 
					                                                      .VITE_BACKEND_URL +
 | 
				
			||||||
                                                  'storage/' +
 | 
					                                                    'storage/' +
 | 
				
			||||||
                                                  v.image
 | 
					                                                    v.image
 | 
				
			||||||
                                                  : import.meta.env
 | 
					                                                  : import.meta.env
 | 
				
			||||||
                                                    .VITE_BACKEND_URL +
 | 
					                                                      .VITE_BACKEND_URL +
 | 
				
			||||||
                                                  'image/storage/' +
 | 
					                                                    'image/storage/' +
 | 
				
			||||||
                                                  v.image
 | 
					                                                    v.image
 | 
				
			||||||
                                              }
 | 
					                                              }
 | 
				
			||||||
                                            />
 | 
					                                            />
 | 
				
			||||||
                                          )}
 | 
					                                          )}
 | 
				
			||||||
| 
						 | 
					@ -416,72 +579,72 @@ const Timekeeping = () => {
 | 
				
			||||||
                                }}
 | 
					                                }}
 | 
				
			||||||
                              />
 | 
					                              />
 | 
				
			||||||
                            </Tooltip>
 | 
					                            </Tooltip>
 | 
				
			||||||
                          : total >= 7 ? (
 | 
					                          )
 | 
				
			||||||
                            <Tooltip
 | 
					                        ) : total >= 7 ? (
 | 
				
			||||||
                              multiline
 | 
					                          <Tooltip
 | 
				
			||||||
                              label={
 | 
					                            multiline
 | 
				
			||||||
                                <div>
 | 
					                            label={
 | 
				
			||||||
                                  {`Total: ${(total / 60 / 60).toFixed(1)}h`}
 | 
					                              <div>
 | 
				
			||||||
                                  {user.history
 | 
					                                {`Total: ${(total / 60 / 60).toFixed(1)}h`}
 | 
				
			||||||
                                    .find((h) => h.day === d)
 | 
					                                {user.history
 | 
				
			||||||
                                    ?.values.map((v) => {
 | 
					                                  .find((h) => h.day === d)
 | 
				
			||||||
                                      return (
 | 
					                                  ?.values.map((v) => {
 | 
				
			||||||
                                        <Box
 | 
					                                    return (
 | 
				
			||||||
                                          style={{
 | 
					                                      <Box
 | 
				
			||||||
                                            display: 'flex',
 | 
					                                        style={{
 | 
				
			||||||
                                            alignItems: 'center',
 | 
					                                          display: 'flex',
 | 
				
			||||||
                                            justifyContent: 'space-between',
 | 
					                                          alignItems: 'center',
 | 
				
			||||||
                                          }}
 | 
					                                          justifyContent: 'space-between',
 | 
				
			||||||
                                          key={v.id}
 | 
					                                        }}
 | 
				
			||||||
                                        >
 | 
					                                        key={v.id}
 | 
				
			||||||
                                          <p>{v.status + ': ' + v.time_string}</p>{' '}
 | 
					                                      >
 | 
				
			||||||
                                          {v.image && (
 | 
					                                        <p>{v.status + ': ' + v.time_string}</p>{' '}
 | 
				
			||||||
                                            <Image
 | 
					                                        {v.image && (
 | 
				
			||||||
                                              w={100}
 | 
					                                          <Image
 | 
				
			||||||
                                              h={100}
 | 
					                                            w={100}
 | 
				
			||||||
                                              src={
 | 
					                                            h={100}
 | 
				
			||||||
                                                import.meta.env.VITE_BACKEND_URL.includes(
 | 
					                                            src={
 | 
				
			||||||
                                                  'local',
 | 
					                                              import.meta.env.VITE_BACKEND_URL.includes(
 | 
				
			||||||
                                                )
 | 
					                                                'local',
 | 
				
			||||||
                                                  ? import.meta.env
 | 
					                                              )
 | 
				
			||||||
 | 
					                                                ? import.meta.env
 | 
				
			||||||
                                                    .VITE_BACKEND_URL +
 | 
					                                                    .VITE_BACKEND_URL +
 | 
				
			||||||
                                                  'storage/' +
 | 
					                                                  'storage/' +
 | 
				
			||||||
                                                  v.image
 | 
					                                                  v.image
 | 
				
			||||||
                                                  : import.meta.env
 | 
					                                                : import.meta.env
 | 
				
			||||||
                                                    .VITE_BACKEND_URL +
 | 
					                                                    .VITE_BACKEND_URL +
 | 
				
			||||||
                                                  'image/storage/' +
 | 
					                                                  'image/storage/' +
 | 
				
			||||||
                                                  v.image
 | 
					                                                  v.image
 | 
				
			||||||
                                              }
 | 
					                                            }
 | 
				
			||||||
                                            />
 | 
					                                          />
 | 
				
			||||||
                                          )}
 | 
					                                        )}
 | 
				
			||||||
                                        </Box>
 | 
					                                      </Box>
 | 
				
			||||||
                                      )
 | 
					                                    )
 | 
				
			||||||
                                    })}
 | 
					                                  })}
 | 
				
			||||||
                                </div>
 | 
					                              </div>
 | 
				
			||||||
                              }
 | 
					                            }
 | 
				
			||||||
                            >
 | 
					                          >
 | 
				
			||||||
                              <IconCheck
 | 
					                            <IconCheck
 | 
				
			||||||
                                size={20}
 | 
					 | 
				
			||||||
                                style={{
 | 
					 | 
				
			||||||
                                  backgroundColor: 'green',
 | 
					 | 
				
			||||||
                                  color: 'white',
 | 
					 | 
				
			||||||
                                  borderRadius: '5px',
 | 
					 | 
				
			||||||
                                  padding: '2px',
 | 
					 | 
				
			||||||
                                }}
 | 
					 | 
				
			||||||
                              />
 | 
					 | 
				
			||||||
                            </Tooltip>
 | 
					 | 
				
			||||||
                          ) : (
 | 
					 | 
				
			||||||
                            
 | 
					 | 
				
			||||||
                            <IconX
 | 
					 | 
				
			||||||
                              size={20}
 | 
					                              size={20}
 | 
				
			||||||
                              style={{
 | 
					                              style={{
 | 
				
			||||||
                                backgroundColor: '#ff4646',
 | 
					                                backgroundColor: 'green',
 | 
				
			||||||
                                color: 'white',
 | 
					                                color: 'white',
 | 
				
			||||||
                                borderRadius: '5px',
 | 
					                                borderRadius: '5px',
 | 
				
			||||||
                                padding: '2px',
 | 
					                                padding: '2px',
 | 
				
			||||||
                              }}
 | 
					                              }}
 | 
				
			||||||
                            />
 | 
					                            />
 | 
				
			||||||
                          )}
 | 
					                          </Tooltip>
 | 
				
			||||||
 | 
					                        ) : (
 | 
				
			||||||
 | 
					                          <IconX
 | 
				
			||||||
 | 
					                            size={20}
 | 
				
			||||||
 | 
					                            style={{
 | 
				
			||||||
 | 
					                              backgroundColor: '#ff4646',
 | 
				
			||||||
 | 
					                              color: 'white',
 | 
				
			||||||
 | 
					                              borderRadius: '5px',
 | 
				
			||||||
 | 
					                              padding: '2px',
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                          />
 | 
				
			||||||
 | 
					                        )}
 | 
				
			||||||
                      </Table.Td>
 | 
					                      </Table.Td>
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                  })}
 | 
					                  })}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue