load(['project', 'user', 'labors', 'equipment', 'activities', 'materials', 'issues']); $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('Daily Report'); $sheet->setShowGridlines(true); // Styling helpers $headerStyle = [ 'font' => [ 'name' => 'Arial', 'size' => 16, 'bold' => true, 'color' => ['rgb' => 'FFFFFF'], ], 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '334155'], // Slate 700 ], 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER, ], ]; $subHeaderStyle = [ 'font' => [ 'name' => 'Arial', 'size' => 11, 'bold' => true, 'color' => ['rgb' => '334155'], ], 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'F1F5F9'], // Slate 100 ], 'alignment' => [ 'vertical' => Alignment::VERTICAL_CENTER, ], 'borders' => [ 'bottom' => [ 'borderStyle' => Border::BORDER_MEDIUM, 'color' => ['rgb' => 'CBD5E1'], ], ], ]; $sectionTitleStyle = [ 'font' => [ 'name' => 'Arial', 'size' => 12, 'bold' => true, 'color' => ['rgb' => '0F172A'], // Slate 900 ], 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'E2E8F0'], // Slate 200 ], 'alignment' => [ 'vertical' => Alignment::VERTICAL_CENTER, ], ]; $boldLabelStyle = [ 'font' => [ 'name' => 'Arial', 'size' => 10, 'bold' => true, 'color' => ['rgb' => '475569'], ], ]; $tableHeaderStyle = [ 'font' => [ 'name' => 'Arial', 'size' => 10, 'bold' => true, 'color' => ['rgb' => '475569'], ], 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'F8FAFC'], ], 'borders' => [ 'bottom' => [ 'borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => 'E2E8F0'], ], ], ]; $borderBottomThin = [ 'borders' => [ 'bottom' => [ 'borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => 'F1F5F9'], ], ], ]; // 1. Title Block $sheet->mergeCells('A1:F1'); $sheet->setCellValue('A1', 'GSB CONSTRUCTION - DAILY SITE REPORT'); $sheet->getStyle('A1:F1')->applyFromArray($headerStyle); $sheet->getRowDimension(1)->setRowHeight(40); // 2. Metadata Block $sheet->mergeCells('A3:F3'); $sheet->setCellValue('A3', ' REPORT METADATA'); $sheet->getStyle('A3:F3')->applyFromArray($subHeaderStyle); $sheet->getRowDimension(3)->setRowHeight(25); // Row 4 $sheet->setCellValue('A4', 'Report Number:'); $sheet->setCellValue('B4', $dailyReport->report_number); $sheet->setCellValue('C4', 'Report Date:'); $sheet->setCellValue('D4', $dailyReport->report_date ? $dailyReport->report_date->format('Y-m-d') : 'N/A'); $sheet->setCellValue('E4', 'Prepared By:'); $sheet->setCellValue('F4', $dailyReport->user ? $dailyReport->user->name : 'N/A'); // Row 5 $sheet->setCellValue('A5', 'Project Code:'); $sheet->setCellValue('B5', $dailyReport->project ? $dailyReport->project->code : 'N/A'); $sheet->setCellValue('C5', 'Project Name:'); $sheet->mergeCells('D5:F5'); $sheet->setCellValue('D5', $dailyReport->project ? $dailyReport->project->name : 'N/A'); // Row 6 $sheet->setCellValue('A6', 'Weather:'); $sheet->setCellValue('B6', $dailyReport->weather ?: 'N/A'); $sheet->setCellValue('C6', 'Temperature:'); $sheet->setCellValue('D6', $dailyReport->temperature ? $dailyReport->temperature . ' °C' : 'N/A'); $sheet->setCellValue('E6', 'Precipitation:'); $sheet->setCellValue('F6', $dailyReport->precipitation ?: 'N/A'); // Row 7 $sheet->setCellValue('A7', 'Wind:'); $sheet->setCellValue('B7', $dailyReport->wind ?: 'N/A'); $sheet->getStyle('A4')->applyFromArray($boldLabelStyle); $sheet->getStyle('C4')->applyFromArray($boldLabelStyle); $sheet->getStyle('E4')->applyFromArray($boldLabelStyle); $sheet->getStyle('A5')->applyFromArray($boldLabelStyle); $sheet->getStyle('C5')->applyFromArray($boldLabelStyle); $sheet->getStyle('A6')->applyFromArray($boldLabelStyle); $sheet->getStyle('C6')->applyFromArray($boldLabelStyle); $sheet->getStyle('E6')->applyFromArray($boldLabelStyle); $sheet->getStyle('A7')->applyFromArray($boldLabelStyle); // 2.5. Summary Dashboard Block $sheet->mergeCells('A9:F9'); $sheet->setCellValue('A9', ' SUMMARY & KEY METRICS'); $sheet->getStyle('A9:F9')->applyFromArray($subHeaderStyle); $sheet->getRowDimension(9)->setRowHeight(25); // Calculate summary metrics $totalWorkers = 0; $totalManHours = 0; foreach ($dailyReport->labors as $lab) { $totalWorkers += $lab->workers_count; $totalManHours += $lab->workers_count * ($lab->hours ?: 0); } $totalEquipmentHours = $dailyReport->equipment->sum('hours_used') ?: 0; $avgProgress = $dailyReport->activities->isEmpty() ? 0 : ($dailyReport->activities->avg('percentage_completed') ?: 0); // Row 10 $sheet->setCellValue('A10', 'Tasks Logged:'); $sheet->setCellValue('B10', count($dailyReport->activities)); $sheet->setCellValue('C10', 'Materials Logged:'); $sheet->setCellValue('D10', count($dailyReport->materials)); $sheet->setCellValue('E10', 'Manpower Count:'); $sheet->setCellValue('F10', $totalWorkers); // Row 11 $sheet->setCellValue('A11', 'Avg. Progress:'); $sheet->setCellValue('B11', number_format($avgProgress, 1) . '%'); $sheet->setCellValue('C11', 'Reported Issues:'); $sheet->setCellValue('D11', count($dailyReport->issues)); $sheet->setCellValue('E11', 'Total Man-Hours:'); $sheet->setCellValue('F11', number_format($totalManHours, 1) . ' hrs'); // Row 12 $sheet->setCellValue('A12', 'Active Equipment:'); $sheet->setCellValue('B12', count($dailyReport->equipment)); $sheet->setCellValue('C12', 'Equipment Hours:'); $sheet->setCellValue('D12', number_format($totalEquipmentHours, 1) . ' hrs'); $sheet->getStyle('A10')->applyFromArray($boldLabelStyle); $sheet->getStyle('C10')->applyFromArray($boldLabelStyle); $sheet->getStyle('E10')->applyFromArray($boldLabelStyle); $sheet->getStyle('A11')->applyFromArray($boldLabelStyle); $sheet->getStyle('C11')->applyFromArray($boldLabelStyle); $sheet->getStyle('E11')->applyFromArray($boldLabelStyle); $sheet->getStyle('A12')->applyFromArray($boldLabelStyle); $sheet->getStyle('C12')->applyFromArray($boldLabelStyle); $rowIdx = 14; // 3. Section A: Tasks $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", ' 1. TASKS'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($sectionTitleStyle); $sheet->getRowDimension($rowIdx)->setRowHeight(25); $rowIdx++; // Table Headers $sheet->mergeCells("A{$rowIdx}:C{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'Task Name / Activity'); $sheet->setCellValue("D{$rowIdx}", 'Zone / Area'); $sheet->setCellValue("E{$rowIdx}", 'Qty Completed'); $sheet->setCellValue("F{$rowIdx}", 'Completion %'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($tableHeaderStyle); $rowIdx++; if ($dailyReport->activities->isEmpty()) { $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'No work activities reported for this shift.'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray(['font' => ['italic' => true, 'color' => ['rgb' => '94A3B8']]]); $rowIdx++; } else { foreach ($dailyReport->activities as $act) { $sheet->mergeCells("A{$rowIdx}:C{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", $act->task_name); $sheet->setCellValue("D{$rowIdx}", $act->zone_area ?: 'N/A'); $sheet->setCellValue("E{$rowIdx}", $act->quantity_completed ?: 'N/A'); $sheet->setCellValue("F{$rowIdx}", $act->percentage_completed ? $act->percentage_completed . '%' : '0%'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($borderBottomThin); $rowIdx++; } } $rowIdx++; // 4. Section B: Materials $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", ' 2. MATERIALS'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($sectionTitleStyle); $sheet->getRowDimension($rowIdx)->setRowHeight(25); $rowIdx++; // Table Headers $sheet->mergeCells("A{$rowIdx}:C{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'Material Name'); $sheet->setCellValue("D{$rowIdx}", 'Quantity Received / Used'); $sheet->mergeCells("E{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("E{$rowIdx}", 'Condition / Remarks'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($tableHeaderStyle); $rowIdx++; if ($dailyReport->materials->isEmpty()) { $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'No materials logged for this date.'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray(['font' => ['italic' => true, 'color' => ['rgb' => '94A3B8']]]); $rowIdx++; } else { foreach ($dailyReport->materials as $mat) { $sheet->mergeCells("A{$rowIdx}:C{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", $mat->material_name); $sheet->setCellValue("D{$rowIdx}", $mat->quantity_received); $sheet->mergeCells("E{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("E{$rowIdx}", $mat->condition ?: 'Good'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($borderBottomThin); $rowIdx++; } } $rowIdx++; // 5. Section C: Labor & Manpower $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", ' 3. MANPOWER/LABOR'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($sectionTitleStyle); $sheet->getRowDimension($rowIdx)->setRowHeight(25); $rowIdx++; // Table Headers $sheet->mergeCells("A{$rowIdx}:B{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'Labor Trade / Profession'); $sheet->setCellValue("C{$rowIdx}", 'Workers Count'); $sheet->setCellValue("D{$rowIdx}", 'Hours Rendered'); $sheet->mergeCells("E{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("E{$rowIdx}", 'Notes / Details'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($tableHeaderStyle); $rowIdx++; if ($dailyReport->labors->isEmpty()) { $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'No labor resources logged.'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray(['font' => ['italic' => true, 'color' => ['rgb' => '94A3B8']]]); $rowIdx++; } else { foreach ($dailyReport->labors as $lab) { $sheet->mergeCells("A{$rowIdx}:B{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", $lab->trade); $sheet->setCellValue("C{$rowIdx}", $lab->workers_count); $sheet->setCellValue("D{$rowIdx}", $lab->hours); $sheet->mergeCells("E{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("E{$rowIdx}", $lab->notes ?: ''); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($borderBottomThin); $rowIdx++; } } $rowIdx++; // 6. Section D: Equipment Usage $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", ' 4. EQUIPMENT'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($sectionTitleStyle); $sheet->getRowDimension($rowIdx)->setRowHeight(25); $rowIdx++; // Table Headers $sheet->mergeCells("A{$rowIdx}:C{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'Equipment Name'); $sheet->setCellValue("D{$rowIdx}", 'Hours Used'); $sheet->mergeCells("E{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("E{$rowIdx}", 'Status (Active / Idle)'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($tableHeaderStyle); $rowIdx++; if ($dailyReport->equipment->isEmpty()) { $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'No equipment usage logged.'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray(['font' => ['italic' => true, 'color' => ['rgb' => '94A3B8']]]); $rowIdx++; } else { foreach ($dailyReport->equipment as $eq) { $sheet->mergeCells("A{$rowIdx}:C{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", $eq->equipment_name); $sheet->setCellValue("D{$rowIdx}", $eq->hours_used); $sheet->mergeCells("E{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("E{$rowIdx}", ucfirst($eq->status)); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($borderBottomThin); $rowIdx++; } } $rowIdx++; // 7. Section E: Reported Issues & Delays $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", ' 5. ISSUES & CONCERN'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($sectionTitleStyle); $sheet->getRowDimension($rowIdx)->setRowHeight(25); $rowIdx++; // Table Headers $sheet->mergeCells("A{$rowIdx}:B{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'Issue / Delay Type'); $sheet->mergeCells("C{$rowIdx}:E{$rowIdx}"); $sheet->setCellValue("C{$rowIdx}", 'Description'); $sheet->setCellValue("F{$rowIdx}", 'Delay Impact (Hrs)'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($tableHeaderStyle); $rowIdx++; if ($dailyReport->issues->isEmpty()) { $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", 'No major issues or delays reported.'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray(['font' => ['italic' => true, 'color' => ['rgb' => '94A3B8']]]); $rowIdx++; } else { foreach ($dailyReport->issues as $iss) { $sheet->mergeCells("A{$rowIdx}:B{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", ucfirst(str_replace('_', ' ', $iss->issue_type))); $sheet->mergeCells("C{$rowIdx}:E{$rowIdx}"); $sheet->setCellValue("C{$rowIdx}", $iss->description); $sheet->setCellValue("F{$rowIdx}", $iss->delay_impact ?: '0'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($borderBottomThin); $rowIdx++; } } $rowIdx++; // 8. General Remarks $sheet->mergeCells("A{$rowIdx}:F{$rowIdx}"); $sheet->setCellValue("A{$rowIdx}", ' GENERAL REMARKS & NOTES'); $sheet->getStyle("A{$rowIdx}:F{$rowIdx}")->applyFromArray($subHeaderStyle); $rowIdx++; $sheet->mergeCells("A{$rowIdx}:F" . ($rowIdx + 3)); $sheet->setCellValue("A{$rowIdx}", $dailyReport->remarks ?: 'No additional remarks entered.'); $sheet->getStyle("A{$rowIdx}:F" . ($rowIdx + 3))->applyFromArray([ 'alignment' => [ 'vertical' => Alignment::VERTICAL_TOP, 'wrapText' => true ], 'font' => ['italic' => !$dailyReport->remarks] ]); // Auto-fit column widths foreach (range('A', 'F') as $col) { $sheet->getColumnDimension($col)->setAutoSize(true); } // Output Excel response $filename = 'DailyReport_' . ($dailyReport->project ? $dailyReport->project->code : '') . '_' . $dailyReport->report_date->format('Ymd') . '.xlsx'; header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="' . $filename . '"'); header('Cache-Control: max-age=0'); $writer = new Xlsx($spreadsheet); $writer->save('php://output'); exit; } public function pdf(DailyReport $dailyReport) { $dailyReport->load(['project', 'user', 'labors', 'equipment', 'activities', 'materials', 'issues']); // Calculate summary metrics $totalWorkers = 0; $totalManHours = 0; foreach ($dailyReport->labors as $lab) { $totalWorkers += $lab->workers_count; $totalManHours += $lab->workers_count * ($lab->hours ?: 0); } $totalEquipmentHours = 0; foreach ($dailyReport->equipment as $eq) { $totalEquipmentHours += $eq->hours_used ?: 0; } $avgProgress = 0; if (!$dailyReport->activities->isEmpty()) { $avgProgress = $dailyReport->activities->avg('percentage_completed') ?: 0; } $summary = [ 'total_workers' => $totalWorkers, 'total_man_hours' => $totalManHours, 'total_equipment_hours' => $totalEquipmentHours, 'avg_progress' => $avgProgress, ]; $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('dailyreports::pdf.daily-report', [ 'report' => $dailyReport, 'summary' => $summary, ]); $filename = 'DailyReport_' . ($dailyReport->project ? $dailyReport->project->code : '') . '_' . $dailyReport->report_date->format('Ymd') . '.pdf'; return $pdf->download($filename); } }