master #93
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -21,6 +21,43 @@ import { useForm } from '@mantine/form'
 | 
			
		|||
import { Xdelete } from '@/rtk/helpers/CRUD'
 | 
			
		||||
import moment from 'moment'
 | 
			
		||||
 | 
			
		||||
function OrganizationSettings() {
 | 
			
		||||
  const [activeTab, setActiveTab] = useState<string | null>('technical')
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      <div className={classes.title}>
 | 
			
		||||
        <h3>
 | 
			
		||||
          <Text>Admin/</Text>
 | 
			
		||||
          Organization Settings
 | 
			
		||||
        </h3>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <Box w="100%" display={'flex'} mt={15} ml={10}>
 | 
			
		||||
        <Tabs w="100%" value={activeTab} onChange={setActiveTab}>
 | 
			
		||||
          <Tabs.List>
 | 
			
		||||
            <Tabs.Tab value="technical">Technical Setting</Tabs.Tab>
 | 
			
		||||
            <Tabs.Tab value="second">Setting 2</Tabs.Tab>
 | 
			
		||||
            <Tabs.Tab value="third">Setting 3</Tabs.Tab>
 | 
			
		||||
          </Tabs.List>
 | 
			
		||||
 | 
			
		||||
          <Tabs.Panel value="technical" pt="xs">
 | 
			
		||||
            <TechnicalSettingTab />
 | 
			
		||||
          </Tabs.Panel>
 | 
			
		||||
 | 
			
		||||
          <Tabs.Panel value="second" pt="xs">
 | 
			
		||||
            Setting 2
 | 
			
		||||
          </Tabs.Panel>
 | 
			
		||||
 | 
			
		||||
          <Tabs.Panel value="third" pt="xs">
 | 
			
		||||
            Setting 3
 | 
			
		||||
          </Tabs.Panel>
 | 
			
		||||
        </Tabs>
 | 
			
		||||
      </Box>
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface DataTechnical {
 | 
			
		||||
  id: number
 | 
			
		||||
  name: string
 | 
			
		||||
| 
						 | 
				
			
			@ -29,15 +66,13 @@ interface DataTechnical {
 | 
			
		|||
  updated_at: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function OrganizationSettings() {
 | 
			
		||||
  const [activeTab, setActiveTab] = useState<string | null>('technical')
 | 
			
		||||
const TechnicalSettingTab = () => {
 | 
			
		||||
  const [dataTechnical, setDataTechnical] = useState<DataTechnical[]>([])
 | 
			
		||||
  const [isLoading, setIsLoading] = useState(false)
 | 
			
		||||
  const [addTechnicalOpen, setAddTechnicalOpen] = useState(false)
 | 
			
		||||
  const [deleteTechnicalOpen, setDeleteTechnicalOpen] = useState(false)
 | 
			
		||||
  const [selectedId, setSelectedId] = useState(0)
 | 
			
		||||
 | 
			
		||||
  const [dataTechnical, setDataTechnical] = useState<DataTechnical[]>([])
 | 
			
		||||
 | 
			
		||||
  const form = useForm({
 | 
			
		||||
    initialValues: {
 | 
			
		||||
      name: '',
 | 
			
		||||
| 
						 | 
				
			
			@ -169,77 +204,48 @@ function OrganizationSettings() {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      <div className={classes.title}>
 | 
			
		||||
        <h3>
 | 
			
		||||
          <Text>Admin/</Text>
 | 
			
		||||
          Staff Evaluation
 | 
			
		||||
        </h3>
 | 
			
		||||
      </div>
 | 
			
		||||
    <>
 | 
			
		||||
      <Box mt={'md'} p={16}>
 | 
			
		||||
        <Text fw={500}>Note: </Text>
 | 
			
		||||
 | 
			
		||||
      <Box w="100%" display={'flex'} mt={15} ml={10}>
 | 
			
		||||
        <Tabs w="100%" value={activeTab} onChange={setActiveTab}>
 | 
			
		||||
          <Tabs.List>
 | 
			
		||||
            <Tabs.Tab value="technical">Technical setting</Tabs.Tab>
 | 
			
		||||
            <Tabs.Tab value="second">Setting 2</Tabs.Tab>
 | 
			
		||||
            <Tabs.Tab value="third">Setting 3</Tabs.Tab>
 | 
			
		||||
          </Tabs.List>
 | 
			
		||||
        <Flex gap={8}>
 | 
			
		||||
          <Box p={8} bg="#d9d2e9">
 | 
			
		||||
            <span style={{ fontWeight: 500 }}>Level 1:</span> 3-12 Month
 | 
			
		||||
          </Box>
 | 
			
		||||
          <Box p={8} bg="#ffd966">
 | 
			
		||||
            <span style={{ fontWeight: 500 }}>Level 2:</span> 3-5 Year
 | 
			
		||||
          </Box>
 | 
			
		||||
          <Box p={8} bg="#cfe2f3">
 | 
			
		||||
            <span style={{ fontWeight: 500 }}>Level 3:</span> 5 -8 Year
 | 
			
		||||
          </Box>
 | 
			
		||||
        </Flex>
 | 
			
		||||
      </Box>
 | 
			
		||||
 | 
			
		||||
          <Tabs.Panel value="technical" pt="xs">
 | 
			
		||||
            <Box mt={'md'} p={16}>
 | 
			
		||||
              <Text fw={500}>Note: </Text>
 | 
			
		||||
 | 
			
		||||
              <Flex gap={8}>
 | 
			
		||||
                <Box p={8} bg="#d9d2e9">
 | 
			
		||||
                  <span style={{ fontWeight: 500 }}>Level 1:</span> 3-12 Month
 | 
			
		||||
                </Box>
 | 
			
		||||
                <Box p={8} bg="#ffd966">
 | 
			
		||||
                  <span style={{ fontWeight: 500 }}>Level 2:</span> 3-5 Year
 | 
			
		||||
                </Box>
 | 
			
		||||
                <Box p={8} bg="#cfe2f3">
 | 
			
		||||
                  <span style={{ fontWeight: 500 }}>Level 3:</span> 5 -8 Year
 | 
			
		||||
                </Box>
 | 
			
		||||
              </Flex>
 | 
			
		||||
            </Box>
 | 
			
		||||
 | 
			
		||||
            <Box mt={'md'}>
 | 
			
		||||
              {isLoading ? (
 | 
			
		||||
                <Box
 | 
			
		||||
                  style={{
 | 
			
		||||
                    marginTop: '10%',
 | 
			
		||||
                    textAlign: 'center',
 | 
			
		||||
                    display: 'block',
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  <Loader size={'sm'} color="green" type="bars" m={'0 auto'} />
 | 
			
		||||
                  <Text fw={600} c={'gray'} mt={8}>
 | 
			
		||||
                    Loading Technical...
 | 
			
		||||
                  </Text>
 | 
			
		||||
                </Box>
 | 
			
		||||
              ) : (
 | 
			
		||||
                <DataTableAll
 | 
			
		||||
                  data={dataTechnical}
 | 
			
		||||
                  columns={columns}
 | 
			
		||||
                  size=""
 | 
			
		||||
                  searchInput
 | 
			
		||||
                  infoTotal={
 | 
			
		||||
                    <Button onClick={() => setAddTechnicalOpen(true)}>
 | 
			
		||||
                      + Add
 | 
			
		||||
                    </Button>
 | 
			
		||||
                  }
 | 
			
		||||
                />
 | 
			
		||||
              )}
 | 
			
		||||
            </Box>
 | 
			
		||||
          </Tabs.Panel>
 | 
			
		||||
 | 
			
		||||
          <Tabs.Panel value="second" pt="xs">
 | 
			
		||||
            Setting 2
 | 
			
		||||
          </Tabs.Panel>
 | 
			
		||||
 | 
			
		||||
          <Tabs.Panel value="third" pt="xs">
 | 
			
		||||
            Setting 3
 | 
			
		||||
          </Tabs.Panel>
 | 
			
		||||
        </Tabs>
 | 
			
		||||
      <Box mt={'md'}>
 | 
			
		||||
        {isLoading ? (
 | 
			
		||||
          <Box
 | 
			
		||||
            style={{
 | 
			
		||||
              marginTop: '10%',
 | 
			
		||||
              textAlign: 'center',
 | 
			
		||||
              display: 'block',
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Loader size={'sm'} color="green" type="bars" m={'0 auto'} />
 | 
			
		||||
            <Text fw={600} c={'gray'} mt={8}>
 | 
			
		||||
              Loading Technical...
 | 
			
		||||
            </Text>
 | 
			
		||||
          </Box>
 | 
			
		||||
        ) : (
 | 
			
		||||
          <DataTableAll
 | 
			
		||||
            data={dataTechnical}
 | 
			
		||||
            columns={columns}
 | 
			
		||||
            size=""
 | 
			
		||||
            searchInput
 | 
			
		||||
            infoTotal={
 | 
			
		||||
              <Button onClick={() => setAddTechnicalOpen(true)}>+ Add</Button>
 | 
			
		||||
            }
 | 
			
		||||
          />
 | 
			
		||||
        )}
 | 
			
		||||
      </Box>
 | 
			
		||||
 | 
			
		||||
      <Modal
 | 
			
		||||
| 
						 | 
				
			
			@ -320,7 +326,7 @@ function OrganizationSettings() {
 | 
			
		|||
          </Group>
 | 
			
		||||
        </Box>
 | 
			
		||||
      </Dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ import {
 | 
			
		|||
} from '@mantine/core'
 | 
			
		||||
import { notifications } from '@mantine/notifications'
 | 
			
		||||
import {
 | 
			
		||||
  IconExchange,
 | 
			
		||||
  IconPasswordUser,
 | 
			
		||||
  IconUserCode,
 | 
			
		||||
  IconUserCog,
 | 
			
		||||
| 
						 | 
				
			
			@ -39,19 +40,6 @@ import moment from 'moment'
 | 
			
		|||
 | 
			
		||||
const isCompactMenu = false
 | 
			
		||||
 | 
			
		||||
interface DataTechnical {
 | 
			
		||||
  id: number
 | 
			
		||||
  name: string
 | 
			
		||||
  level: number
 | 
			
		||||
  point: number
 | 
			
		||||
  updated_at: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface UpdateDataTechnical {
 | 
			
		||||
  technical_id: number | string
 | 
			
		||||
  point: number | string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Profile = () => {
 | 
			
		||||
  const user = useAppSelector((state) => state.authentication.user)
 | 
			
		||||
  const userData = getUser()
 | 
			
		||||
| 
						 | 
				
			
			@ -70,14 +58,6 @@ const Profile = () => {
 | 
			
		|||
  const [dataProfile, setDataProfile] = useState<any>([])
 | 
			
		||||
  const [countSpam, setCountSpam] = useState(0)
 | 
			
		||||
 | 
			
		||||
  const [dataTechnical, setDataTechnical] = useState<DataTechnical[]>([])
 | 
			
		||||
  const [loadingTechnical, setLoadingTechnical] = useState(false)
 | 
			
		||||
  const [isUpdateTechnical, setIsUpdateTechnical] = useState(false)
 | 
			
		||||
 | 
			
		||||
  const [updatedDataTechnical, setUpdatedDataTechnical] = useState<
 | 
			
		||||
    UpdateDataTechnical[]
 | 
			
		||||
  >([])
 | 
			
		||||
 | 
			
		||||
  const [selectedAvatar, setSelectedAvatar] = useState<string | null>(null)
 | 
			
		||||
  const navigate = useNavigate()
 | 
			
		||||
  const dispatch = useAppDispatch()
 | 
			
		||||
| 
						 | 
				
			
			@ -221,144 +201,6 @@ const Profile = () => {
 | 
			
		|||
    dispatch(logout(navigate))
 | 
			
		||||
  }, [dispatch, navigate])
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const fetchData = async () => {
 | 
			
		||||
      await getListUserTechnical()
 | 
			
		||||
    }
 | 
			
		||||
    fetchData()
 | 
			
		||||
  }, [])
 | 
			
		||||
 | 
			
		||||
  const columns = [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'level',
 | 
			
		||||
      size: '5%',
 | 
			
		||||
      header: 'Level',
 | 
			
		||||
      render: (row: any) => {
 | 
			
		||||
        return (
 | 
			
		||||
          <Box
 | 
			
		||||
            style={
 | 
			
		||||
              row?.level
 | 
			
		||||
                ? row?.level === 1
 | 
			
		||||
                  ? { backgroundColor: '#d9d2e9' }
 | 
			
		||||
                  : row?.level === 2
 | 
			
		||||
                  ? { backgroundColor: '#ffd966' }
 | 
			
		||||
                  : { backgroundColor: '#cfe2f3' }
 | 
			
		||||
                : { backgroundColor: '' }
 | 
			
		||||
            }
 | 
			
		||||
            fw={500}
 | 
			
		||||
            ta="center"
 | 
			
		||||
            p={4}
 | 
			
		||||
          >
 | 
			
		||||
            {row?.level ? row.level : ''}
 | 
			
		||||
          </Box>
 | 
			
		||||
        )
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'name',
 | 
			
		||||
      size: '50%',
 | 
			
		||||
      header: 'Name',
 | 
			
		||||
      render: (row: any) => {
 | 
			
		||||
        return <Text ta="start">{row?.name}</Text>
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'point',
 | 
			
		||||
      size: '5%',
 | 
			
		||||
      header: 'Point',
 | 
			
		||||
      render: (row: any) => {
 | 
			
		||||
        return (
 | 
			
		||||
          <TextInput
 | 
			
		||||
            mb={'md'}
 | 
			
		||||
            value={
 | 
			
		||||
              updatedDataTechnical.find(
 | 
			
		||||
                (technicalItem: UpdateDataTechnical) =>
 | 
			
		||||
                  technicalItem.technical_id === row?.id,
 | 
			
		||||
              )?.point
 | 
			
		||||
            }
 | 
			
		||||
            onChange={(e) => {
 | 
			
		||||
              setUpdatedDataTechnical((prev: any) =>
 | 
			
		||||
                prev.map((technicalItem: UpdateDataTechnical) => {
 | 
			
		||||
                  if (technicalItem.technical_id === row.id) {
 | 
			
		||||
                    return {
 | 
			
		||||
                      ...technicalItem,
 | 
			
		||||
                      point: e.target.value,
 | 
			
		||||
                    }
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  return technicalItem
 | 
			
		||||
                }),
 | 
			
		||||
              )
 | 
			
		||||
              setIsUpdateTechnical(true)
 | 
			
		||||
            }}
 | 
			
		||||
          />
 | 
			
		||||
        )
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'updated_at',
 | 
			
		||||
      size: '40%',
 | 
			
		||||
      header: 'Last update',
 | 
			
		||||
      render: (row: any) => {
 | 
			
		||||
        if (row?.updated_at) {
 | 
			
		||||
          return (
 | 
			
		||||
            <Text ta="start">
 | 
			
		||||
              {moment(row?.updated_at).format('HH:mm:ss DD/MM/YYYY')}
 | 
			
		||||
            </Text>
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ]
 | 
			
		||||
 | 
			
		||||
  const getListUserTechnical = async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      setLoadingTechnical(true)
 | 
			
		||||
      const params = {}
 | 
			
		||||
      const res = await get(listUserTechnical, params)
 | 
			
		||||
      if (res.status) {
 | 
			
		||||
        setDataTechnical(res.data)
 | 
			
		||||
        setUpdatedDataTechnical(
 | 
			
		||||
          res.data?.map((technicalItem: DataTechnical) => {
 | 
			
		||||
            return {
 | 
			
		||||
              technical_id: technicalItem.id,
 | 
			
		||||
              point: technicalItem.point,
 | 
			
		||||
            }
 | 
			
		||||
          }),
 | 
			
		||||
        )
 | 
			
		||||
      }
 | 
			
		||||
    } catch (error: any) {
 | 
			
		||||
      notifications.show({
 | 
			
		||||
        title: 'Error',
 | 
			
		||||
        message: error.message ?? error,
 | 
			
		||||
        color: 'red',
 | 
			
		||||
      })
 | 
			
		||||
    } finally {
 | 
			
		||||
      setLoadingTechnical(false)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const handleUpdateTechnical = async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      const res = await post(updateUserTechnical, {
 | 
			
		||||
        technicals: updatedDataTechnical,
 | 
			
		||||
      })
 | 
			
		||||
      if (res.status === true) {
 | 
			
		||||
        await getListUserTechnical()
 | 
			
		||||
 | 
			
		||||
        notifications.show({
 | 
			
		||||
          title: 'Success',
 | 
			
		||||
          message: res.message,
 | 
			
		||||
          color: 'green',
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log(error)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      <div className={classes.title}>
 | 
			
		||||
| 
						 | 
				
			
			@ -491,79 +333,7 @@ const Profile = () => {
 | 
			
		|||
          </Box>
 | 
			
		||||
 | 
			
		||||
          {swapTap ? (
 | 
			
		||||
            <Box className={classes.projectInvolvement}>
 | 
			
		||||
              <Flex justify="space-between" wrap="wrap">
 | 
			
		||||
                <Box px={16} ta="start">
 | 
			
		||||
                  <Text fw={500}>Level: </Text>
 | 
			
		||||
 | 
			
		||||
                  <Flex gap={8}>
 | 
			
		||||
                    <Box p={8} bg="#d9d2e9">
 | 
			
		||||
                      <span style={{ fontWeight: 500 }}>1:</span> 3-12 Month
 | 
			
		||||
                    </Box>
 | 
			
		||||
                    <Box p={8} bg="#ffd966">
 | 
			
		||||
                      <span style={{ fontWeight: 500 }}>2:</span> 3-5 Year
 | 
			
		||||
                    </Box>
 | 
			
		||||
                    <Box p={8} bg="#cfe2f3">
 | 
			
		||||
                      <span style={{ fontWeight: 500 }}>3:</span> 5 -8 Year
 | 
			
		||||
                    </Box>
 | 
			
		||||
                  </Flex>
 | 
			
		||||
                </Box>
 | 
			
		||||
 | 
			
		||||
                <Box px={16} ta="start">
 | 
			
		||||
                  <Text fw={500}>Point: </Text>
 | 
			
		||||
 | 
			
		||||
                  <Flex gap={8}>
 | 
			
		||||
                    <Box p={8} bg="#FFEA00">
 | 
			
		||||
                      <span style={{ fontWeight: 500 }}>0:</span> Unknown
 | 
			
		||||
                    </Box>
 | 
			
		||||
                    <Box p={8} bg="#FFEA00">
 | 
			
		||||
                      <span style={{ fontWeight: 500 }}>1:</span> Basic
 | 
			
		||||
                    </Box>
 | 
			
		||||
                    <Box p={8} bg="#FFEA00">
 | 
			
		||||
                      <span style={{ fontWeight: 500 }}>2:</span> Advanced
 | 
			
		||||
                    </Box>
 | 
			
		||||
                    <Box p={8} bg="#FFEA00">
 | 
			
		||||
                      <span style={{ fontWeight: 500 }}>3:</span> Master
 | 
			
		||||
                    </Box>
 | 
			
		||||
                  </Flex>
 | 
			
		||||
                </Box>
 | 
			
		||||
              </Flex>
 | 
			
		||||
 | 
			
		||||
              <Flex justify="space-between" mt={'lg'}>
 | 
			
		||||
                <div></div>
 | 
			
		||||
                <Title order={3}>Technicals</Title>
 | 
			
		||||
 | 
			
		||||
                <Button
 | 
			
		||||
                  disabled={loadingTechnical || !isUpdateTechnical}
 | 
			
		||||
                  onClick={handleUpdateTechnical}
 | 
			
		||||
                >
 | 
			
		||||
                  Update
 | 
			
		||||
                </Button>
 | 
			
		||||
              </Flex>
 | 
			
		||||
 | 
			
		||||
              {loadingTechnical ? (
 | 
			
		||||
                <Box
 | 
			
		||||
                  style={{
 | 
			
		||||
                    width: '100%',
 | 
			
		||||
                    marginTop: '10%',
 | 
			
		||||
                    textAlign: 'center',
 | 
			
		||||
                    display: 'block',
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  <Loader size={'sm'} color="green" type="bars" m={'0 auto'} />
 | 
			
		||||
                  <Text fw={600} c={'gray'} mt={8}>
 | 
			
		||||
                    Loading Technical...
 | 
			
		||||
                  </Text>
 | 
			
		||||
                </Box>
 | 
			
		||||
              ) : (
 | 
			
		||||
                <DataTableAll
 | 
			
		||||
                  data={dataTechnical}
 | 
			
		||||
                  columns={columns}
 | 
			
		||||
                  size=""
 | 
			
		||||
                  searchInput
 | 
			
		||||
                />
 | 
			
		||||
              )}
 | 
			
		||||
            </Box>
 | 
			
		||||
            <UserTechnical />
 | 
			
		||||
          ) : (
 | 
			
		||||
            <Box className={classes.projectInvolvement}>
 | 
			
		||||
              <Title order={3}>Project Involved</Title>
 | 
			
		||||
| 
						 | 
				
			
			@ -672,4 +442,259 @@ const Profile = () => {
 | 
			
		|||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// User Technical
 | 
			
		||||
interface DataTechnical {
 | 
			
		||||
  id: number
 | 
			
		||||
  name: string
 | 
			
		||||
  level: number
 | 
			
		||||
  point: number
 | 
			
		||||
  updated_at: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface UpdateDataTechnical {
 | 
			
		||||
  technical_id: number | string
 | 
			
		||||
  point: number | string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const UserTechnical = () => {
 | 
			
		||||
  const [dataTechnical, setDataTechnical] = useState<DataTechnical[]>([])
 | 
			
		||||
  const [loadingTechnical, setLoadingTechnical] = useState(false)
 | 
			
		||||
  const [isUpdateTechnical, setIsUpdateTechnical] = useState<
 | 
			
		||||
    string[] | number[]
 | 
			
		||||
  >([])
 | 
			
		||||
  const [updatedDataTechnical, setUpdatedDataTechnical] = useState<
 | 
			
		||||
    UpdateDataTechnical[]
 | 
			
		||||
  >([])
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const fetchData = async () => {
 | 
			
		||||
      await getListUserTechnical()
 | 
			
		||||
    }
 | 
			
		||||
    fetchData()
 | 
			
		||||
  }, [])
 | 
			
		||||
 | 
			
		||||
  const columns = [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'level',
 | 
			
		||||
      size: '5%',
 | 
			
		||||
      header: 'Level',
 | 
			
		||||
      render: (row: any) => {
 | 
			
		||||
        return (
 | 
			
		||||
          <Box
 | 
			
		||||
            style={
 | 
			
		||||
              row?.level
 | 
			
		||||
                ? row?.level === 1
 | 
			
		||||
                  ? { backgroundColor: '#d9d2e9' }
 | 
			
		||||
                  : row?.level === 2
 | 
			
		||||
                  ? { backgroundColor: '#ffd966' }
 | 
			
		||||
                  : { backgroundColor: '#cfe2f3' }
 | 
			
		||||
                : { backgroundColor: '' }
 | 
			
		||||
            }
 | 
			
		||||
            fw={500}
 | 
			
		||||
            ta="center"
 | 
			
		||||
            p={4}
 | 
			
		||||
          >
 | 
			
		||||
            {row?.level ? row.level : ''}
 | 
			
		||||
          </Box>
 | 
			
		||||
        )
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'name',
 | 
			
		||||
      size: '45%',
 | 
			
		||||
      header: 'Name',
 | 
			
		||||
      render: (row: any) => {
 | 
			
		||||
        return <Text ta="start">{row?.name}</Text>
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'point',
 | 
			
		||||
      size: '10%',
 | 
			
		||||
      header: 'Point',
 | 
			
		||||
      render: (row: any) => {
 | 
			
		||||
        return (
 | 
			
		||||
          <TextInput
 | 
			
		||||
            mb={'md'}
 | 
			
		||||
            value={
 | 
			
		||||
              updatedDataTechnical.find(
 | 
			
		||||
                (technicalItem: UpdateDataTechnical) =>
 | 
			
		||||
                  technicalItem.technical_id === row?.id,
 | 
			
		||||
              )?.point
 | 
			
		||||
            }
 | 
			
		||||
            rightSection={
 | 
			
		||||
              isUpdateTechnical.some(
 | 
			
		||||
                (item: string | number) => item === row.id,
 | 
			
		||||
              ) ? (
 | 
			
		||||
                <IconExchange size={16} color="#1c7ed6" />
 | 
			
		||||
              ) : (
 | 
			
		||||
                ''
 | 
			
		||||
              )
 | 
			
		||||
            }
 | 
			
		||||
            onChange={(e) => {
 | 
			
		||||
              const value = e.target.value
 | 
			
		||||
 | 
			
		||||
              // Ensure the input is between 0 and 3
 | 
			
		||||
              if (value === '' || (Number(value) >= 0 && Number(value) <= 3)) {
 | 
			
		||||
                setUpdatedDataTechnical((prev: any) =>
 | 
			
		||||
                  prev.map((technicalItem: UpdateDataTechnical) => {
 | 
			
		||||
                    if (technicalItem.technical_id === row.id) {
 | 
			
		||||
                      return {
 | 
			
		||||
                        ...technicalItem,
 | 
			
		||||
                        point: value,
 | 
			
		||||
                      }
 | 
			
		||||
                    }
 | 
			
		||||
                    return technicalItem
 | 
			
		||||
                  }),
 | 
			
		||||
                )
 | 
			
		||||
                setIsUpdateTechnical((prev) => [...prev, row?.id])
 | 
			
		||||
              }
 | 
			
		||||
            }}
 | 
			
		||||
            onFocus={(e) => e.target.select()}
 | 
			
		||||
          />
 | 
			
		||||
        )
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'updated_at',
 | 
			
		||||
      size: '40%',
 | 
			
		||||
      header: 'Last update',
 | 
			
		||||
      render: (row: any) => {
 | 
			
		||||
        if (row?.updated_at) {
 | 
			
		||||
          return (
 | 
			
		||||
            <Text ta="start">
 | 
			
		||||
              {moment(row?.updated_at).format('HH:mm:ss DD/MM/YYYY')}
 | 
			
		||||
            </Text>
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ]
 | 
			
		||||
 | 
			
		||||
  const getListUserTechnical = async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      setLoadingTechnical(true)
 | 
			
		||||
      const params = {}
 | 
			
		||||
      const res = await get(listUserTechnical, params)
 | 
			
		||||
      if (res.status) {
 | 
			
		||||
        setDataTechnical(res.data)
 | 
			
		||||
        setUpdatedDataTechnical(
 | 
			
		||||
          res.data?.map((technicalItem: DataTechnical) => {
 | 
			
		||||
            return {
 | 
			
		||||
              technical_id: technicalItem.id,
 | 
			
		||||
              point: technicalItem.point,
 | 
			
		||||
            }
 | 
			
		||||
          }),
 | 
			
		||||
        )
 | 
			
		||||
      }
 | 
			
		||||
    } catch (error: any) {
 | 
			
		||||
      notifications.show({
 | 
			
		||||
        title: 'Error',
 | 
			
		||||
        message: error.message ?? error,
 | 
			
		||||
        color: 'red',
 | 
			
		||||
      })
 | 
			
		||||
    } finally {
 | 
			
		||||
      setLoadingTechnical(false)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const handleUpdateUserTechnical = async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      const res = await post(updateUserTechnical, {
 | 
			
		||||
        technicals: updatedDataTechnical,
 | 
			
		||||
      })
 | 
			
		||||
      if (res.status === true) {
 | 
			
		||||
        await getListUserTechnical()
 | 
			
		||||
 | 
			
		||||
        notifications.show({
 | 
			
		||||
          title: 'Success',
 | 
			
		||||
          message: res.message,
 | 
			
		||||
          color: 'green',
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log(error)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Box className={classes.projectInvolvement}>
 | 
			
		||||
      <Flex justify="space-between" wrap="wrap">
 | 
			
		||||
        {/* Level */}
 | 
			
		||||
        <Box px={16} ta="start">
 | 
			
		||||
          <Text fw={500}>Level: </Text>
 | 
			
		||||
 | 
			
		||||
          <Flex gap={8} wrap="wrap">
 | 
			
		||||
            <Box p={8} bg="#d9d2e9">
 | 
			
		||||
              <span style={{ fontWeight: 500 }}>1:</span> 3-12 Month
 | 
			
		||||
            </Box>
 | 
			
		||||
            <Box p={8} bg="#ffd966">
 | 
			
		||||
              <span style={{ fontWeight: 500 }}>2:</span> 3-5 Year
 | 
			
		||||
            </Box>
 | 
			
		||||
            <Box p={8} bg="#cfe2f3">
 | 
			
		||||
              <span style={{ fontWeight: 500 }}>3:</span> 5 -8 Year
 | 
			
		||||
            </Box>
 | 
			
		||||
          </Flex>
 | 
			
		||||
        </Box>
 | 
			
		||||
 | 
			
		||||
        {/* Point */}
 | 
			
		||||
        <Box px={16} ta="start" mt={{ base: 8, lg: 0 }}>
 | 
			
		||||
          <Text fw={500}>Point: </Text>
 | 
			
		||||
 | 
			
		||||
          <Flex gap={8} wrap="wrap">
 | 
			
		||||
            <Box p={8} bg="#FFEA00">
 | 
			
		||||
              <span style={{ fontWeight: 500 }}>0:</span> Unknown
 | 
			
		||||
            </Box>
 | 
			
		||||
            <Box p={8} bg="#FFEA00">
 | 
			
		||||
              <span style={{ fontWeight: 500 }}>1:</span> Basic
 | 
			
		||||
            </Box>
 | 
			
		||||
            <Box p={8} bg="#FFEA00">
 | 
			
		||||
              <span style={{ fontWeight: 500 }}>2:</span> Advanced
 | 
			
		||||
            </Box>
 | 
			
		||||
            <Box p={8} bg="#FFEA00">
 | 
			
		||||
              <span style={{ fontWeight: 500 }}>3:</span> Master
 | 
			
		||||
            </Box>
 | 
			
		||||
          </Flex>
 | 
			
		||||
        </Box>
 | 
			
		||||
      </Flex>
 | 
			
		||||
 | 
			
		||||
      <Flex justify="space-between" mt={'lg'}>
 | 
			
		||||
        <div></div>
 | 
			
		||||
        <Title order={3}>Technicals</Title>
 | 
			
		||||
 | 
			
		||||
        <Button
 | 
			
		||||
          disabled={loadingTechnical || isUpdateTechnical.length === 0}
 | 
			
		||||
          onClick={handleUpdateUserTechnical}
 | 
			
		||||
        >
 | 
			
		||||
          Update
 | 
			
		||||
        </Button>
 | 
			
		||||
      </Flex>
 | 
			
		||||
 | 
			
		||||
      {loadingTechnical ? (
 | 
			
		||||
        <Box
 | 
			
		||||
          style={{
 | 
			
		||||
            width: '100%',
 | 
			
		||||
            marginTop: '10%',
 | 
			
		||||
            textAlign: 'center',
 | 
			
		||||
            display: 'block',
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Loader size={'sm'} color="green" type="bars" m={'0 auto'} />
 | 
			
		||||
          <Text fw={600} c={'gray'} mt={8}>
 | 
			
		||||
            Loading Technical...
 | 
			
		||||
          </Text>
 | 
			
		||||
        </Box>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <DataTableAll
 | 
			
		||||
          data={dataTechnical}
 | 
			
		||||
          columns={columns}
 | 
			
		||||
          size=""
 | 
			
		||||
          searchInput
 | 
			
		||||
        />
 | 
			
		||||
      )}
 | 
			
		||||
    </Box>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default Profile
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue