truong-leave-day #116

Merged
joseph merged 26 commits from truong-leave-day into dev 2025-06-10 12:51:32 +10:00
3 changed files with 116 additions and 31 deletions
Showing only changes of commit b5a7740d9f - Show all commits

View File

@ -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

View File

@ -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;
}

View File

@ -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>
) )
} }