commit
						824b2fd87c
					
				| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Modules\Admin\app\Http\Controllers;
 | 
					namespace Modules\Admin\app\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Exports\LeaveManagementExport;
 | 
				
			||||||
use App\Http\Controllers\Controller;
 | 
					use App\Http\Controllers\Controller;
 | 
				
			||||||
use App\Jobs\InitializeLeaveDays;
 | 
					use App\Jobs\InitializeLeaveDays;
 | 
				
			||||||
use App\Models\LeaveDays;
 | 
					use App\Models\LeaveDays;
 | 
				
			||||||
| 
						 | 
					@ -9,6 +10,7 @@ use App\Models\Notes;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
use Illuminate\Support\Facades\DB;
 | 
					use Illuminate\Support\Facades\DB;
 | 
				
			||||||
use Illuminate\Support\Facades\Validator;
 | 
					use Illuminate\Support\Facades\Validator;
 | 
				
			||||||
 | 
					use Maatwebsite\Excel\Facades\Excel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LeaveManagementController extends Controller
 | 
					class LeaveManagementController extends Controller
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -139,4 +141,20 @@ class LeaveManagementController extends Controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return response()->json(['status' => true, 'message' => 'Updated successfully']);
 | 
					        return response()->json(['status' => true, 'message' => 'Updated successfully']);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function export(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $year = $request->query('year', now()->year);
 | 
				
			||||||
 | 
					        $leaveDays = $this->getDataByYear($year);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($leaveDays->isEmpty()) {
 | 
				
			||||||
 | 
					            return response()->json(['status' => false, 'message' => 'No data found']);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $currentDate = date('d_His');
 | 
				
			||||||
 | 
					        return Excel::download(
 | 
				
			||||||
 | 
					            new LeaveManagementExport($leaveDays),
 | 
				
			||||||
 | 
					            "LeaveManagement_{$year}_{$currentDate}.xlsx"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,8 @@ use Illuminate\Support\Facades\DB;
 | 
				
			||||||
use Modules\Admin\app\Models\Admin;
 | 
					use Modules\Admin\app\Models\Admin;
 | 
				
			||||||
use Modules\Admin\app\Models\MonthlyTimekeeping;
 | 
					use Modules\Admin\app\Models\MonthlyTimekeeping;
 | 
				
			||||||
use Modules\Admin\app\Models\Tracking;
 | 
					use Modules\Admin\app\Models\Tracking;
 | 
				
			||||||
 | 
					use Maatwebsite\Excel\Facades\Excel;
 | 
				
			||||||
 | 
					use App\Exports\TimekeepingExport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TimekeepingController extends Controller
 | 
					class TimekeepingController extends Controller
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -149,7 +151,7 @@ class TimekeepingController extends Controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return response()->json(['status' => true, 'message' => 'Add successfully']);
 | 
					        return response()->json(['status' => true, 'message' => 'Add successfully']);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function updateCacheMonth(Request $request)
 | 
					    public function updateCacheMonth(Request $request)
 | 
				
			||||||
| 
						 | 
					@ -185,4 +187,38 @@ class TimekeepingController extends Controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return response()->json(['message' => 'Delete fail', 'status' => false]);
 | 
					        return response()->json(['message' => 'Delete fail', 'status' => false]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function export(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Validate request
 | 
				
			||||||
 | 
					        $request->validate([
 | 
				
			||||||
 | 
					            'month' => 'required|numeric|between:1,12',
 | 
				
			||||||
 | 
					            'year' => 'required|numeric|min:2000',
 | 
				
			||||||
 | 
					            'working_days' => 'required|numeric|between:1,31'
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Reuse get() function to fetch data
 | 
				
			||||||
 | 
					        $response = $this->get($request);
 | 
				
			||||||
 | 
					        $responseData = json_decode($response->getContent(), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!$responseData['status']) {
 | 
				
			||||||
 | 
					            return response()->json(['status' => false, 'message' => 'No data found']);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Lọc chỉ lấy user có permission staff
 | 
				
			||||||
 | 
					        $staffData = array_filter($responseData['data'], function($user) {
 | 
				
			||||||
 | 
					            return isset($user['user']['permission']) && $user['user']['permission'] === 'staff';
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $currentDate = date('d_His');
 | 
				
			||||||
 | 
					        return Excel::download(
 | 
				
			||||||
 | 
					            new TimekeepingExport(
 | 
				
			||||||
 | 
					                array_values($staffData), // Convert to indexed array after filtering
 | 
				
			||||||
 | 
					                $request->month,
 | 
				
			||||||
 | 
					                $request->year,
 | 
				
			||||||
 | 
					                $request->working_days
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            "Timekeeping_{$request->month}_{$request->year}_{$currentDate}.xlsx"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,6 +126,7 @@ Route::middleware('api')
 | 
				
			||||||
                Route::get('/delete', [TimekeepingController::class, 'deleteNote'])->middleware('check.permission:admin.hr');
 | 
					                Route::get('/delete', [TimekeepingController::class, 'deleteNote'])->middleware('check.permission:admin.hr');
 | 
				
			||||||
                Route::post('/update-cache-month', [TimekeepingController::class, 'updateCacheMonth'])->middleware('check.permission:admin');
 | 
					                Route::post('/update-cache-month', [TimekeepingController::class, 'updateCacheMonth'])->middleware('check.permission:admin');
 | 
				
			||||||
                Route::post('/update-working-days', [TimekeepingController::class, 'saveWorkingDays'])->middleware('check.permission:admin.hr');
 | 
					                Route::post('/update-working-days', [TimekeepingController::class, 'saveWorkingDays'])->middleware('check.permission:admin.hr');
 | 
				
			||||||
 | 
					                Route::get('/export', [TimekeepingController::class, 'export'])->middleware('check.permission:admin.hr.staff.accountant');
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Route::group([
 | 
					            Route::group([
 | 
				
			||||||
| 
						 | 
					@ -146,6 +147,7 @@ Route::middleware('api')
 | 
				
			||||||
                'prefix' => 'leave-management',
 | 
					                'prefix' => 'leave-management',
 | 
				
			||||||
            ], function () {
 | 
					            ], function () {
 | 
				
			||||||
                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::post('/saveNoteLeave', [LeaveManagementController::class, 'saveNoteLeave'])->middleware('check.permission:admin.hr');
 | 
					                Route::post('/saveNoteLeave', [LeaveManagementController::class, 'saveNoteLeave'])->middleware('check.permission:admin.hr');
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,134 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Exports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Carbon\Carbon;
 | 
				
			||||||
 | 
					use Maatwebsite\Excel\Concerns\FromArray;
 | 
				
			||||||
 | 
					use Maatwebsite\Excel\Concerns\WithHeadings;
 | 
				
			||||||
 | 
					use Maatwebsite\Excel\Concerns\WithStyles;
 | 
				
			||||||
 | 
					use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
 | 
				
			||||||
 | 
					use PhpOffice\PhpSpreadsheet\Style\Border;
 | 
				
			||||||
 | 
					use PhpOffice\PhpSpreadsheet\Style\Alignment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LeaveManagementExport implements FromArray, WithHeadings, WithStyles
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $data;
 | 
				
			||||||
 | 
					    protected $year;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct($data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->data = $data;
 | 
				
			||||||
 | 
					        $this->year = Carbon::now()->year;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function headings(): array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
 | 
				
			||||||
 | 
					        return array_merge(
 | 
				
			||||||
 | 
					            ['No.', 'User'],
 | 
				
			||||||
 | 
					            $months,
 | 
				
			||||||
 | 
					            ['Total', 'Off', 'Remaining', 'Notes']
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function array(): array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $headers = $this->headings(); // Lấy tiêu đề
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $rows = [];
 | 
				
			||||||
 | 
					        foreach ($this->data as $index => $user) {
 | 
				
			||||||
 | 
					            $totalDayOff = 0;
 | 
				
			||||||
 | 
					            $totalDayLeave = $user['leaveDay']['ld_day'] + $user['leaveDay']['ld_date_additional'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Tính tổng ngày nghỉ theo tháng
 | 
				
			||||||
 | 
					            $monthlyLeaves = array_fill(1, 12, 0);
 | 
				
			||||||
 | 
					            foreach ($user['monthlyLeaveDays'] as $leaveDay) {
 | 
				
			||||||
 | 
					                $monthlyLeaves[$leaveDay['month']] += $leaveDay['leave_days'];
 | 
				
			||||||
 | 
					                $totalDayOff += $leaveDay['leave_days'];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Tạo dòng dữ liệu
 | 
				
			||||||
 | 
					            $row = [
 | 
				
			||||||
 | 
					                $index + 1,
 | 
				
			||||||
 | 
					                $user['user']['name']
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Thêm dữ liệu các tháng
 | 
				
			||||||
 | 
					            for ($month = 1; $month <= 12; $month++) {
 | 
				
			||||||
 | 
					                $row[] = $monthlyLeaves[$month] ?: '';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Thêm tổng số ngày
 | 
				
			||||||
 | 
					            $row[] = $totalDayLeave;
 | 
				
			||||||
 | 
					            $row[] = $totalDayOff;
 | 
				
			||||||
 | 
					            $row[] = $totalDayLeave - $totalDayOff;
 | 
				
			||||||
 | 
					            $row[] = $user['leaveDay']['ld_note'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $rows[] = $row;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return array_merge([$headers], $rows); // Thêm tiêu đề vào đầu mảng
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function styles(Worksheet $sheet)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $lastRow = count($this->data) + 2;
 | 
				
			||||||
 | 
					        $lastColumn = 'R';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Thêm và style title
 | 
				
			||||||
 | 
					        $sheet->mergeCells("A1:{$lastColumn}1");
 | 
				
			||||||
 | 
					        $sheet->setCellValue('A1', "DANH SÁCH NGÀY NGHỈ NĂM {$this->year}");
 | 
				
			||||||
 | 
					        $sheet->getStyle("A1:{$lastColumn}1")->applyFromArray([
 | 
				
			||||||
 | 
					            'font' => [
 | 
				
			||||||
 | 
					                'bold' => true,
 | 
				
			||||||
 | 
					                'size' => 14
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'alignment' => [
 | 
				
			||||||
 | 
					                'horizontal' => Alignment::HORIZONTAL_CENTER,
 | 
				
			||||||
 | 
					                'vertical' => Alignment::VERTICAL_CENTER
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Style cho header (dời xuống row 2)
 | 
				
			||||||
 | 
					        $sheet->getStyle("A2:{$lastColumn}2")->applyFromArray([
 | 
				
			||||||
 | 
					            'font' => ['bold' => true],
 | 
				
			||||||
 | 
					            'alignment' => [
 | 
				
			||||||
 | 
					                'horizontal' => Alignment::HORIZONTAL_CENTER,
 | 
				
			||||||
 | 
					                'vertical' => Alignment::VERTICAL_CENTER
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Style cho toàn bộ bảng (bắt đầu từ row 1)
 | 
				
			||||||
 | 
					        $sheet->getStyle("A1:{$lastColumn}{$lastRow}")->applyFromArray([
 | 
				
			||||||
 | 
					            'borders' => [
 | 
				
			||||||
 | 
					                'allBorders' => [
 | 
				
			||||||
 | 
					                    'borderStyle' => Border::BORDER_THIN
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'alignment' => [
 | 
				
			||||||
 | 
					                'vertical' => Alignment::VERTICAL_CENTER
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Căn giữa cho các cột số liệu (điều chỉnh range bắt đầu từ row 3)
 | 
				
			||||||
 | 
					        for ($col = 'C'; $col <= 'P'; $col++) {
 | 
				
			||||||
 | 
					            $sheet->getStyle("{$col}3:{$col}{$lastRow}")
 | 
				
			||||||
 | 
					                ->getAlignment()
 | 
				
			||||||
 | 
					                ->setHorizontal(Alignment::HORIZONTAL_CENTER);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Set độ rộng cột
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('A')->setWidth(5);  // No.
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('B')->setWidth(30); // User
 | 
				
			||||||
 | 
					        // Các tháng
 | 
				
			||||||
 | 
					        for ($i = 'C'; $i <= 'N'; $i++) {
 | 
				
			||||||
 | 
					            $sheet->getColumnDimension($i)->setWidth(8);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('O')->setWidth(8);  // Total
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('P')->setWidth(8);  // Off
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('Q')->setWidth(12); // Remaining
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('R')->setWidth(30); // Notes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $sheet;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					} 
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,184 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Exports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Carbon\Carbon;
 | 
				
			||||||
 | 
					use Maatwebsite\Excel\Concerns\FromArray;
 | 
				
			||||||
 | 
					use Maatwebsite\Excel\Concerns\WithHeadings;
 | 
				
			||||||
 | 
					use Maatwebsite\Excel\Concerns\WithStyles;
 | 
				
			||||||
 | 
					use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
 | 
				
			||||||
 | 
					use PhpOffice\PhpSpreadsheet\Style\Border;
 | 
				
			||||||
 | 
					use PhpOffice\PhpSpreadsheet\Style\Alignment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TimekeepingExport implements FromArray, WithHeadings, WithStyles
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected $data;
 | 
				
			||||||
 | 
					    protected $month;
 | 
				
			||||||
 | 
					    protected $year;
 | 
				
			||||||
 | 
					    protected $workingDays;
 | 
				
			||||||
 | 
					    protected $daysInMonth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct($data, $month, $year, $workingDays)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->data = $data;
 | 
				
			||||||
 | 
					        $this->month = $month;
 | 
				
			||||||
 | 
					        $this->year = $year;
 | 
				
			||||||
 | 
					        $this->workingDays = $workingDays;
 | 
				
			||||||
 | 
					        $this->daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function array(): array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Lấy headers
 | 
				
			||||||
 | 
					        $headers = $this->headings();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Lấy dữ liệu người dùng
 | 
				
			||||||
 | 
					        $userRows = [];
 | 
				
			||||||
 | 
					        foreach ($this->data as $user) {
 | 
				
			||||||
 | 
					            // Kiểm tra permission staff
 | 
				
			||||||
 | 
					            if (!isset($user['user']['permission']) || $user['user']['permission'] !== 'staff') {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $row = [
 | 
				
			||||||
 | 
					                $user['user']['name'] ?? 'Unknown',
 | 
				
			||||||
 | 
					                0, // Total days
 | 
				
			||||||
 | 
					                $this->workingDays, // Off days (initialize with working days)
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $totalDays = 0;
 | 
				
			||||||
 | 
					            // Add data for each day in month
 | 
				
			||||||
 | 
					            for ($day = 1; $day <= $this->daysInMonth; $day++) {
 | 
				
			||||||
 | 
					                $dayData = '';
 | 
				
			||||||
 | 
					                if (isset($user['history'])) {
 | 
				
			||||||
 | 
					                    foreach ($user['history'] as $history) {
 | 
				
			||||||
 | 
					                        if ($history['day'] === $day) {
 | 
				
			||||||
 | 
					                            $total = $history['total'] ?? 0;
 | 
				
			||||||
 | 
					                            if ($total >= 7 * 3600) {
 | 
				
			||||||
 | 
					                                $dayData = '1';
 | 
				
			||||||
 | 
					                                $totalDays += 1;
 | 
				
			||||||
 | 
					                            } else if ($total >= 3.5 * 3600) {
 | 
				
			||||||
 | 
					                                $dayData = '0.5';
 | 
				
			||||||
 | 
					                                $totalDays += 0.5;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                $row[] = $dayData;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Update total and off days
 | 
				
			||||||
 | 
					            $row[1] = $totalDays;
 | 
				
			||||||
 | 
					            $row[2] = $this->workingDays - $totalDays;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Add Notes column with formatted content
 | 
				
			||||||
 | 
					            $notes = [];
 | 
				
			||||||
 | 
					            if (isset($user['history'])) {
 | 
				
			||||||
 | 
					                foreach ($user['history'] as $history) {
 | 
				
			||||||
 | 
					                    if (!empty($history['notes'])) {
 | 
				
			||||||
 | 
					                        $dayNotes = [];
 | 
				
			||||||
 | 
					                        foreach ($history['notes'] as $note) {
 | 
				
			||||||
 | 
					                            $dayNotes[] = "- {$note['reasonName']} ({$note['timeTypeName']}): {$note['note']}";
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        if (!empty($dayNotes)) {
 | 
				
			||||||
 | 
					                            $notes[] = "Day {$history['day']}:\n" . implode("\n", $dayNotes);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $row[] = !empty($notes) ? implode("\n\n", $notes) : '';
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            $userRows[] = $row;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return array_merge($headers, $userRows);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function headings(): array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $firstRow = ['Day', '', ''];
 | 
				
			||||||
 | 
					        // Second row: Day of week
 | 
				
			||||||
 | 
					        $secondRow = ['', '', ''];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $date = Carbon::create($this->year, $this->month, 1);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        for ($day = 1; $day <= $this->daysInMonth; $day++) {
 | 
				
			||||||
 | 
					            $firstRow[] = $day;
 | 
				
			||||||
 | 
					            $secondRow[] = $date->format('D');
 | 
				
			||||||
 | 
					            $date->addDay();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Add Notes column
 | 
				
			||||||
 | 
					        $firstRow[] = 'Notes';
 | 
				
			||||||
 | 
					        $secondRow[] = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [$firstRow, $secondRow];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function styles(Worksheet $sheet)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $lastColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($this->daysInMonth + 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Title and working days
 | 
				
			||||||
 | 
					        $sheet->mergeCells("A1:{$lastColumn}1");
 | 
				
			||||||
 | 
					        $sheet->setCellValue('A1', "DANH SÁCH CHẤM CÔNG THÁNG {$this->month} NĂM {$this->year}");
 | 
				
			||||||
 | 
					        $sheet->mergeCells("A2:{$lastColumn}2");
 | 
				
			||||||
 | 
					        $sheet->setCellValue('A2', "Số ngày làm việc: {$this->workingDays}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Merge cells for "Day" title and set value
 | 
				
			||||||
 | 
					        $sheet->mergeCells("A3:C3");
 | 
				
			||||||
 | 
					        $sheet->setCellValue('A3', 'Day');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Set values for A4, B4, C4
 | 
				
			||||||
 | 
					        $sheet->setCellValue('A4', 'User');
 | 
				
			||||||
 | 
					        $sheet->setCellValue('B4', 'Total');
 | 
				
			||||||
 | 
					        $sheet->setCellValue('C4', 'Off');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Calculate last row (2 title rows + 2 header rows + data rows)
 | 
				
			||||||
 | 
					        $lastRow = count($this->data) + 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Styling
 | 
				
			||||||
 | 
					        $sheet->getStyle("A1:{$lastColumn}1")->getFont()->setBold(true)->setSize(14);
 | 
				
			||||||
 | 
					        $sheet->getStyle("A2:{$lastColumn}2")->getFont()->setBold(true);
 | 
				
			||||||
 | 
					        $sheet->getStyle("A3:{$lastColumn}4")->getFont()->setBold(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Border style
 | 
				
			||||||
 | 
					        $borderStyle = [
 | 
				
			||||||
 | 
					            'borders' => [
 | 
				
			||||||
 | 
					                'allBorders' => [
 | 
				
			||||||
 | 
					                    'borderStyle' => Border::BORDER_THIN,
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Apply borders to the data area
 | 
				
			||||||
 | 
					        $sheet->getStyle("A1:{$lastColumn}{$lastRow}")->applyFromArray($borderStyle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Center align all cells except Notes column
 | 
				
			||||||
 | 
					        $sheet->getStyle("A1:{$lastColumn}{$lastRow}")
 | 
				
			||||||
 | 
					            ->getAlignment()
 | 
				
			||||||
 | 
					            ->setHorizontal(Alignment::HORIZONTAL_CENTER)
 | 
				
			||||||
 | 
					            ->setVertical(Alignment::VERTICAL_CENTER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Left align Notes column
 | 
				
			||||||
 | 
					        $noteColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($this->daysInMonth + 4);
 | 
				
			||||||
 | 
					        $sheet->getStyle("{$noteColumn}5:{$noteColumn}{$lastRow}")
 | 
				
			||||||
 | 
					            ->getAlignment()
 | 
				
			||||||
 | 
					            ->setHorizontal(Alignment::HORIZONTAL_LEFT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Set column widths
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('A')->setWidth(30);
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('B')->setWidth(10);
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension('C')->setWidth(10);
 | 
				
			||||||
 | 
					        for ($i = 4; $i <= $this->daysInMonth + 3; $i++) {
 | 
				
			||||||
 | 
					            $sheet->getColumnDimension(\PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i))->setWidth(5);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Set width for Note column
 | 
				
			||||||
 | 
					        $sheet->getColumnDimension($noteColumn)->setWidth(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					} 
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -20,6 +20,7 @@ export const getDetailIssByKey = API_URL + 'v1/admin/jira/issue/detail'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//Timekeeping
 | 
					//Timekeeping
 | 
				
			||||||
export const getTheTimesheet = API_URL + 'v1/admin/timekeeping'
 | 
					export const getTheTimesheet = API_URL + 'v1/admin/timekeeping'
 | 
				
			||||||
 | 
					export const exportTimekeeping = API_URL + 'v1/admin/timekeeping/export'
 | 
				
			||||||
export const updateMultipleUserWorkingTime =
 | 
					export const updateMultipleUserWorkingTime =
 | 
				
			||||||
  API_URL + 'v1/admin/timekeeping/addMutilple'
 | 
					  API_URL + 'v1/admin/timekeeping/addMutilple'
 | 
				
			||||||
export const updateNote = API_URL + 'v1/admin/timekeeping/addNote'
 | 
					export const updateNote = API_URL + 'v1/admin/timekeeping/addNote'
 | 
				
			||||||
| 
						 | 
					@ -36,6 +37,7 @@ 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 exportLeaveManagement = API_URL + 'v1/admin/leave-management/export'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//Tickets
 | 
					//Tickets
 | 
				
			||||||
export const getTickets = API_URL + 'v1/admin/ticket/all'
 | 
					export const getTickets = API_URL + 'v1/admin/ticket/all'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
import { getLeaveManagement, updateNoteLeave } from '@/api/Admin'
 | 
					import { getLeaveManagement, updateNoteLeave, exportLeaveManagement } from '@/api/Admin'
 | 
				
			||||||
import { update } from '@/rtk/helpers/CRUD'
 | 
					import { update } from '@/rtk/helpers/CRUD'
 | 
				
			||||||
import { get } from '@/rtk/helpers/apiService'
 | 
					import { get, exportFile } from '@/rtk/helpers/apiService'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Avatar,
 | 
					  Avatar,
 | 
				
			||||||
  Box,
 | 
					  Box,
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ import { notifications } from '@mantine/notifications'
 | 
				
			||||||
import moment from 'moment'
 | 
					import moment from 'moment'
 | 
				
			||||||
import { useEffect, useState } from 'react'
 | 
					import { useEffect, useState } from 'react'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { IconEdit } from '@tabler/icons-react'
 | 
					import { IconEdit, IconFileExcel } from '@tabler/icons-react'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import classes from './LeaveManagement.module.css'
 | 
					import classes from './LeaveManagement.module.css'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -245,6 +245,29 @@ const LeaveManagement = () => {
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleExport = async () => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const timestamp = moment().format('DDMMYYYY_HHmmss')
 | 
				
			||||||
 | 
					      const fileName = `LeaveManagement_${date.year}_${timestamp}.xlsx`
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      await exportFile(
 | 
				
			||||||
 | 
					        exportLeaveManagement,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          year: parseInt(date.year)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        fileName
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      console.error('Export error:', error)
 | 
				
			||||||
 | 
					      notifications.show({
 | 
				
			||||||
 | 
					        title: 'Error',
 | 
				
			||||||
 | 
					        message: 'Export failed',
 | 
				
			||||||
 | 
					        color: 'red',
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
      <div className={classes.title}>
 | 
					      <div className={classes.title}>
 | 
				
			||||||
| 
						 | 
					@ -391,22 +414,18 @@ const LeaveManagement = () => {
 | 
				
			||||||
          pl={200}
 | 
					          pl={200}
 | 
				
			||||||
          style={{
 | 
					          style={{
 | 
				
			||||||
            display: 'flex',
 | 
					            display: 'flex',
 | 
				
			||||||
            // alignItems: 'end',
 | 
					 | 
				
			||||||
            justifyContent: 'end',
 | 
					            justifyContent: 'end',
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          <Box display={'flex'} style={{ alignItems: 'end' }}>
 | 
					          <Box display={'flex'} style={{ alignItems: 'end' }}>
 | 
				
			||||||
            {/* <Tooltip label="Save working days">
 | 
					            <Button
 | 
				
			||||||
              <Button
 | 
					              size="xs"
 | 
				
			||||||
                size="xs"
 | 
					              ml={'sm'}
 | 
				
			||||||
                ml={'sm'}
 | 
					              onClick={handleExport}
 | 
				
			||||||
                onClick={() => {
 | 
					              leftSection={<IconFileExcel size={16} />}
 | 
				
			||||||
                  //form add user new
 | 
					            >
 | 
				
			||||||
                }}
 | 
					              Export Excel
 | 
				
			||||||
              >
 | 
					            </Button>
 | 
				
			||||||
                Add
 | 
					 | 
				
			||||||
              </Button>
 | 
					 | 
				
			||||||
            </Tooltip> */}
 | 
					 | 
				
			||||||
          </Box>
 | 
					          </Box>
 | 
				
			||||||
        </Box>
 | 
					        </Box>
 | 
				
			||||||
      </Box>
 | 
					      </Box>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  deleteNote,
 | 
					  deleteNote,
 | 
				
			||||||
 | 
					  exportTimekeeping,
 | 
				
			||||||
  getListMaster,
 | 
					  getListMaster,
 | 
				
			||||||
  getTheTimesheet,
 | 
					  getTheTimesheet,
 | 
				
			||||||
  updateMultipleUserWorkingTime,
 | 
					  updateMultipleUserWorkingTime,
 | 
				
			||||||
| 
						 | 
					@ -7,7 +8,7 @@ import {
 | 
				
			||||||
  updateWorkingDays,
 | 
					  updateWorkingDays,
 | 
				
			||||||
} from '@/api/Admin'
 | 
					} from '@/api/Admin'
 | 
				
			||||||
import { update, Xdelete } from '@/rtk/helpers/CRUD'
 | 
					import { update, Xdelete } from '@/rtk/helpers/CRUD'
 | 
				
			||||||
import { get } from '@/rtk/helpers/apiService'
 | 
					import { exportFile, get } from '@/rtk/helpers/apiService'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Avatar,
 | 
					  Avatar,
 | 
				
			||||||
  Box,
 | 
					  Box,
 | 
				
			||||||
| 
						 | 
					@ -31,6 +32,7 @@ import {
 | 
				
			||||||
  IconPointFilled,
 | 
					  IconPointFilled,
 | 
				
			||||||
  IconTrash,
 | 
					  IconTrash,
 | 
				
			||||||
  IconX,
 | 
					  IconX,
 | 
				
			||||||
 | 
					  IconFileExcel,
 | 
				
			||||||
} from '@tabler/icons-react'
 | 
					} from '@tabler/icons-react'
 | 
				
			||||||
import moment from 'moment'
 | 
					import moment from 'moment'
 | 
				
			||||||
import { useEffect, useState } from 'react'
 | 
					import { useEffect, useState } from 'react'
 | 
				
			||||||
| 
						 | 
					@ -435,12 +437,29 @@ const Timekeeping = () => {
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleExport = async () => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const timestamp = moment().format('DDMMYYYY_HHmmss')
 | 
				
			||||||
 | 
					      const fileName = `Timekeeping_${date.month}_${date.year}_${timestamp}.xlsx`
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      await exportFile(
 | 
				
			||||||
 | 
					        exportTimekeeping,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          month: date.month,
 | 
				
			||||||
 | 
					          year: date.year,
 | 
				
			||||||
 | 
					          working_days: workingDays
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        fileName
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      console.error('Export error:', error)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
      <div className={classes.title}>
 | 
					      <div className={classes.title}>
 | 
				
			||||||
        <h3>
 | 
					        <h3>Timekeeping</h3>
 | 
				
			||||||
          Timekeeping
 | 
					 | 
				
			||||||
        </h3>
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <Drawer
 | 
					      <Drawer
 | 
				
			||||||
        opened={opened1}
 | 
					        opened={opened1}
 | 
				
			||||||
| 
						 | 
					@ -511,7 +530,6 @@ const Timekeeping = () => {
 | 
				
			||||||
          <span style={{ paddingLeft: '10px', paddingRight: '10px' }}>|</span>
 | 
					          <span style={{ paddingLeft: '10px', paddingRight: '10px' }}>|</span>
 | 
				
			||||||
          <span style={{ fontWeight: 'bold' }}>Day</span>: {customAddNotes.day}
 | 
					          <span style={{ fontWeight: 'bold' }}>Day</span>: {customAddNotes.day}
 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
 | 
					 | 
				
			||||||
        <Select
 | 
					        <Select
 | 
				
			||||||
          mb={'md'}
 | 
					          mb={'md'}
 | 
				
			||||||
          searchable
 | 
					          searchable
 | 
				
			||||||
| 
						 | 
					@ -688,6 +706,14 @@ const Timekeeping = () => {
 | 
				
			||||||
                Save
 | 
					                Save
 | 
				
			||||||
              </Button>
 | 
					              </Button>
 | 
				
			||||||
            </Tooltip>
 | 
					            </Tooltip>
 | 
				
			||||||
 | 
					            <Button 
 | 
				
			||||||
 | 
					              onClick={handleExport} 
 | 
				
			||||||
 | 
					              size="xs" 
 | 
				
			||||||
 | 
					              ml="xl"
 | 
				
			||||||
 | 
					              leftSection={<IconFileExcel size={16} />}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              Export Excel
 | 
				
			||||||
 | 
					            </Button>
 | 
				
			||||||
          </Box>
 | 
					          </Box>
 | 
				
			||||||
        </Box>
 | 
					        </Box>
 | 
				
			||||||
        <Box
 | 
					        <Box
 | 
				
			||||||
| 
						 | 
					@ -866,13 +892,22 @@ const Timekeeping = () => {
 | 
				
			||||||
                      // offset={{ mainAxis: 5, crossAxis: 0 }}
 | 
					                      // offset={{ mainAxis: 5, crossAxis: 0 }}
 | 
				
			||||||
                      label={showTooltipAllNote(user)}
 | 
					                      label={showTooltipAllNote(user)}
 | 
				
			||||||
                    >
 | 
					                    >
 | 
				
			||||||
                      <div style={{display:'flex', alignItems:'center'}}><Avatar size={'md'} mr={'md'} src={import.meta.env.VITE_BACKEND_URL.includes('local')
 | 
					                      <div style={{ display: 'flex', alignItems: 'center' }}>
 | 
				
			||||||
                          ? import.meta.env.VITE_BACKEND_URL +
 | 
					                        <Avatar
 | 
				
			||||||
                            'storage/' +
 | 
					                          size={'md'}
 | 
				
			||||||
                           user.user.avatar
 | 
					                          mr={'md'}
 | 
				
			||||||
                          : import.meta.env.VITE_BACKEND_URL +
 | 
					                          src={
 | 
				
			||||||
                            'image/storage/' +
 | 
					                            import.meta.env.VITE_BACKEND_URL.includes('local')
 | 
				
			||||||
                           user.user.avatar}/>{user.user.name}</div>
 | 
					                              ? import.meta.env.VITE_BACKEND_URL +
 | 
				
			||||||
 | 
					                                'storage/' +
 | 
				
			||||||
 | 
					                                user.user.avatar
 | 
				
			||||||
 | 
					                              : import.meta.env.VITE_BACKEND_URL +
 | 
				
			||||||
 | 
					                                'image/storage/' +
 | 
				
			||||||
 | 
					                                user.user.avatar
 | 
				
			||||||
 | 
					                          }
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                        {user.user.name}
 | 
				
			||||||
 | 
					                      </div>
 | 
				
			||||||
                    </Tooltip>
 | 
					                    </Tooltip>
 | 
				
			||||||
                  </Table.Td>
 | 
					                  </Table.Td>
 | 
				
			||||||
                  <Table.Td ta={'center'}>{totalDays}</Table.Td>
 | 
					                  <Table.Td ta={'center'}>{totalDays}</Table.Td>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ import { getFormDataHeader, getHeaderInfo } from '@/rtk/helpers/tokenCreator'
 | 
				
			||||||
import { removeTokens } from '@/rtk/localStorage'
 | 
					import { removeTokens } from '@/rtk/localStorage'
 | 
				
			||||||
import { notifications } from '@mantine/notifications'
 | 
					import { notifications } from '@mantine/notifications'
 | 
				
			||||||
import axios from 'axios'
 | 
					import axios from 'axios'
 | 
				
			||||||
 | 
					import moment from 'moment'
 | 
				
			||||||
const handleResponse = (response: any) => {
 | 
					const handleResponse = (response: any) => {
 | 
				
			||||||
  if (response.status === 401) {
 | 
					  if (response.status === 401) {
 | 
				
			||||||
    removeTokens()
 | 
					    removeTokens()
 | 
				
			||||||
| 
						 | 
					@ -156,3 +157,45 @@ export const postImage = async (url: string, body: any, method: any) => {
 | 
				
			||||||
    throw handleResponse(err.response)
 | 
					    throw handleResponse(err.response)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const exportFile = async (url: string, params: any = {}, fileName: string) => {
 | 
				
			||||||
 | 
					  const header = await getHeaderInfo()
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const response = await axios.get(url, {
 | 
				
			||||||
 | 
					      ...header,
 | 
				
			||||||
 | 
					      params,
 | 
				
			||||||
 | 
					      responseType: 'blob'
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (response.status === 200) {
 | 
				
			||||||
 | 
					      const blob = new Blob([response.data])
 | 
				
			||||||
 | 
					      const downloadUrl = window.URL.createObjectURL(blob)
 | 
				
			||||||
 | 
					      const link = document.createElement('a')
 | 
				
			||||||
 | 
					      link.href = downloadUrl
 | 
				
			||||||
 | 
					      link.download = fileName
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      document.body.appendChild(link)
 | 
				
			||||||
 | 
					      link.click()
 | 
				
			||||||
 | 
					      window.URL.revokeObjectURL(downloadUrl)
 | 
				
			||||||
 | 
					      document.body.removeChild(link)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // notifications.show({
 | 
				
			||||||
 | 
					      //   title: 'Success',
 | 
				
			||||||
 | 
					      //   message: 'Export successfully',
 | 
				
			||||||
 | 
					      //   color: 'green',
 | 
				
			||||||
 | 
					      // })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    throw new Error('Export failed')
 | 
				
			||||||
 | 
					  } catch (error: any) {
 | 
				
			||||||
 | 
					    notifications.show({
 | 
				
			||||||
 | 
					      title: 'Error',
 | 
				
			||||||
 | 
					      message: error.message || 'Export failed',
 | 
				
			||||||
 | 
					      color: 'red',
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    throw error
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue