dev #130
|
|
@ -216,7 +216,7 @@ class TicketController extends Controller
|
||||||
$reason = $request->input('reason');
|
$reason = $request->input('reason');
|
||||||
$isAccept = $request->input('is_accept') ?? false;
|
$isAccept = $request->input('is_accept') ?? false;
|
||||||
$user = auth('admins')->user(); // user create ticket
|
$user = auth('admins')->user(); // user create ticket
|
||||||
|
|
||||||
$start_date = Carbon::create($startDate)->setTimezone(env('TIME_ZONE'));
|
$start_date = Carbon::create($startDate)->setTimezone(env('TIME_ZONE'));
|
||||||
$end_date = Carbon::create($endDate)->setTimezone(env('TIME_ZONE'));
|
$end_date = Carbon::create($endDate)->setTimezone(env('TIME_ZONE'));
|
||||||
|
|
||||||
|
|
@ -369,7 +369,7 @@ class TicketController extends Controller
|
||||||
);
|
);
|
||||||
// Thêm kiểm tra null trước khi gửi mail
|
// Thêm kiểm tra null trước khi gửi mail
|
||||||
if ($dataMasterStartPeriod && $dataMasterEndPeriod && $dataMasterType) {
|
if ($dataMasterStartPeriod && $dataMasterEndPeriod && $dataMasterType) {
|
||||||
Mail::to($value->email)->send(new TicketMail($data));
|
Mail::to($value->email)->send(new TicketMail($data));
|
||||||
} else {
|
} else {
|
||||||
Log::error("Missing category data for ticket ID: {$ticket->id}. Mail not sent.");
|
Log::error("Missing category data for ticket ID: {$ticket->id}. Mail not sent.");
|
||||||
}
|
}
|
||||||
|
|
@ -846,16 +846,16 @@ class TicketController extends Controller
|
||||||
} else if ($ticket->type == "WFH") {
|
} else if ($ticket->type == "WFH") {
|
||||||
$dataListPeriod = $this->getAllPeriod($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
|
$dataListPeriod = $this->getAllPeriod($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
|
||||||
foreach ($dataListPeriod as $result) {
|
foreach ($dataListPeriod as $result) {
|
||||||
list($year, $month, $day) = explode('-', $result['date']);
|
list($year, $month, $day) = explode('-', $result['date']);
|
||||||
Notes::create([
|
Notes::create([
|
||||||
'n_user_id' => $ticket->user_id,
|
'n_user_id' => $ticket->user_id,
|
||||||
'n_day' => $day,
|
'n_day' => $day,
|
||||||
'n_month' => $month,
|
'n_month' => $month,
|
||||||
'n_year' => $year,
|
'n_year' => $year,
|
||||||
'n_time_type' => $result['period'],
|
'n_time_type' => $result['period'],
|
||||||
'n_reason' => $ticket->type,
|
'n_reason' => $ticket->type,
|
||||||
'n_note' => $ticket->reason
|
'n_note' => $ticket->reason
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
//WFH - start tracking
|
//WFH - start tracking
|
||||||
|
|
|
||||||
|
|
@ -60,3 +60,37 @@
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Thêm styles cho Modal xác nhận xóa */
|
||||||
|
.deleteModal {
|
||||||
|
background-color: light-dark(white, #2d353c);
|
||||||
|
text-align: center;
|
||||||
|
border: solid 1px #ff4646;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteModalTitle {
|
||||||
|
color: #ff4646;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteModalContent {
|
||||||
|
color: light-dark(#2d353c, white);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteModalFooter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteButton {
|
||||||
|
background-color: #ff4646;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteButton:hover {
|
||||||
|
background-color: #ff6b6b;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import {
|
||||||
TextInput,
|
TextInput,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Modal,
|
Modal,
|
||||||
|
Group,
|
||||||
} from '@mantine/core'
|
} from '@mantine/core'
|
||||||
import { useDisclosure } from '@mantine/hooks'
|
import { useDisclosure } from '@mantine/hooks'
|
||||||
import { notifications } from '@mantine/notifications'
|
import { notifications } from '@mantine/notifications'
|
||||||
|
|
@ -147,6 +148,9 @@ const Timekeeping = () => {
|
||||||
const [exportModalOpened, setExportModalOpened] = useState(false)
|
const [exportModalOpened, setExportModalOpened] = useState(false)
|
||||||
const [exportOption, setExportOption] = useState('default')
|
const [exportOption, setExportOption] = useState('default')
|
||||||
|
|
||||||
|
const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false)
|
||||||
|
const [noteToDelete, setNoteToDelete] = useState<any>(null)
|
||||||
|
|
||||||
const getListMasterByType = async (type: string) => {
|
const getListMasterByType = async (type: string) => {
|
||||||
try {
|
try {
|
||||||
const params = {
|
const params = {
|
||||||
|
|
@ -445,16 +449,16 @@ const Timekeeping = () => {
|
||||||
try {
|
try {
|
||||||
const timestamp = moment().format('DDMMYYYY_HHmmss')
|
const timestamp = moment().format('DDMMYYYY_HHmmss')
|
||||||
const fileName = `Timekeeping_${date.month}_${date.year}_${timestamp}.xlsx`
|
const fileName = `Timekeeping_${date.month}_${date.year}_${timestamp}.xlsx`
|
||||||
|
|
||||||
await exportFile(
|
await exportFile(
|
||||||
exportTimekeeping,
|
exportTimekeeping,
|
||||||
{
|
{
|
||||||
month: date.month,
|
month: date.month,
|
||||||
year: date.year,
|
year: date.year,
|
||||||
working_days: workingDays,
|
working_days: workingDays,
|
||||||
option: option
|
option: option,
|
||||||
},
|
},
|
||||||
fileName
|
fileName,
|
||||||
)
|
)
|
||||||
setExportModalOpened(false)
|
setExportModalOpened(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -462,6 +466,58 @@ const Timekeeping = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleConfirmDelete = async () => {
|
||||||
|
if (noteToDelete) {
|
||||||
|
await handleDelete(noteToDelete.id)
|
||||||
|
setIsDeleteConfirmOpen(false)
|
||||||
|
setNoteToDelete(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const openDeleteConfirm = (note: any) => {
|
||||||
|
setNoteToDelete(note)
|
||||||
|
setIsDeleteConfirmOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeleteConfirmModal = () => (
|
||||||
|
<Modal
|
||||||
|
opened={isDeleteConfirmOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsDeleteConfirmOpen(false)
|
||||||
|
setNoteToDelete(null)
|
||||||
|
}}
|
||||||
|
centered
|
||||||
|
size="sm"
|
||||||
|
classNames={{
|
||||||
|
content: classes.deleteModal,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text className={classes.deleteModalTitle}>
|
||||||
|
Confirm Delete
|
||||||
|
</Text>
|
||||||
|
<Text className={classes.deleteModalContent}>
|
||||||
|
Are you sure you want to delete this note?
|
||||||
|
</Text>
|
||||||
|
<Box className={classes.deleteModalFooter}>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => {
|
||||||
|
setIsDeleteConfirmOpen(false)
|
||||||
|
setNoteToDelete(null)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className={classes.deleteButton}
|
||||||
|
onClick={handleConfirmDelete}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.title}>
|
<div className={classes.title}>
|
||||||
|
|
@ -631,11 +687,7 @@ const Timekeeping = () => {
|
||||||
>
|
>
|
||||||
<IconTrash
|
<IconTrash
|
||||||
className={classes.deleteIcon}
|
className={classes.deleteIcon}
|
||||||
onClick={async () => {
|
onClick={() => openDeleteConfirm(item)}
|
||||||
await handleDelete(item.id)
|
|
||||||
// handleUpdateCacheMonth()
|
|
||||||
// close2()
|
|
||||||
}}
|
|
||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
/>
|
/>
|
||||||
|
|
@ -655,7 +707,7 @@ const Timekeeping = () => {
|
||||||
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(),
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|
@ -710,9 +762,9 @@ const Timekeeping = () => {
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setExportModalOpened(true)}
|
onClick={() => setExportModalOpened(true)}
|
||||||
size="xs"
|
size="xs"
|
||||||
ml="md"
|
ml="md"
|
||||||
bg={'green'}
|
bg={'green'}
|
||||||
leftSection={<IconFileExcel size={16} />}
|
leftSection={<IconFileExcel size={16} />}
|
||||||
|
|
@ -1074,20 +1126,19 @@ const Timekeeping = () => {
|
||||||
placeholder="Choose an option"
|
placeholder="Choose an option"
|
||||||
value={exportOption}
|
value={exportOption}
|
||||||
onChange={(value) => setExportOption(value || 'default')}
|
onChange={(value) => setExportOption(value || 'default')}
|
||||||
data={[
|
data={[{ value: 'default', label: 'Default' }]}
|
||||||
{ value: 'default', label: 'Default' }
|
|
||||||
]}
|
|
||||||
mb="md"
|
mb="md"
|
||||||
/>
|
/>
|
||||||
<Box style={{ display: 'flex', justifyContent: 'flex-end', gap: '10px' }}>
|
<Box
|
||||||
|
style={{ display: 'flex', justifyContent: 'flex-end', gap: '10px' }}
|
||||||
|
>
|
||||||
<Button variant="outline" onClick={() => setExportModalOpened(false)}>
|
<Button variant="outline" onClick={() => setExportModalOpened(false)}>
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => handleExport(exportOption)}>
|
<Button onClick={() => handleExport(exportOption)}>Export</Button>
|
||||||
Export
|
|
||||||
</Button>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<DeleteConfirmModal />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue