Tạo page ticket management
This commit is contained in:
parent
afca1c0f6c
commit
1bc36e6eec
|
|
@ -1,385 +0,0 @@
|
|||
import {
|
||||
getLeaveManagement,
|
||||
getListMaster,
|
||||
getTicketOfUser,
|
||||
updateNoteLeave,
|
||||
} from '@/api/Admin'
|
||||
import { update } from '@/rtk/helpers/CRUD'
|
||||
import { get } from '@/rtk/helpers/apiService'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Drawer,
|
||||
HoverCard,
|
||||
Menu,
|
||||
Select,
|
||||
Table,
|
||||
Text,
|
||||
Textarea,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import moment from 'moment'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { IconEdit } from '@tabler/icons-react'
|
||||
|
||||
import classes from './Tickets.module.css'
|
||||
|
||||
interface UserData {
|
||||
id: number
|
||||
name: string
|
||||
email: string
|
||||
email_verified_at: string | null
|
||||
permission: string
|
||||
remember_token: string | null
|
||||
created_at: string | null
|
||||
updated_at: string | null
|
||||
reason: string
|
||||
}
|
||||
|
||||
interface DataReason {
|
||||
id: number
|
||||
c_code: string
|
||||
c_name: string
|
||||
}
|
||||
|
||||
interface DataTimeType {
|
||||
id: number
|
||||
c_code: string
|
||||
c_name: string
|
||||
}
|
||||
|
||||
const Tickets = () => {
|
||||
const [opened1, { open: open1, close: close1 }] = useDisclosure(false)
|
||||
const [disableBtn, setDisableBtn] = useState(false)
|
||||
const monthInYear = getMonthNames()
|
||||
const [customAddNotes, setCustomAddNotes] = useState<{
|
||||
id: number
|
||||
user: {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
note: string
|
||||
totalLeave: string
|
||||
dayAdditional: string
|
||||
}>({
|
||||
id: 0,
|
||||
user: {
|
||||
id: 0,
|
||||
name: '',
|
||||
},
|
||||
note: '',
|
||||
totalLeave: '',
|
||||
dayAdditional: '',
|
||||
})
|
||||
|
||||
const [data, setData] = useState<UserData[]>([])
|
||||
const [date, setDate] = useState({
|
||||
year: new Date().getFullYear().toString(),
|
||||
})
|
||||
|
||||
const [dataTimeType, setDataTimeType] = useState<DataTimeType[]>([])
|
||||
const [dataReason, setDataReason] = useState<DataReason[]>([])
|
||||
|
||||
const getListMasterByType = async (type: string) => {
|
||||
try {
|
||||
const params = {
|
||||
type: type,
|
||||
}
|
||||
const res = await get(getListMaster, params)
|
||||
if (res.status) {
|
||||
return res.data
|
||||
}
|
||||
} catch (error: any) {
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: error.message ?? error,
|
||||
color: 'red',
|
||||
})
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const resultTimeType = await getListMasterByType('TIME_TYPE')
|
||||
setDataTimeType(resultTimeType)
|
||||
|
||||
const resultReason = await getListMasterByType('REASON')
|
||||
setDataReason(resultReason)
|
||||
}
|
||||
|
||||
fetchData()
|
||||
}, [])
|
||||
|
||||
const getLeaveList = async () => {
|
||||
try {
|
||||
const res = await get(getTicketOfUser, {
|
||||
// year: date.year,
|
||||
})
|
||||
if (res.status) {
|
||||
setData(res.data)
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log(error)
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: error.message ?? error,
|
||||
color: 'red',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getLeaveList()
|
||||
}, [date])
|
||||
|
||||
const updateInfoNote = async (
|
||||
id: number,
|
||||
users: {
|
||||
id: number
|
||||
name: string
|
||||
},
|
||||
totalLeave: string,
|
||||
dayAdditional: string,
|
||||
note: string,
|
||||
) => {
|
||||
try {
|
||||
await update(
|
||||
updateNoteLeave,
|
||||
{
|
||||
id: id,
|
||||
users: users,
|
||||
totalLeave: totalLeave,
|
||||
dayAdditional: dayAdditional,
|
||||
note: note,
|
||||
},
|
||||
getLeaveList,
|
||||
)
|
||||
|
||||
setDisableBtn(false)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
function getMonthNames() {
|
||||
const monthNames = [
|
||||
{
|
||||
value: 1,
|
||||
name: 'January',
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
name: 'February',
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
name: 'March',
|
||||
},
|
||||
{
|
||||
value: 4,
|
||||
name: 'April',
|
||||
},
|
||||
{
|
||||
value: 5,
|
||||
name: 'May',
|
||||
},
|
||||
{
|
||||
value: 6,
|
||||
name: 'June',
|
||||
},
|
||||
{
|
||||
value: 7,
|
||||
name: 'July',
|
||||
},
|
||||
{
|
||||
value: 8,
|
||||
name: 'August',
|
||||
},
|
||||
{
|
||||
value: 9,
|
||||
name: 'September',
|
||||
},
|
||||
{
|
||||
value: 10,
|
||||
name: 'October',
|
||||
},
|
||||
{
|
||||
value: 11,
|
||||
name: 'November',
|
||||
},
|
||||
{
|
||||
value: 12,
|
||||
name: 'December',
|
||||
},
|
||||
]
|
||||
return monthNames.map((month) => {
|
||||
return {
|
||||
value: month.value,
|
||||
name: month.name.substring(0, 3),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// console.log(customAddNotes, 'customAddNotes')
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.title}>
|
||||
<h3>
|
||||
<Text>Admin/</Text> Tickets
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<Box display={'flex'}>
|
||||
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'30%'}>
|
||||
<Box w="100%" display={'flex'}>
|
||||
{/* <Select
|
||||
w="50%"
|
||||
value={date.year}
|
||||
size="xs"
|
||||
ml={'sm'}
|
||||
label="Year"
|
||||
data={Array.from({ length: 10 }, (_, index) => {
|
||||
return {
|
||||
value: (
|
||||
parseInt(moment(Date.now()).format('YYYY')) -
|
||||
3 +
|
||||
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) => {
|
||||
setDate({ ...date, year: e! })
|
||||
}}
|
||||
></Select> */}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
w="70%"
|
||||
pl={200}
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'end',
|
||||
}}
|
||||
>
|
||||
<Box display={'flex'} style={{ alignItems: 'end' }}></Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box>
|
||||
<Table
|
||||
striped
|
||||
highlightOnHover
|
||||
withTableBorder
|
||||
withColumnBorders
|
||||
mt={'md'}
|
||||
>
|
||||
<Table.Thead>
|
||||
<Table.Tr bg={'#228be66b'}>
|
||||
<Table.Th></Table.Th>
|
||||
<Table.Th>User</Table.Th>
|
||||
<Table.Th ta={'center'}>Start Period</Table.Th>
|
||||
<Table.Th ta={'center'}>Start Date</Table.Th>
|
||||
<Table.Th ta={'center'}>End Period</Table.Th>
|
||||
<Table.Th ta={'center'}>End Date</Table.Th>
|
||||
<Table.Th ta={'center'}>Reason</Table.Th>
|
||||
<Table.Th ta={'center'}>Notes</Table.Th>
|
||||
<Table.Th ta={'center'}></Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{data.map((user, index) => {
|
||||
let ld_note = user.reason
|
||||
return (
|
||||
<Table.Tr key={user.id} className={classes.tableTr}>
|
||||
<Table.Td ta={'center'}>{index + 1}</Table.Td>
|
||||
<Table.Td>
|
||||
<Tooltip multiline label={user.name}>
|
||||
<div>{user.name}</div>
|
||||
</Tooltip>
|
||||
</Table.Td>
|
||||
|
||||
<Table.Td ta={'center'}>{}</Table.Td>
|
||||
<Table.Td ta={'center'}>{}</Table.Td>
|
||||
<Table.Td ta={'center'}>{}</Table.Td>
|
||||
<Table.Td ta={'center'} bg={'#ffb5b5'}>
|
||||
{}
|
||||
</Table.Td>
|
||||
<Table.Td ta={'center'} bg={'#c3ffc3'}>
|
||||
{}
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Box
|
||||
style={{
|
||||
display:
|
||||
ld_note === '' || ld_note === null ? 'none' : 'block',
|
||||
}}
|
||||
>
|
||||
<HoverCard width={280} shadow="md">
|
||||
<HoverCard.Target>
|
||||
<Text fz={'sm'}>
|
||||
{ld_note !== null &&
|
||||
ld_note !== '' &&
|
||||
ld_note.slice(0, 25) + '...'}
|
||||
</Text>
|
||||
</HoverCard.Target>
|
||||
<HoverCard.Dropdown>
|
||||
<Textarea size="sm" autosize>
|
||||
{ld_note}
|
||||
</Textarea>
|
||||
</HoverCard.Dropdown>
|
||||
</HoverCard>
|
||||
</Box>
|
||||
</Table.Td>
|
||||
<Table.Td ta={'center'}>
|
||||
<IconEdit
|
||||
color="green"
|
||||
width={20}
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
// let totalLeave =
|
||||
// user.leaveDay.ld_day == 0
|
||||
// ? ''
|
||||
// : String(user.leaveDay.ld_day)
|
||||
// let dayAdditional =
|
||||
// user.leaveDay.ld_date_additional == 0
|
||||
// ? ''
|
||||
// : String(user.leaveDay.ld_date_additional)
|
||||
// open1()
|
||||
// setCustomAddNotes({
|
||||
// ...customAddNotes,
|
||||
// id: user.leaveDay.id,
|
||||
// note: ld_note,
|
||||
// totalLeave: totalLeave,
|
||||
// dayAdditional: dayAdditional,
|
||||
// user: {
|
||||
// id: user.user.id,
|
||||
// name: user.user.name,
|
||||
// },
|
||||
// })
|
||||
}}
|
||||
/>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
)
|
||||
})}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Box>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tickets
|
||||
|
|
@ -7,56 +7,42 @@
|
|||
padding: 0 var(--mantine-spacing-sm) var(--mantine-spacing-lg)
|
||||
var(--mantine-spacing-sm);
|
||||
border-bottom: solid rgba(201, 201, 201, 0.377) 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.optionIcon {
|
||||
.optionIcon {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
}
|
||||
|
||||
.deleteIcon {
|
||||
.deleteIcon {
|
||||
color: red;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
border-radius: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
.deleteIcon:hover {
|
||||
background-color: rgba(203, 203, 203, 0.809);
|
||||
}
|
||||
|
||||
.editIcon {
|
||||
.editIcon {
|
||||
color: rgb(9, 132, 132);
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
border-radius: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
.editIcon:hover {
|
||||
.editIcon:hover {
|
||||
background-color: rgba(203, 203, 203, 0.809);
|
||||
}
|
||||
}
|
||||
|
||||
.dialog {
|
||||
.deleteIcon:hover {
|
||||
background-color: rgba(203, 203, 203, 0.809);
|
||||
}
|
||||
|
||||
.dialog {
|
||||
background-color: light-dark(white, #2d353c);
|
||||
text-align: center;
|
||||
border: solid 1px rgb(255, 145, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.dialogText {
|
||||
.dialogText {
|
||||
color: light-dark(#2d353c, white);
|
||||
}
|
||||
|
||||
.tableTr:hover {
|
||||
background-color: rgb(205, 255, 255);
|
||||
}
|
||||
|
||||
.popoverFooter {
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
.historyRow td {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,44 @@
|
|||
import { getLeaveManagement, updateNoteLeave } from '@/api/Admin'
|
||||
import { update } from '@/rtk/helpers/CRUD'
|
||||
import {
|
||||
addTicket,
|
||||
deleteTicket,
|
||||
getListMaster,
|
||||
getTicketsOfUser
|
||||
} from '@/api/Admin'
|
||||
import { DataTablePagination } from '@/components/DataTable/DataTable'
|
||||
import { Xdelete, create } from '@/rtk/helpers/CRUD'
|
||||
import { get } from '@/rtk/helpers/apiService'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Drawer,
|
||||
HoverCard,
|
||||
Menu,
|
||||
Dialog,
|
||||
Group,
|
||||
Modal,
|
||||
Select,
|
||||
Table,
|
||||
Text,
|
||||
Textarea,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { DateInput } from '@mantine/dates'
|
||||
import { useForm } from '@mantine/form'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import { IconTrash } from '@tabler/icons-react'
|
||||
import moment from 'moment'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { IconEdit } from '@tabler/icons-react'
|
||||
|
||||
import classes from './TicketsManagement.module.css'
|
||||
|
||||
type TTickets = {
|
||||
id: number
|
||||
start_period: string
|
||||
end_period: string
|
||||
type: string
|
||||
start_date: Date
|
||||
end_date: Date
|
||||
reason: string
|
||||
}
|
||||
|
||||
type TListTickets = {
|
||||
data: User[]
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: number
|
||||
name: string
|
||||
|
|
@ -34,68 +50,173 @@ interface User {
|
|||
updated_at: string | null
|
||||
}
|
||||
|
||||
interface LeaveDay {
|
||||
interface DataReason {
|
||||
id: number
|
||||
ld_user_id: number
|
||||
ld_year: number
|
||||
ld_day: number
|
||||
ld_date_additional: number
|
||||
ld_note: string
|
||||
created_at: string | null
|
||||
updated_at: string | null
|
||||
c_code: string
|
||||
c_name: string
|
||||
}
|
||||
|
||||
interface MonthlyLeaveDays {
|
||||
month: number
|
||||
leave_days: number
|
||||
}
|
||||
|
||||
interface UserData {
|
||||
user: User
|
||||
leaveDay: LeaveDay
|
||||
monthlyLeaveDays: MonthlyLeaveDays[]
|
||||
interface DataTimeType {
|
||||
id: number
|
||||
c_code: string
|
||||
c_name: string
|
||||
}
|
||||
|
||||
const TicketsManagement = () => {
|
||||
const [opened1, { open: open1, close: close1 }] = useDisclosure(false)
|
||||
const [listTickets, setListTiskets] = useState<TListTickets>({
|
||||
data: [],
|
||||
})
|
||||
const [action, setAction] = useState('')
|
||||
const [item, setItem] = useState({ id: 0 })
|
||||
const [activeBtn, setActiveBtn] = useState(false)
|
||||
const [disableBtn, setDisableBtn] = useState(false)
|
||||
const monthInYear = getMonthNames()
|
||||
const [customAddNotes, setCustomAddNotes] = useState<{
|
||||
id: number
|
||||
user: {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
note: string
|
||||
totalLeave: string
|
||||
dayAdditional: string
|
||||
}>({
|
||||
id: 0,
|
||||
user: {
|
||||
id: 0,
|
||||
name: '',
|
||||
},
|
||||
note: '',
|
||||
totalLeave: '',
|
||||
dayAdditional: '',
|
||||
})
|
||||
|
||||
const [data, setData] = useState<UserData[]>([])
|
||||
const [date, setDate] = useState({
|
||||
year: new Date().getFullYear().toString(),
|
||||
})
|
||||
const getLeaveList = async () => {
|
||||
const [dataTimeType, setDataTimeType] = useState<DataTimeType[]>([])
|
||||
const [dataReason, setDataReason] = useState<DataReason[]>([])
|
||||
|
||||
const getListMasterByType = async (type: string) => {
|
||||
try {
|
||||
const res = await get(getLeaveManagement, {
|
||||
year: date.year,
|
||||
})
|
||||
const params = {
|
||||
type: type,
|
||||
}
|
||||
const res = await get(getListMaster, params)
|
||||
if (res.status) {
|
||||
setData(
|
||||
res.data.filter((u: UserData) => u.user.permission.includes('staff')),
|
||||
)
|
||||
return res.data
|
||||
}
|
||||
} catch (error: any) {
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: error.message ?? error,
|
||||
color: 'red',
|
||||
})
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const resultTimeType = await getListMasterByType('TIME_TYPE')
|
||||
setDataTimeType(
|
||||
resultTimeType.filter((item: DataTimeType) => item.c_code !== 'ALL'),
|
||||
)
|
||||
|
||||
const resultReason = await getListMasterByType('REASON')
|
||||
setDataReason(resultReason)
|
||||
}
|
||||
|
||||
fetchData()
|
||||
}, [])
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'id',
|
||||
size: '3%',
|
||||
header: 'ID',
|
||||
},
|
||||
{
|
||||
name: 'user_name',
|
||||
size: '17%',
|
||||
header: 'User',
|
||||
},
|
||||
{
|
||||
name: 'startPeriodName',
|
||||
size: '8%',
|
||||
header: 'Start Period',
|
||||
},
|
||||
{
|
||||
name: 'start_date',
|
||||
size: '11%',
|
||||
header: 'From Date',
|
||||
render: (row: any) => {
|
||||
return moment(row.start_date).format('DD/MM/YYYY')
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'endPeriodName',
|
||||
size: '8%',
|
||||
header: 'End Period',
|
||||
},
|
||||
{
|
||||
name: 'end_date',
|
||||
size: '10%',
|
||||
header: 'End Date',
|
||||
render: (row: any) => {
|
||||
return moment(row.end_date).format('DD/MM/YYYY')
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'typeReasonName',
|
||||
size: '10%',
|
||||
header: 'Reason',
|
||||
},
|
||||
{
|
||||
name: 'reason',
|
||||
size: '20%',
|
||||
header: 'Notes',
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
size: '8%',
|
||||
header: 'Status',
|
||||
},
|
||||
{
|
||||
name: '#',
|
||||
size: '5%',
|
||||
header: 'Action',
|
||||
render: (row: any) => {
|
||||
return (
|
||||
<Box className={classes.optionIcon}>
|
||||
<IconTrash
|
||||
className={classes.deleteIcon}
|
||||
onClick={() => {
|
||||
setAction('delete')
|
||||
setItem(row)
|
||||
}}
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const filterInfo = [
|
||||
{
|
||||
key: 'reason',
|
||||
name: 'Notes',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
key: 'start_date',
|
||||
name: 'From Date',
|
||||
type: 'date',
|
||||
},
|
||||
{
|
||||
key: 'end_date',
|
||||
name: 'End Date',
|
||||
type: 'date',
|
||||
},
|
||||
]
|
||||
|
||||
const getAllTickets = async () => {
|
||||
try {
|
||||
const searchParams = new URLSearchParams(window.location.search)
|
||||
const params = {}
|
||||
|
||||
for (const [key, value] of searchParams.entries()) {
|
||||
if (key === 'page' && value === '') {
|
||||
Object.assign(params, { [`${key}`]: 1 })
|
||||
} else {
|
||||
Object.assign(params, { [`${key}`]: value })
|
||||
}
|
||||
}
|
||||
|
||||
const res = await get(getTicketsOfUser, params)
|
||||
if (res.status) {
|
||||
setListTiskets(res)
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log(error)
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: error.message ?? error,
|
||||
|
|
@ -104,377 +225,227 @@ const TicketsManagement = () => {
|
|||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getLeaveList()
|
||||
}, [date])
|
||||
|
||||
const updateInfoNote = async (
|
||||
id: number,
|
||||
users: {
|
||||
id: number
|
||||
name: string
|
||||
},
|
||||
totalLeave: string,
|
||||
dayAdditional: string,
|
||||
note: string,
|
||||
) => {
|
||||
const handleCreate = async (values: TTickets) => {
|
||||
try {
|
||||
await update(
|
||||
updateNoteLeave,
|
||||
const res = await create(
|
||||
addTicket,
|
||||
{
|
||||
id: id,
|
||||
users: users,
|
||||
totalLeave: totalLeave,
|
||||
dayAdditional: dayAdditional,
|
||||
note: note,
|
||||
// time_string: moment(values.time_string).format('YYYY-MM-DD HH:mm:ss'),
|
||||
start_date: moment(values.start_date).format('YYYY-MM-DD'),
|
||||
start_period: values.start_period,
|
||||
end_date: moment(values.end_date).format('YYYY-MM-DD'),
|
||||
end_period: values.end_period,
|
||||
type: values.type,
|
||||
reason: values.reason,
|
||||
},
|
||||
getLeaveList,
|
||||
getAllTickets,
|
||||
)
|
||||
|
||||
setDisableBtn(false)
|
||||
if (res === true) {
|
||||
setAction('')
|
||||
form.reset()
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
function getMonthNames() {
|
||||
const monthNames = [
|
||||
{
|
||||
value: 1,
|
||||
name: 'January',
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
name: 'February',
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
name: 'March',
|
||||
},
|
||||
{
|
||||
value: 4,
|
||||
name: 'April',
|
||||
},
|
||||
{
|
||||
value: 5,
|
||||
name: 'May',
|
||||
},
|
||||
{
|
||||
value: 6,
|
||||
name: 'June',
|
||||
},
|
||||
{
|
||||
value: 7,
|
||||
name: 'July',
|
||||
},
|
||||
{
|
||||
value: 8,
|
||||
name: 'August',
|
||||
},
|
||||
{
|
||||
value: 9,
|
||||
name: 'September',
|
||||
},
|
||||
{
|
||||
value: 10,
|
||||
name: 'October',
|
||||
},
|
||||
{
|
||||
value: 11,
|
||||
name: 'November',
|
||||
},
|
||||
{
|
||||
value: 12,
|
||||
name: 'December',
|
||||
},
|
||||
]
|
||||
return monthNames.map((month) => {
|
||||
return {
|
||||
value: month.value,
|
||||
name: month.name.substring(0, 3),
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
await Xdelete(deleteTicket, { ticket_id: id }, getAllTickets)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// console.log(customAddNotes, 'customAddNotes')
|
||||
useEffect(() => {
|
||||
getAllTickets()
|
||||
}, [])
|
||||
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
id: 0,
|
||||
start_date: new Date(),
|
||||
start_period: '',
|
||||
end_date: new Date(),
|
||||
end_period: '',
|
||||
type: '',
|
||||
reason: '',
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.title}>
|
||||
<h3>
|
||||
<Text>Admin/</Text> Leave Management
|
||||
<Text>Admin/</Text>
|
||||
Tickets Management
|
||||
</h3>
|
||||
</div>
|
||||
<Drawer
|
||||
opened={opened1}
|
||||
onClose={close1}
|
||||
position="right"
|
||||
title={<strong>Update Day Leave</strong>}
|
||||
>
|
||||
<TextInput
|
||||
mb={'md'}
|
||||
value={customAddNotes.totalLeave}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
if (value) {
|
||||
const floatValue = parseFloat(value)
|
||||
if (
|
||||
/^\d*\.?\d?$/.test(value) &&
|
||||
floatValue >= 0 &&
|
||||
floatValue <= 20
|
||||
) {
|
||||
setCustomAddNotes({
|
||||
...customAddNotes,
|
||||
totalLeave: value,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
setCustomAddNotes({
|
||||
...customAddNotes,
|
||||
totalLeave: value,
|
||||
})
|
||||
}
|
||||
}}
|
||||
label={'Total Leave'}
|
||||
placeholder="Input placeholder"
|
||||
/>
|
||||
<TextInput
|
||||
mb={'md'}
|
||||
value={customAddNotes.dayAdditional}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
if (value) {
|
||||
const floatValue = parseFloat(value)
|
||||
if (
|
||||
/^\d*\.?\d?$/.test(value) &&
|
||||
floatValue >= 0 &&
|
||||
floatValue <= 20
|
||||
) {
|
||||
setCustomAddNotes({
|
||||
...customAddNotes,
|
||||
dayAdditional: value,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
setCustomAddNotes({
|
||||
...customAddNotes,
|
||||
dayAdditional: '',
|
||||
})
|
||||
}
|
||||
}}
|
||||
label={'Day additional leave'}
|
||||
placeholder="Input placeholder"
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
mb={'md'}
|
||||
label="Note"
|
||||
value={customAddNotes.note}
|
||||
onChange={(e) => {
|
||||
setCustomAddNotes({ ...customAddNotes, note: e.target.value })
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
m={5}
|
||||
onClick={() => {
|
||||
setDisableBtn(true)
|
||||
if (
|
||||
customAddNotes.id === 0
|
||||
// ||
|
||||
// customAddNotes.totalLeave === '' ||
|
||||
// customAddNotes.totalLeave === '0'
|
||||
// customAddNotes.dayAdditional === 0 ||
|
||||
// customAddNotes.note === ''
|
||||
) {
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Input data required',
|
||||
color: 'red',
|
||||
})
|
||||
setDisableBtn(false)
|
||||
} else {
|
||||
updateInfoNote(
|
||||
customAddNotes.id,
|
||||
customAddNotes.user,
|
||||
customAddNotes.totalLeave,
|
||||
customAddNotes.dayAdditional,
|
||||
customAddNotes.note,
|
||||
)
|
||||
}
|
||||
setAction('add')
|
||||
form.reset()
|
||||
}}
|
||||
disabled={disableBtn}
|
||||
>
|
||||
Save
|
||||
+ Add
|
||||
</Button>
|
||||
</Drawer>
|
||||
<Box display={'flex'}>
|
||||
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'30%'}>
|
||||
<Box w="100%" display={'flex'}>
|
||||
<Select
|
||||
w="50%"
|
||||
value={date.year}
|
||||
size="xs"
|
||||
ml={'sm'}
|
||||
label="Year"
|
||||
data={Array.from({ length: 10 }, (_, index) => {
|
||||
return {
|
||||
value: (
|
||||
parseInt(moment(Date.now()).format('YYYY')) -
|
||||
3 +
|
||||
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) => {
|
||||
setDate({ ...date, year: e! })
|
||||
}}
|
||||
></Select>
|
||||
</div>
|
||||
<Box p={20}>
|
||||
{listTickets.data.length > 0 && (
|
||||
<DataTablePagination
|
||||
filterInfo={filterInfo}
|
||||
data={listTickets}
|
||||
columns={columns}
|
||||
// searchInput
|
||||
size=""
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Add/Edit User modal */}
|
||||
<Modal
|
||||
opened={action === 'add' || action === 'edit'}
|
||||
onClose={() => {
|
||||
setAction('')
|
||||
form.reset()
|
||||
}}
|
||||
title={
|
||||
<Text pl={'sm'} fw={700} fz={'lg'}>
|
||||
{action === 'add' && 'Add Ticket'}
|
||||
</Text>
|
||||
}
|
||||
>
|
||||
<form
|
||||
onSubmit={form.onSubmit(async (values) => {
|
||||
setDisableBtn(true)
|
||||
action === 'add' && (await handleCreate(values))
|
||||
setDisableBtn(false)
|
||||
})}
|
||||
>
|
||||
<Box pl={'md'} pr={'md'}>
|
||||
<Box display={'flex'}>
|
||||
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'40%'}>
|
||||
<DateInput
|
||||
required
|
||||
mb={'md'}
|
||||
label={'From Date'}
|
||||
value={new Date(form.values.start_date)}
|
||||
valueFormat="DD/MM/YYYY"
|
||||
onChange={(e) => form.setFieldValue('start_date', e!)}
|
||||
></DateInput>
|
||||
|
||||
<Select
|
||||
required
|
||||
mb={'md'}
|
||||
label={'Start Period'}
|
||||
data={dataTimeType.map((item) => {
|
||||
return { value: item.c_code.toString(), label: item.c_name }
|
||||
})}
|
||||
value={form.values.start_period}
|
||||
error={form.errors.start_period}
|
||||
onChange={(e) => form.setFieldValue('start_period', e!)}
|
||||
/>
|
||||
|
||||
<Select
|
||||
required
|
||||
mb={'md'}
|
||||
searchable
|
||||
label="Type"
|
||||
data={dataReason.map((user) => ({
|
||||
value: user.c_code.toString(),
|
||||
label: user.c_name,
|
||||
}))}
|
||||
value={form.values.type}
|
||||
error={form.errors.type}
|
||||
onChange={(e) => form.setFieldValue('type', e!)}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
w="70%"
|
||||
pl={200}
|
||||
style={{
|
||||
display: 'flex',
|
||||
// alignItems: 'end',
|
||||
justifyContent: 'end',
|
||||
}}
|
||||
>
|
||||
<Box display={'flex'} style={{ alignItems: 'end' }}>
|
||||
{/* <Tooltip label="Save working days">
|
||||
<Button
|
||||
size="xs"
|
||||
ml={'sm'}
|
||||
onClick={() => {
|
||||
//form add user new
|
||||
}}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</Tooltip> */}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box>
|
||||
<Table
|
||||
striped
|
||||
highlightOnHover
|
||||
withTableBorder
|
||||
withColumnBorders
|
||||
mt={'md'}
|
||||
>
|
||||
<Table.Thead>
|
||||
<Table.Tr bg={'#228be66b'}>
|
||||
<Table.Th></Table.Th>
|
||||
<Table.Th>User</Table.Th>
|
||||
{monthInYear.map((d) => {
|
||||
return (
|
||||
<Menu width={200} shadow="md" key={d.value}>
|
||||
<Menu.Target>
|
||||
<Table.Th ta={'center'} style={{ cursor: 'pointer' }}>
|
||||
<span>{d.name}</span>
|
||||
</Table.Th>
|
||||
</Menu.Target>
|
||||
</Menu>
|
||||
)
|
||||
style={{ display: 'flex', flexFlow: 'column' }}
|
||||
w={'20%'}
|
||||
></Box>
|
||||
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'40%'}>
|
||||
<DateInput
|
||||
required
|
||||
mb={'md'}
|
||||
label={'End Date'}
|
||||
value={new Date(form.values.end_date)}
|
||||
valueFormat="DD/MM/YYYY"
|
||||
onChange={(e) => form.setFieldValue('end_date', e!)}
|
||||
></DateInput>
|
||||
<Select
|
||||
required
|
||||
mb={'md'}
|
||||
label={'End Period'}
|
||||
data={dataTimeType.map((item) => {
|
||||
return { value: item.c_code.toString(), label: item.c_name }
|
||||
})}
|
||||
<Table.Th ta={'center'}>Total</Table.Th>
|
||||
<Table.Th ta={'center'}>Off</Table.Th>
|
||||
<Table.Th ta={'center'}>Remaining</Table.Th>
|
||||
<Table.Th ta={'center'}>Notes</Table.Th>
|
||||
<Table.Th ta={'center'}></Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{data.map((user, index) => {
|
||||
let totalDayOff = 0
|
||||
let totalDayLeave =
|
||||
user.leaveDay.ld_day + user.leaveDay.ld_date_additional
|
||||
let ld_note = user.leaveDay.ld_note
|
||||
return (
|
||||
<Table.Tr key={user.user.id} className={classes.tableTr}>
|
||||
<Table.Td ta={'center'}>{index + 1}</Table.Td>
|
||||
<Table.Td>
|
||||
<Tooltip multiline label={user.user.name}>
|
||||
<div>{user.user.name}</div>
|
||||
</Tooltip>
|
||||
</Table.Td>
|
||||
|
||||
{monthInYear.map((d, i) => {
|
||||
let total =
|
||||
user.monthlyLeaveDays.find((item) => {
|
||||
return item.month == d.value
|
||||
})?.leave_days ?? 0
|
||||
totalDayOff = totalDayOff + total
|
||||
return (
|
||||
<Table.Td bg={total > 0 ? '#ffb5b5' : ''} key={i} ta={'center'}>
|
||||
{total === 0 ? '' : total}
|
||||
</Table.Td>
|
||||
)
|
||||
})}
|
||||
|
||||
<Table.Td ta={'center'}>{totalDayLeave}</Table.Td>
|
||||
<Table.Td ta={'center'} bg={'#ffb5b5'}>{totalDayOff}</Table.Td>
|
||||
<Table.Td ta={'center'} bg={'#c3ffc3'}>
|
||||
{totalDayLeave - totalDayOff}
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Box style={{display: ld_note === "" || ld_note === null? 'none' : 'block'}}>
|
||||
<HoverCard width={280} shadow="md" >
|
||||
<HoverCard.Target>
|
||||
<Text fz={'sm'}>{ld_note !== null && ld_note !== "" && ld_note.slice(0,25)+"..."}</Text>
|
||||
</HoverCard.Target>
|
||||
<HoverCard.Dropdown>
|
||||
<Textarea size="sm" autosize>
|
||||
{ld_note}
|
||||
</Textarea>
|
||||
</HoverCard.Dropdown>
|
||||
</HoverCard>
|
||||
</Box>
|
||||
</Table.Td>
|
||||
<Table.Td ta={'center'}>
|
||||
<IconEdit
|
||||
color="green"
|
||||
width={20}
|
||||
style={{cursor:'pointer'}}
|
||||
onClick={() => {
|
||||
let totalLeave =
|
||||
user.leaveDay.ld_day == 0
|
||||
? ''
|
||||
: String(user.leaveDay.ld_day)
|
||||
let dayAdditional =
|
||||
user.leaveDay.ld_date_additional == 0
|
||||
? ''
|
||||
: String(user.leaveDay.ld_date_additional)
|
||||
open1()
|
||||
setCustomAddNotes({
|
||||
...customAddNotes,
|
||||
id: user.leaveDay.id,
|
||||
note: ld_note,
|
||||
totalLeave: totalLeave,
|
||||
dayAdditional: dayAdditional,
|
||||
user: {
|
||||
id: user.user.id,
|
||||
name: user.user.name,
|
||||
},
|
||||
})
|
||||
}}
|
||||
value={form.values.end_period}
|
||||
error={form.errors.end_period}
|
||||
onChange={(e) => form.setFieldValue('end_period', e!)}
|
||||
/>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
)
|
||||
})}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Textarea
|
||||
label="Reason"
|
||||
required
|
||||
value={form.values.reason}
|
||||
onChange={(e) => form.setFieldValue('reason', e.target.value)}
|
||||
/>
|
||||
<Box ta={'center'}>
|
||||
{action === 'add' && (
|
||||
<Button
|
||||
mt={'lg'}
|
||||
bg={'green'}
|
||||
type="submit"
|
||||
disabled={disableBtn}
|
||||
>
|
||||
Create
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</form>
|
||||
</Modal>
|
||||
|
||||
<Dialog
|
||||
className={classes.dialog}
|
||||
opened={action === 'delete'}
|
||||
withCloseButton
|
||||
onClose={() => setAction('')}
|
||||
size="lg"
|
||||
radius="md"
|
||||
position={{ top: 30, right: 10 }}
|
||||
>
|
||||
<Text className={classes.dialogText} size="sm" mb="xs" fw={500}>
|
||||
Do you want to delete this record?
|
||||
<Group justify="center" m={10}>
|
||||
<Button
|
||||
disabled={activeBtn}
|
||||
fw={700}
|
||||
size="xs"
|
||||
variant="light"
|
||||
onClick={async () => {
|
||||
setActiveBtn(true)
|
||||
await handleDelete(item.id)
|
||||
setActiveBtn(false)
|
||||
setAction('')
|
||||
}}
|
||||
>
|
||||
Yes
|
||||
</Button>
|
||||
<Button
|
||||
fw={700}
|
||||
size="xs"
|
||||
variant="light"
|
||||
onClick={() => setAction('')}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</Group>
|
||||
</Text>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue