Bổ sung nút report excel trang timekeeping , leave management
This commit is contained in:
parent
93030b73c7
commit
7fdf6f3e25
|
|
@ -151,9 +151,14 @@ class LeaveManagementController extends Controller
|
|||
return response()->json(['status' => false, 'message' => 'No data found']);
|
||||
}
|
||||
|
||||
// Lọc chỉ lấy user có permission bao gồm staff
|
||||
$staffData = $leaveDays->filter(function($user) {
|
||||
return isset($user['user']['permission']) && strpos($user['user']['permission'], 'staff') !== false;
|
||||
});
|
||||
|
||||
$currentDate = date('d_His');
|
||||
return Excel::download(
|
||||
new LeaveManagementExport($leaveDays),
|
||||
new LeaveManagementExport($staffData),
|
||||
"LeaveManagement_{$year}_{$currentDate}.xlsx"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,9 +205,9 @@ class TimekeepingController extends Controller
|
|||
return response()->json(['status' => false, 'message' => 'No data found']);
|
||||
}
|
||||
|
||||
// Lọc chỉ lấy user có permission staff
|
||||
// Lọc chỉ lấy user có permission bao gồm staff
|
||||
$staffData = array_filter($responseData['data'], function($user) {
|
||||
return isset($user['user']['permission']) && $user['user']['permission'] === 'staff';
|
||||
return isset($user['user']['permission']) && strpos($user['user']['permission'], 'staff') !== false;
|
||||
});
|
||||
|
||||
$currentDate = date('d_His');
|
||||
|
|
|
|||
|
|
@ -4,13 +4,15 @@ namespace App\Exports;
|
|||
|
||||
use Carbon\Carbon;
|
||||
use Maatwebsite\Excel\Concerns\FromArray;
|
||||
use Maatwebsite\Excel\Concerns\WithEvents;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||
use Maatwebsite\Excel\Events\AfterSheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
|
||||
class LeaveManagementExport implements FromArray, WithHeadings, WithStyles
|
||||
class LeaveManagementExport implements FromArray, WithHeadings, WithStyles, WithEvents
|
||||
{
|
||||
protected $data;
|
||||
protected $year;
|
||||
|
|
@ -36,6 +38,7 @@ class LeaveManagementExport implements FromArray, WithHeadings, WithStyles
|
|||
$headers = $this->headings(); // Lấy tiêu đề
|
||||
|
||||
$rows = [];
|
||||
$stt = 0;
|
||||
foreach ($this->data as $index => $user) {
|
||||
$totalDayOff = 0;
|
||||
$totalDayLeave = $user['leaveDay']['ld_day'] + $user['leaveDay']['ld_date_additional'];
|
||||
|
|
@ -49,7 +52,7 @@ class LeaveManagementExport implements FromArray, WithHeadings, WithStyles
|
|||
|
||||
// Tạo dòng dữ liệu
|
||||
$row = [
|
||||
$index + 1,
|
||||
$stt + 1,
|
||||
$user['user']['name']
|
||||
];
|
||||
|
||||
|
|
@ -65,11 +68,61 @@ class LeaveManagementExport implements FromArray, WithHeadings, WithStyles
|
|||
$row[] = $user['leaveDay']['ld_note'] ?? '';
|
||||
|
||||
$rows[] = $row;
|
||||
$stt++;
|
||||
}
|
||||
|
||||
return array_merge([$headers], $rows); // Thêm tiêu đề vào đầu mảng
|
||||
}
|
||||
|
||||
public function registerEvents(): array
|
||||
{
|
||||
return [
|
||||
AfterSheet::class => function(AfterSheet $event) {
|
||||
$sheet = $event->sheet->getDelegate();
|
||||
$lastRow = count($this->data) + 2;
|
||||
$noteColumn = 'R'; // Cột Notes
|
||||
|
||||
// Xử lý đặc biệt cho cột Notes
|
||||
$sheet->getStyle("{$noteColumn}3:{$noteColumn}{$lastRow}")
|
||||
->getAlignment()
|
||||
->setWrapText(true)
|
||||
->setVertical(Alignment::VERTICAL_TOP)
|
||||
->setHorizontal(Alignment::HORIZONTAL_LEFT);
|
||||
|
||||
// Tắt auto-size cho cột Notes và set độ rộng cố định
|
||||
$sheet->getColumnDimension($noteColumn)
|
||||
->setAutoSize(false)
|
||||
->setWidth(60);
|
||||
|
||||
// Tự động điều chỉnh chiều cao cho từng dòng có nội dung
|
||||
for ($row = 3; $row <= $lastRow; $row++) {
|
||||
$cellValue = $sheet->getCell($noteColumn . $row)->getValue();
|
||||
if (!empty($cellValue)) {
|
||||
// Tính toán chiều cao dựa trên nội dung
|
||||
$sheet->getRowDimension($row)->setRowHeight(-1);
|
||||
|
||||
// Tính toán lại chiều cao dựa trên số dòng trong nội dung
|
||||
$lineCount = substr_count($cellValue, "\n") + 1;
|
||||
$minHeight = max(30, $lineCount * 15); // 15 pixels cho mỗi dòng
|
||||
|
||||
// Lấy chiều cao hiện tại sau khi auto-size
|
||||
$currentHeight = $sheet->getRowDimension($row)->getRowHeight();
|
||||
|
||||
// Nếu chiều cao tự động nhỏ hơn chiều cao tối thiểu, sử dụng chiều cao tối thiểu
|
||||
if ($currentHeight < $minHeight) {
|
||||
$sheet->getRowDimension($row)->setRowHeight($minHeight);
|
||||
}
|
||||
} else {
|
||||
$sheet->getRowDimension($row)->setRowHeight(30);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh các tính toán của Excel
|
||||
$sheet->calculateColumnWidths();
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
public function styles(Worksheet $sheet)
|
||||
{
|
||||
$lastRow = count($this->data) + 2;
|
||||
|
|
@ -129,6 +182,13 @@ class LeaveManagementExport implements FromArray, WithHeadings, WithStyles
|
|||
$sheet->getColumnDimension('Q')->setWidth(12); // Remaining
|
||||
$sheet->getColumnDimension('R')->setWidth(30); // Notes
|
||||
|
||||
// Điều chỉnh style cho cột Notes
|
||||
$sheet->getStyle("R3:R{$lastRow}")
|
||||
->getAlignment()
|
||||
->setHorizontal(Alignment::HORIZONTAL_LEFT)
|
||||
->setVertical(Alignment::VERTICAL_TOP)
|
||||
->setWrapText(true);
|
||||
|
||||
return $sheet;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,13 +4,15 @@ namespace App\Exports;
|
|||
|
||||
use Carbon\Carbon;
|
||||
use Maatwebsite\Excel\Concerns\FromArray;
|
||||
use Maatwebsite\Excel\Concerns\WithEvents;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||
use Maatwebsite\Excel\Events\AfterSheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
|
||||
class TimekeepingExport implements FromArray, WithHeadings, WithStyles
|
||||
class TimekeepingExport implements FromArray, WithHeadings, WithStyles, WithEvents
|
||||
{
|
||||
protected $data;
|
||||
protected $month;
|
||||
|
|
@ -27,6 +29,55 @@ class TimekeepingExport implements FromArray, WithHeadings, WithStyles
|
|||
$this->daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
|
||||
}
|
||||
|
||||
public function registerEvents(): array
|
||||
{
|
||||
return [
|
||||
AfterSheet::class => function(AfterSheet $event) {
|
||||
$sheet = $event->sheet->getDelegate();
|
||||
$lastRow = count($this->data) + 4;
|
||||
$noteColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($this->daysInMonth + 4);
|
||||
|
||||
// Xử lý đặc biệt cho cột Notes
|
||||
$sheet->getStyle("{$noteColumn}5:{$noteColumn}{$lastRow}")
|
||||
->getAlignment()
|
||||
->setWrapText(true)
|
||||
->setVertical(Alignment::VERTICAL_TOP)
|
||||
->setHorizontal(Alignment::HORIZONTAL_LEFT);
|
||||
|
||||
// Tắt auto-size cho cột Notes và set độ rộng cố định
|
||||
$sheet->getColumnDimension($noteColumn)
|
||||
->setAutoSize(false)
|
||||
->setWidth(60);
|
||||
|
||||
// Tự động điều chỉnh chiều cao cho từng dòng có nội dung
|
||||
for ($row = 5; $row <= $lastRow; $row++) {
|
||||
$cellValue = $sheet->getCell($noteColumn . $row)->getValue();
|
||||
if (!empty($cellValue)) {
|
||||
// Tính toán chiều cao dựa trên nội dung
|
||||
$sheet->getRowDimension($row)->setRowHeight(-1);
|
||||
|
||||
// Tính toán lại chiều cao dựa trên số dòng trong nội dung
|
||||
$lineCount = substr_count($cellValue, "\n") + 1;
|
||||
$minHeight = max(30, $lineCount * 15); // 15 pixels cho mỗi dòng
|
||||
|
||||
// Lấy chiều cao hiện tại sau khi auto-size
|
||||
$currentHeight = $sheet->getRowDimension($row)->getRowHeight();
|
||||
|
||||
// Nếu chiều cao tự động nhỏ hơn chiều cao tối thiểu, sử dụng chiều cao tối thiểu
|
||||
if ($currentHeight < $minHeight) {
|
||||
$sheet->getRowDimension($row)->setRowHeight($minHeight);
|
||||
}
|
||||
} else {
|
||||
$sheet->getRowDimension($row)->setRowHeight(30);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh các tính toán của Excel
|
||||
$sheet->calculateColumnWidths();
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
public function array(): array
|
||||
{
|
||||
// Lấy headers
|
||||
|
|
@ -35,11 +86,6 @@ class TimekeepingExport implements FromArray, WithHeadings, WithStyles
|
|||
// 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
|
||||
|
|
@ -120,6 +166,8 @@ class TimekeepingExport implements FromArray, WithHeadings, WithStyles
|
|||
public function styles(Worksheet $sheet)
|
||||
{
|
||||
$lastColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($this->daysInMonth + 4);
|
||||
$lastRow = count($this->data) + 4;
|
||||
$noteColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($this->daysInMonth + 4);
|
||||
|
||||
// Title and working days
|
||||
$sheet->mergeCells("A1:{$lastColumn}1");
|
||||
|
|
@ -136,9 +184,6 @@ class TimekeepingExport implements FromArray, WithHeadings, WithStyles
|
|||
$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);
|
||||
|
|
@ -162,11 +207,33 @@ class TimekeepingExport implements FromArray, WithHeadings, WithStyles
|
|||
->setHorizontal(Alignment::HORIZONTAL_CENTER)
|
||||
->setVertical(Alignment::VERTICAL_CENTER);
|
||||
|
||||
// Left align Notes column
|
||||
$noteColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($this->daysInMonth + 4);
|
||||
// Left align Notes column và bật wrap text
|
||||
$sheet->getStyle("{$noteColumn}5:{$noteColumn}{$lastRow}")
|
||||
->getAlignment()
|
||||
->setHorizontal(Alignment::HORIZONTAL_LEFT);
|
||||
->setHorizontal(Alignment::HORIZONTAL_LEFT)
|
||||
->setVertical(Alignment::VERTICAL_TOP)
|
||||
->setWrapText(true);
|
||||
|
||||
// Set width for Note column - tăng độ rộng để hiển thị tốt hơn
|
||||
$sheet->getColumnDimension($noteColumn)->setWidth(60);
|
||||
|
||||
// Tự động điều chỉnh chiều cao cho các dòng có nội dung Notes
|
||||
for ($row = 5; $row <= $lastRow; $row++) {
|
||||
$cellValue = $sheet->getCell($noteColumn . $row)->getValue();
|
||||
if (!empty($cellValue)) {
|
||||
// Đết chiều cao tự động
|
||||
$sheet->getRowDimension($row)->setRowHeight(-1);
|
||||
|
||||
// Đảm bảo chiều cao tối thiểu
|
||||
$currentHeight = $sheet->getRowDimension($row)->getRowHeight();
|
||||
if ($currentHeight < 30) {
|
||||
$sheet->getRowDimension($row)->setRowHeight(30);
|
||||
}
|
||||
} else {
|
||||
// Chiều cao mặc định cho các dòng không có note
|
||||
$sheet->getRowDimension($row)->setRowHeight(30);
|
||||
}
|
||||
}
|
||||
|
||||
// Set column widths
|
||||
$sheet->getColumnDimension('A')->setWidth(30);
|
||||
|
|
@ -176,9 +243,6 @@ class TimekeepingExport implements FromArray, WithHeadings, WithStyles
|
|||
$sheet->getColumnDimension(\PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i))->setWidth(5);
|
||||
}
|
||||
|
||||
// Set width for Note column
|
||||
$sheet->getColumnDimension($noteColumn)->setWidth(40);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ import {
|
|||
Textarea,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
Modal,
|
||||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
|
|
@ -143,6 +144,9 @@ const Timekeeping = () => {
|
|||
const [dataTimeType, setDataTimeType] = useState<DataTimeType[]>([])
|
||||
const [dataReason, setDataReason] = useState<DataReason[]>([])
|
||||
|
||||
const [exportModalOpened, setExportModalOpened] = useState(false)
|
||||
const [exportOption, setExportOption] = useState('default')
|
||||
|
||||
const getListMasterByType = async (type: string) => {
|
||||
try {
|
||||
const params = {
|
||||
|
|
@ -437,7 +441,7 @@ const Timekeeping = () => {
|
|||
})
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
const handleExport = async (option: string) => {
|
||||
try {
|
||||
const timestamp = moment().format('DDMMYYYY_HHmmss')
|
||||
const fileName = `Timekeeping_${date.month}_${date.year}_${timestamp}.xlsx`
|
||||
|
|
@ -447,10 +451,12 @@ const Timekeeping = () => {
|
|||
{
|
||||
month: date.month,
|
||||
year: date.year,
|
||||
working_days: workingDays
|
||||
working_days: workingDays,
|
||||
option: option
|
||||
},
|
||||
fileName
|
||||
)
|
||||
setExportModalOpened(false)
|
||||
} catch (error) {
|
||||
console.error('Export error:', error)
|
||||
}
|
||||
|
|
@ -707,7 +713,7 @@ const Timekeeping = () => {
|
|||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
onClick={handleExport}
|
||||
onClick={() => setExportModalOpened(true)}
|
||||
size="xs"
|
||||
ml="xl"
|
||||
leftSection={<IconFileExcel size={16} />}
|
||||
|
|
@ -1054,6 +1060,35 @@ const Timekeeping = () => {
|
|||
</Table.Tbody>
|
||||
</Table>
|
||||
</Box>
|
||||
<Modal
|
||||
opened={exportModalOpened}
|
||||
onClose={() => setExportModalOpened(false)}
|
||||
title={
|
||||
<Text pl={'sm'} fw={700} fz={'lg'}>
|
||||
Export
|
||||
</Text>
|
||||
}
|
||||
size="sm"
|
||||
>
|
||||
<Select
|
||||
label="Option"
|
||||
placeholder="Choose an option"
|
||||
value={exportOption}
|
||||
onChange={(value) => setExportOption(value || 'default')}
|
||||
data={[
|
||||
{ value: 'default', label: 'Default' }
|
||||
]}
|
||||
mb="md"
|
||||
/>
|
||||
<Box style={{ display: 'flex', justifyContent: 'flex-end', gap: '10px' }}>
|
||||
<Button variant="outline" onClick={() => setExportModalOpened(false)}>
|
||||
Close
|
||||
</Button>
|
||||
<Button onClick={() => handleExport(exportOption)}>
|
||||
Export
|
||||
</Button>
|
||||
</Box>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue