Merge pull request 'Deploy to prod' (#132) from dev into master
Reviewed-on: #132
This commit is contained in:
commit
6e1e452bf1
|
|
@ -38,6 +38,7 @@ class LeaveManagementController extends Controller
|
||||||
$join->on('reason.c_type', DB::raw("CONCAT('REASON_NOTES')"));
|
$join->on('reason.c_type', DB::raw("CONCAT('REASON_NOTES')"));
|
||||||
})
|
})
|
||||||
->select(
|
->select(
|
||||||
|
DB::raw('notes.id as id'),
|
||||||
DB::raw('notes.n_user_id as n_user_id'),
|
DB::raw('notes.n_user_id as n_user_id'),
|
||||||
DB::raw('notes.n_time_type as time_type'),
|
DB::raw('notes.n_time_type as time_type'),
|
||||||
DB::raw('notes.n_year as year'),
|
DB::raw('notes.n_year as year'),
|
||||||
|
|
@ -58,6 +59,7 @@ class LeaveManagementController extends Controller
|
||||||
->get()
|
->get()
|
||||||
->map(function ($item) {
|
->map(function ($item) {
|
||||||
return [
|
return [
|
||||||
|
"id" => $item->id,
|
||||||
"day" => $item->day,
|
"day" => $item->day,
|
||||||
"n_user_id" => $item->n_user_id,
|
"n_user_id" => $item->n_user_id,
|
||||||
"reason_code" => $item->reason_code,
|
"reason_code" => $item->reason_code,
|
||||||
|
|
@ -145,6 +147,28 @@ class LeaveManagementController extends Controller
|
||||||
return response()->json(['status' => true, 'message' => 'Updated successfully']);
|
return response()->json(['status' => true, 'message' => 'Updated successfully']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function updateNoteStatus(Request $request)
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
'id' => 'required',
|
||||||
|
'n_reason' => 'required|in:ONLEAVE,LEAVE_WITHOUT_PAY'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validate the request
|
||||||
|
$request->validate($rules);
|
||||||
|
$id = $request->input('id');
|
||||||
|
$reason = $request->input('n_reason');
|
||||||
|
|
||||||
|
$note = Notes::find($id);
|
||||||
|
if (!$note) {
|
||||||
|
return response()->json(['message' => 'Note not found', 'status' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$note->n_reason = $reason;
|
||||||
|
$note->save();
|
||||||
|
return response()->json(data: ['message' => 'Update success', 'status' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
public function export(Request $request)
|
public function export(Request $request)
|
||||||
{
|
{
|
||||||
$year = $request->query('year', now()->year);
|
$year = $request->query('year', now()->year);
|
||||||
|
|
|
||||||
|
|
@ -173,52 +173,62 @@ class TimekeepingController extends Controller
|
||||||
// Validate the request
|
// Validate the request
|
||||||
$request->validate($rules);
|
$request->validate($rules);
|
||||||
$id = $request->input('id');
|
$id = $request->input('id');
|
||||||
|
$month = $request->month;
|
||||||
|
$year = $request->year;
|
||||||
|
|
||||||
$note = Notes::find($id);
|
$note = Notes::find($id);
|
||||||
if (!$note) {
|
if (!$note) {
|
||||||
return response()->json(['message' => 'Note not found', 'status' => false]);
|
return response()->json(['message' => 'Note not found', 'status' => false]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$ticket = Ticket::find($note->ticket_id);
|
if ($note->ticket_id != null) {
|
||||||
if (!$ticket) {
|
$ticket = Ticket::find($note->ticket_id);
|
||||||
return response()->json(['message' => 'Ticket not found, can not delete note', 'status' => false]);
|
if (!$ticket) {
|
||||||
|
return response()->json(['message' => 'Ticket not found, can not delete note', 'status' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin = auth('admins')->user();
|
||||||
|
|
||||||
|
// Handle send mail
|
||||||
|
$dataMasterStartPeriod = CategoryController::getListMasterByCodeAndType("TIME_TYPE", $ticket->start_period);
|
||||||
|
$dataMasterEndPeriod = CategoryController::getListMasterByCodeAndType("TIME_TYPE", $ticket->end_period);
|
||||||
|
$dataMasterType = CategoryController::getListMasterByCodeAndType("REASON", $ticket->type);
|
||||||
|
$formattedStartDate = Carbon::createFromFormat('Y-m-d', $ticket->start_date)->format('d/m/Y');
|
||||||
|
$formattedEndDate = Carbon::createFromFormat('Y-m-d', $ticket->end_date)->format('d/m/Y');
|
||||||
|
|
||||||
|
$user = Admin::find($ticket->user_id);
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
"email_template" => "email.notification_tickets_user",
|
||||||
|
"user_name" => $user->name,
|
||||||
|
"email" => $user->email,
|
||||||
|
"name" => $admin->name, //name admin duyệt
|
||||||
|
"date" => $dataMasterStartPeriod->c_name . " (" . $formattedStartDate . ") - " . $dataMasterEndPeriod->c_name . " (" . $formattedEndDate . ")",
|
||||||
|
"type" => $dataMasterType->c_name,
|
||||||
|
"note" => $ticket->reason,
|
||||||
|
"admin_note" => $ticket->admin_note,
|
||||||
|
"link" => "/tickets", //link đến page admin
|
||||||
|
"status" => "refused",
|
||||||
|
"subject" => "[Ticket response] Ticket From " . $admin->name
|
||||||
|
);
|
||||||
|
Mail::to($user->email)->send(new TicketMail($data));
|
||||||
|
|
||||||
|
// Update
|
||||||
|
$ticket->updated_by = $admin->name;
|
||||||
|
$ticket->status = "REFUSED";
|
||||||
|
$ticket->save();
|
||||||
|
Notes::where('ticket_id', $ticket->id)->delete();
|
||||||
|
|
||||||
|
// Clear Timekeeping cache
|
||||||
|
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->start_date)->month, Carbon::parse($ticket->start_date)->year);
|
||||||
|
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->end_date)->month, Carbon::parse($ticket->end_date)->year);
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Delete success', 'status' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$admin = auth('admins')->user();
|
$note->delete();
|
||||||
|
$this->createOrUpdateRecordForCurrentMonth($month, $year);
|
||||||
|
|
||||||
// Handle send mail
|
|
||||||
$dataMasterStartPeriod = CategoryController::getListMasterByCodeAndType("TIME_TYPE", $ticket->start_period);
|
|
||||||
$dataMasterEndPeriod = CategoryController::getListMasterByCodeAndType("TIME_TYPE", $ticket->end_period);
|
|
||||||
$dataMasterType = CategoryController::getListMasterByCodeAndType("REASON", $ticket->type);
|
|
||||||
$formattedStartDate = Carbon::createFromFormat('Y-m-d', $ticket->start_date)->format('d/m/Y');
|
|
||||||
$formattedEndDate = Carbon::createFromFormat('Y-m-d', $ticket->end_date)->format('d/m/Y');
|
|
||||||
|
|
||||||
$user = Admin::find($ticket->user_id);
|
|
||||||
|
|
||||||
$data = array(
|
|
||||||
"email_template" => "email.notification_tickets_user",
|
|
||||||
"user_name" => $user->name,
|
|
||||||
"email" => $user->email,
|
|
||||||
"name" => $admin->name, //name admin duyệt
|
|
||||||
"date" => $dataMasterStartPeriod->c_name . " (" . $formattedStartDate . ") - " . $dataMasterEndPeriod->c_name . " (" . $formattedEndDate . ")",
|
|
||||||
"type" => $dataMasterType->c_name,
|
|
||||||
"note" => $ticket->reason,
|
|
||||||
"admin_note" => $ticket->admin_note,
|
|
||||||
"link" => "/tickets", //link đến page admin
|
|
||||||
"status" => "refused",
|
|
||||||
"subject" => "[Ticket response] Ticket From " . $admin->name
|
|
||||||
);
|
|
||||||
Mail::to($user->email)->send(new TicketMail($data));
|
|
||||||
|
|
||||||
// Update
|
|
||||||
$ticket->updated_by = $admin->name;
|
|
||||||
$ticket->status = "REFUSED";
|
|
||||||
$ticket->save();
|
|
||||||
Notes::where('ticket_id', $ticket->id)->delete();
|
|
||||||
|
|
||||||
// Clear Timekeeping cache
|
|
||||||
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->start_date)->month, Carbon::parse($ticket->start_date)->year);
|
|
||||||
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->end_date)->month, Carbon::parse($ticket->end_date)->year);
|
|
||||||
return response()->json(['message' => 'Delete success', 'status' => true]);
|
return response()->json(['message' => 'Delete success', 'status' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,7 @@ Route::middleware('api')
|
||||||
Route::get('/', [LeaveManagementController::class, 'get'])->middleware('check.permission:admin.hr.staff.accountant');
|
Route::get('/', [LeaveManagementController::class, 'get'])->middleware('check.permission:admin.hr.staff.accountant');
|
||||||
Route::get('/export', [LeaveManagementController::class, 'export'])->middleware('check.permission:admin.hr.staff.accountant');
|
Route::get('/export', [LeaveManagementController::class, 'export'])->middleware('check.permission:admin.hr.staff.accountant');
|
||||||
Route::post('/saveNoteLeave', [LeaveManagementController::class, 'saveNoteLeave'])->middleware('check.permission:admin.hr');
|
Route::post('/saveNoteLeave', [LeaveManagementController::class, 'saveNoteLeave'])->middleware('check.permission:admin.hr');
|
||||||
|
Route::post('/updateNoteStatus', [LeaveManagementController::class, 'updateNoteStatus'])->middleware('check.permission:admin.hr');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group([
|
Route::group([
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,13 @@ use Modules\Auth\app\Models\User;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Modules\Admin\app\Models\Category;
|
use Modules\Admin\app\Models\Category;
|
||||||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||||||
|
use App\Traits\AnalyzeData;
|
||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
use IsAPI;
|
use IsAPI;
|
||||||
|
use AnalyzeData;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('jwt.auth');
|
$this->middleware('jwt.auth');
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ export const getListMaster = API_URL + 'v1/admin/category/get-list-master'
|
||||||
export const getLeaveManagement = API_URL + 'v1/admin/leave-management'
|
export const getLeaveManagement = API_URL + 'v1/admin/leave-management'
|
||||||
export const updateNoteLeave =
|
export const updateNoteLeave =
|
||||||
API_URL + 'v1/admin/leave-management/saveNoteLeave'
|
API_URL + 'v1/admin/leave-management/saveNoteLeave'
|
||||||
|
export const updateNoteStatus =
|
||||||
|
API_URL + 'v1/admin/leave-management/updateNoteStatus'
|
||||||
export const exportLeaveManagement =
|
export const exportLeaveManagement =
|
||||||
API_URL + 'v1/admin/leave-management/export'
|
API_URL + 'v1/admin/leave-management/export'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
Group,
|
Group,
|
||||||
HoverCard,
|
HoverCard,
|
||||||
Menu,
|
Menu,
|
||||||
|
Modal,
|
||||||
Select,
|
Select,
|
||||||
Stack,
|
Stack,
|
||||||
Table,
|
Table,
|
||||||
|
|
@ -21,15 +22,23 @@ import {
|
||||||
} 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'
|
||||||
import { IconEdit, IconFileExcel, IconHelpCircle } from '@tabler/icons-react'
|
import {
|
||||||
|
IconEdit,
|
||||||
|
IconFileExcel,
|
||||||
|
IconHelpCircle,
|
||||||
|
IconRefresh,
|
||||||
|
IconTrash,
|
||||||
|
} from '@tabler/icons-react'
|
||||||
import classes from './LeaveManagement.module.css'
|
import classes from './LeaveManagement.module.css'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getLeaveManagement,
|
getLeaveManagement,
|
||||||
updateNoteLeave,
|
updateNoteLeave,
|
||||||
exportLeaveManagement,
|
exportLeaveManagement,
|
||||||
|
updateNoteStatus,
|
||||||
|
deleteNote,
|
||||||
} from '@/api/Admin'
|
} from '@/api/Admin'
|
||||||
import { update } from '@/rtk/helpers/CRUD'
|
import { update, Xdelete } from '@/rtk/helpers/CRUD'
|
||||||
import { get, exportFile } from '@/rtk/helpers/apiService'
|
import { get, exportFile } from '@/rtk/helpers/apiService'
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
|
|
@ -57,6 +66,7 @@ interface LeaveDay {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MonthlyLeaveDays {
|
interface MonthlyLeaveDays {
|
||||||
|
id: number
|
||||||
day: number
|
day: number
|
||||||
leave_days: number
|
leave_days: number
|
||||||
month: number
|
month: number
|
||||||
|
|
@ -86,6 +96,48 @@ interface UserData {
|
||||||
|
|
||||||
const LeaveManagement = () => {
|
const LeaveManagement = () => {
|
||||||
const [opened1, { open: open1, close: close1 }] = useDisclosure(false)
|
const [opened1, { open: open1, close: close1 }] = useDisclosure(false)
|
||||||
|
const [openedDetailOff, { open: openDetailOff, close: closeDetailOff }] =
|
||||||
|
useDisclosure(false)
|
||||||
|
const [detailOffItem, setDetailOffItem] = useState<UserData>({
|
||||||
|
user: {
|
||||||
|
id: 0,
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
email_verified_at: '',
|
||||||
|
permission: '',
|
||||||
|
remember_token: '',
|
||||||
|
avatar: '',
|
||||||
|
created_at: '',
|
||||||
|
updated_at: '',
|
||||||
|
},
|
||||||
|
leaveDay: {
|
||||||
|
id: 0,
|
||||||
|
ld_user_id: 0,
|
||||||
|
ld_year: 0,
|
||||||
|
ld_day_total: 0,
|
||||||
|
ld_additional_day: 0,
|
||||||
|
ld_special_leave_day: 0,
|
||||||
|
ld_note: '',
|
||||||
|
created_at: '',
|
||||||
|
updated_at: '',
|
||||||
|
},
|
||||||
|
monthlyLeaveDays: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const [isStatusConfirmOpen, setIsStatusConfirmOpen] = useState(false)
|
||||||
|
const [isDisableStatusBtn, setIsDisableStatusBtn] = useState(false)
|
||||||
|
const [noteStatus, setNoteStatus] = useState<{
|
||||||
|
id: number
|
||||||
|
reason: string
|
||||||
|
}>({
|
||||||
|
id: 0,
|
||||||
|
reason: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false)
|
||||||
|
const [isDisableDeleteBtn, setIsDisableDeleteBtn] = useState(false)
|
||||||
|
const [noteToDelete, setNoteToDelete] = useState<any>(null)
|
||||||
|
|
||||||
const [disableBtn, setDisableBtn] = useState(false)
|
const [disableBtn, setDisableBtn] = useState(false)
|
||||||
const monthInYear = getMonthNames()
|
const monthInYear = getMonthNames()
|
||||||
const [customAddNotes, setCustomAddNotes] = useState<{
|
const [customAddNotes, setCustomAddNotes] = useState<{
|
||||||
|
|
@ -209,6 +261,51 @@ const LeaveManagement = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateNote = async () => {
|
||||||
|
setIsDisableStatusBtn(true)
|
||||||
|
try {
|
||||||
|
await update(
|
||||||
|
updateNoteStatus,
|
||||||
|
{
|
||||||
|
id: noteStatus.id,
|
||||||
|
n_reason: noteStatus.reason,
|
||||||
|
},
|
||||||
|
getLeaveList,
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
} finally {
|
||||||
|
setIsDisableStatusBtn(false)
|
||||||
|
closeDetailOff()
|
||||||
|
setIsStatusConfirmOpen(false)
|
||||||
|
setNoteStatus({
|
||||||
|
id: 0,
|
||||||
|
reason: '',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteNote = async () => {
|
||||||
|
if (noteToDelete) {
|
||||||
|
setIsDisableDeleteBtn(true)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Xdelete(
|
||||||
|
deleteNote,
|
||||||
|
{ id: noteToDelete.id, month: noteToDelete.month, year: date.year },
|
||||||
|
getLeaveList,
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
} finally {
|
||||||
|
setIsDisableDeleteBtn(false)
|
||||||
|
closeDetailOff()
|
||||||
|
setIsDeleteConfirmOpen(false)
|
||||||
|
setNoteToDelete(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getMonthNames() {
|
function getMonthNames() {
|
||||||
const monthNames = [
|
const monthNames = [
|
||||||
{
|
{
|
||||||
|
|
@ -831,7 +928,12 @@ const LeaveManagement = () => {
|
||||||
</Table.Td>
|
</Table.Td>
|
||||||
|
|
||||||
{/* Off */}
|
{/* Off */}
|
||||||
<Table.Td>
|
<Table.Td
|
||||||
|
onClick={() => {
|
||||||
|
openDetailOff()
|
||||||
|
setDetailOffItem(user)
|
||||||
|
}}
|
||||||
|
>
|
||||||
{totalDayOff > 0 ? (
|
{totalDayOff > 0 ? (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
multiline
|
multiline
|
||||||
|
|
@ -949,6 +1051,248 @@ const LeaveManagement = () => {
|
||||||
</Table.Tbody>
|
</Table.Tbody>
|
||||||
</Table>
|
</Table>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
opened={openedDetailOff}
|
||||||
|
onClose={() => {
|
||||||
|
closeDetailOff()
|
||||||
|
setDetailOffItem({
|
||||||
|
user: {
|
||||||
|
id: 0,
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
email_verified_at: '',
|
||||||
|
permission: '',
|
||||||
|
remember_token: '',
|
||||||
|
avatar: '',
|
||||||
|
created_at: '',
|
||||||
|
updated_at: '',
|
||||||
|
},
|
||||||
|
leaveDay: {
|
||||||
|
id: 0,
|
||||||
|
ld_user_id: 0,
|
||||||
|
ld_year: 0,
|
||||||
|
ld_day_total: 0,
|
||||||
|
ld_additional_day: 0,
|
||||||
|
ld_special_leave_day: 0,
|
||||||
|
ld_note: '',
|
||||||
|
created_at: '',
|
||||||
|
updated_at: '',
|
||||||
|
},
|
||||||
|
monthlyLeaveDays: [],
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
title={
|
||||||
|
<Stack>
|
||||||
|
<Text size="lg" fw={600}>
|
||||||
|
Chi tiết nghỉ phép {date.year}
|
||||||
|
</Text>
|
||||||
|
<Text size="md" c="dimmed">
|
||||||
|
Nhân viên:{' '}
|
||||||
|
<Text span fw={700} c="dark">
|
||||||
|
{detailOffItem.user.name}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
|
size="70%"
|
||||||
|
>
|
||||||
|
<Table striped highlightOnHover withTableBorder withColumnBorders>
|
||||||
|
<Table.Thead>
|
||||||
|
<Table.Tr>
|
||||||
|
<Table.Th>Time</Table.Th>
|
||||||
|
<Table.Th>Status</Table.Th>
|
||||||
|
<Table.Th>Action</Table.Th>
|
||||||
|
</Table.Tr>
|
||||||
|
</Table.Thead>
|
||||||
|
|
||||||
|
<Table.Tbody>
|
||||||
|
{detailOffItem.monthlyLeaveDays
|
||||||
|
.slice()
|
||||||
|
.reverse()
|
||||||
|
.map((item: MonthlyLeaveDays) => {
|
||||||
|
return (
|
||||||
|
<Table.Tr key={item.id}>
|
||||||
|
<Table.Td>
|
||||||
|
{item.time_type_name} ({item.day}/{item.month})
|
||||||
|
</Table.Td>
|
||||||
|
<Table.Td>
|
||||||
|
<Badge
|
||||||
|
color={
|
||||||
|
item.reason_code === 'ONLEAVE'
|
||||||
|
? 'teal'
|
||||||
|
: item.reason_code === 'LEAVE_WITHOUT_PAY'
|
||||||
|
? 'red'
|
||||||
|
: 'blue'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.reason_name}
|
||||||
|
</Badge>
|
||||||
|
</Table.Td>
|
||||||
|
<Table.Td>
|
||||||
|
{item.reason_code === 'ONLEAVE' ? (
|
||||||
|
<IconRefresh
|
||||||
|
className={classes.deleteIcon}
|
||||||
|
onClick={() => {
|
||||||
|
setIsStatusConfirmOpen(true)
|
||||||
|
setNoteStatus({
|
||||||
|
id: item.id,
|
||||||
|
reason: 'LEAVE_WITHOUT_PAY',
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
title="Chuyển thành không phép"
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
) : item.reason_code === 'LEAVE_WITHOUT_PAY' ? (
|
||||||
|
<IconRefresh
|
||||||
|
className={classes.editIcon}
|
||||||
|
onClick={() => {
|
||||||
|
setIsStatusConfirmOpen(true)
|
||||||
|
setNoteStatus({
|
||||||
|
id: item.id,
|
||||||
|
reason: 'ONLEAVE',
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
title="Chuyển thành có phép"
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
|
||||||
|
<IconTrash
|
||||||
|
className={classes.deleteIcon}
|
||||||
|
onClick={() => {
|
||||||
|
setNoteToDelete(item)
|
||||||
|
setIsDeleteConfirmOpen(true)
|
||||||
|
}}
|
||||||
|
title="Xóa Note"
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
</Table.Td>
|
||||||
|
</Table.Tr>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Table.Tbody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
{/* Confirm Change Status Note Modal */}
|
||||||
|
<Modal
|
||||||
|
opened={isStatusConfirmOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsStatusConfirmOpen(false)
|
||||||
|
setNoteStatus({
|
||||||
|
id: 0,
|
||||||
|
reason: '',
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
centered
|
||||||
|
size="sm"
|
||||||
|
classNames={{
|
||||||
|
content: classes.deleteModal,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text className={classes.deleteModalTitle} c="dark">
|
||||||
|
Confirm Change Note Status
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{noteStatus.reason === 'ONLEAVE' ? (
|
||||||
|
<Text className={classes.deleteModalContent}>
|
||||||
|
This action will change the note status from{' '}
|
||||||
|
<Text span c="red" fw="bold">
|
||||||
|
Không phép
|
||||||
|
</Text>{' '}
|
||||||
|
to{' '}
|
||||||
|
<Text span c="teal" fw="bold">
|
||||||
|
Nghỉ phép
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
<Text className={classes.deleteModalContent}>
|
||||||
|
This action will change the note status from{' '}
|
||||||
|
<Text span c="teal" fw="bold">
|
||||||
|
Nghỉ phép
|
||||||
|
</Text>{' '}
|
||||||
|
to{' '}
|
||||||
|
<Text span c="red" fw="bold">
|
||||||
|
Không phép
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Text className={classes.deleteModalContent}>
|
||||||
|
Are you sure you want to proceed?
|
||||||
|
</Text>
|
||||||
|
<Box className={classes.deleteModalFooter}>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => {
|
||||||
|
setIsStatusConfirmOpen(false)
|
||||||
|
setNoteStatus({
|
||||||
|
id: 0,
|
||||||
|
reason: '',
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
disabled={isDisableStatusBtn}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className={classes.deleteButton}
|
||||||
|
onClick={updateNote}
|
||||||
|
disabled={isDisableStatusBtn}
|
||||||
|
bg={noteStatus.reason === 'ONLEAVE' ? 'teal' : 'red'}
|
||||||
|
>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
{/* Confirm Delete Note Modal */}
|
||||||
|
<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}>
|
||||||
|
This action will change the ticket status to{' '}
|
||||||
|
<strong>Refused</strong> and delete all related notes.
|
||||||
|
</Text>
|
||||||
|
<Text className={classes.deleteModalContent}>
|
||||||
|
Are you sure you want to proceed?
|
||||||
|
</Text>
|
||||||
|
<Box className={classes.deleteModalFooter}>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => {
|
||||||
|
setIsDeleteConfirmOpen(false)
|
||||||
|
setNoteToDelete(null)
|
||||||
|
}}
|
||||||
|
disabled={isDisableDeleteBtn}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className={classes.deleteButton}
|
||||||
|
onClick={handleDeleteNote}
|
||||||
|
disabled={isDisableDeleteBtn}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -498,7 +498,7 @@ const TicketsManagement = () => {
|
||||||
setDisableBtn(true)
|
setDisableBtn(true)
|
||||||
|
|
||||||
if (action === 'update') {
|
if (action === 'update') {
|
||||||
if (values.status === 'REFUSED') {
|
if (values.status === 'REFUSED' && item.status !== 'REFUSED') {
|
||||||
setIsRefuseConfirmOpen(true)
|
setIsRefuseConfirmOpen(true)
|
||||||
} else {
|
} else {
|
||||||
await handleUpdate(values)
|
await handleUpdate(values)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue