From bcfecf4b79e96b8baccb9633e2ab0a4b0cad6454 Mon Sep 17 00:00:00 2001 From: Vckynando12 Date: Tue, 25 Mar 2025 11:30:25 +0700 Subject: [PATCH] new fiture export reports to pdf --- .../Controllers/ExportReportController.php | 139 +++++++ composer.json | 1 + composer.lock | 366 +++++++++++++++++- resources/views/export/reports-pdf.blade.php | 164 ++++++++ resources/views/reports.blade.php | 139 ++++++- routes/web.php | 5 +- 6 files changed, 806 insertions(+), 8 deletions(-) create mode 100644 app/Http/Controllers/ExportReportController.php create mode 100644 resources/views/export/reports-pdf.blade.php diff --git a/app/Http/Controllers/ExportReportController.php b/app/Http/Controllers/ExportReportController.php new file mode 100644 index 0000000..f2a9dd2 --- /dev/null +++ b/app/Http/Controllers/ExportReportController.php @@ -0,0 +1,139 @@ +validate([ + 'startDate' => 'required|date', + 'endDate' => 'required|date|after_or_equal:startDate', + ]); + + // Ambil parameter + $startDate = $request->startDate; + $endDate = $request->endDate; + + Log::info('Export PDF with date range', [ + 'startDate' => $startDate, + 'endDate' => $endDate + ]); + + // Tambahkan 1 hari ke endDate untuk query "sampai dengan" yang benar + // Ensure the end date is included by adding one day + $endDateForQuery = Carbon::parse($endDate)->addDay()->format('Y-m-d'); + + Log::info('Actual date range for query', [ + 'startDate' => $startDate, + 'endDateForQuery' => $endDateForQuery + ]); + + // Ambil data report dari file JSON + $jsonPath = storage_path('app/reports.json'); + $reports = []; + + if (File::exists($jsonPath)) { + Log::info('JSON file exists: ' . $jsonPath); + $jsonContent = File::get($jsonPath); + $jsonData = json_decode($jsonContent, true); + + if ($jsonData) { + Log::info('JSON data loaded successfully, count: ' . count($jsonData)); + + // Debug: Show a few timestamps from the data + $sampleTimestamps = array_slice(array_column($jsonData, 'timestamp'), 0, 5); + Log::info('Sample timestamps', ['samples' => $sampleTimestamps]); + + // Debug: Check for reports on the specific date (24th) + $date24th = substr($endDate, 0, 8) . '24'; // Assuming format YYYY-MM-DD + $reportsOn24th = array_filter($jsonData, function($report) use ($date24th) { + return isset($report['timestamp']) && substr($report['timestamp'], 0, 10) === $date24th; + }); + Log::info('Reports on the 24th', [ + 'date24th' => $date24th, + 'count' => count($reportsOn24th), + 'samples' => array_slice(array_column($reportsOn24th, 'timestamp'), 0, 3) + ]); + + // Filter berdasarkan range tanggal + $filteredReports = array_filter($jsonData, function($report) use ($startDate, $endDateForQuery, $endDate) { + if (!isset($report['timestamp'])) { + Log::warning('Report missing timestamp', ['report' => json_encode($report)]); + return false; + } + + $reportTimestamp = $report['timestamp']; + $reportDate = substr($reportTimestamp, 0, 10); // Ambil bagian YYYY-MM-DD saja + + // Log date comparison for debugging + Log::info('Date comparison', [ + 'reportTimestamp' => $reportTimestamp, + 'reportDate' => $reportDate, + 'startDate' => $startDate, + 'endDateForQuery' => $endDateForQuery, + 'isAfterStart' => $reportDate >= $startDate, + 'isBeforeEnd' => $reportDate <= $endDate // Compare with original endDate for inclusive + ]); + + // Use inclusive comparison for the end date (≤ instead of <) + // With endDateForQuery being endDate + 1 day, proper check is: reportDate < endDateForQuery + $isInRange = $reportDate >= $startDate && $reportDate < $endDateForQuery; + + // Explicitly check for the end date to make sure it's included + if (substr($endDate, 0, 10) === $reportDate) { + Log::info('Found report on end date', ['timestamp' => $reportTimestamp]); + return true; + } + + return $isInRange; + }); + + Log::info('Filtered reports count: ' . count($filteredReports)); + + // Urutkan data berdasarkan timestamp (terbaru dulu) + usort($filteredReports, function($a, $b) { + $timeA = strtotime($a['timestamp']); + $timeB = strtotime($b['timestamp']); + return $timeB - $timeA; // Descending order + }); + + $reports = array_values($filteredReports); // Reset array keys + Log::info('Final reports count: ' . count($reports)); + } else { + Log::error('Failed to decode JSON data', [ + 'fileSize' => strlen($jsonContent), + 'jsonError' => json_last_error_msg() + ]); + } + } else { + Log::error('JSON file not found: ' . $jsonPath); + } + + // Preparation data untuk PDF + $data = [ + 'title' => 'Laporan Keamanan dan Monitoring', + 'date' => date('d/m/Y'), + 'startDate' => Carbon::parse($startDate)->format('d/m/Y'), + 'endDate' => Carbon::parse($endDate)->format('d/m/Y'), + 'reports' => $reports, + 'totalReports' => count($reports), + ]; + + // Generate PDF + $pdf = Pdf::loadView('export.reports-pdf', $data); + + // Set paper dan orientasi + $pdf->setPaper('a4', 'landscape'); + + // Download PDF dengan nama file yang berisi range tanggal + return $pdf->download('laporan_' . $startDate . '_sampai_' . $endDate . '.pdf'); + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index df6eca6..5a3a5cb 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "license": "MIT", "require": { "php": "^8.1", + "barryvdh/laravel-dompdf": "^3.1", "google/cloud-firestore": "^1.48", "guzzlehttp/guzzle": "^7.2", "kreait/firebase-php": "^7.16", diff --git a/composer.lock b/composer.lock index f91e318..6858dff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,85 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "89ca0d9e8053ae1653b307f8756de6a9", + "content-hash": "160c4326c82eeb41dedfb2730b633aa5", "packages": [ + { + "name": "barryvdh/laravel-dompdf", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-dompdf.git", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "shasum": "" + }, + "require": { + "dompdf/dompdf": "^3.0", + "illuminate/support": "^9|^10|^11|^12", + "php": "^8.1" + }, + "require-dev": { + "larastan/larastan": "^2.7|^3.0", + "orchestra/testbench": "^7|^8|^9|^10", + "phpro/grumphp": "^2.5", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf", + "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf" + }, + "providers": [ + "Barryvdh\\DomPDF\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Barryvdh\\DomPDF\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "A DOMPDF Wrapper for Laravel", + "keywords": [ + "dompdf", + "laravel", + "pdf" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-dompdf/issues", + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2025-02-13T15:07:54+00:00" + }, { "name": "beste/clock", "version": "3.0.0", @@ -580,6 +657,161 @@ ], "time": "2024-02-05T11:56:58+00:00" }, + { + "name": "dompdf/dompdf", + "version": "v3.1.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "a51bd7a063a65499446919286fb18b518177155a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/a51bd7a063a65499446919286fb18b518177155a", + "reference": "a51bd7a063a65499446919286fb18b518177155a", + "shasum": "" + }, + "require": { + "dompdf/php-font-lib": "^1.0.0", + "dompdf/php-svg-lib": "^1.0.0", + "ext-dom": "*", + "ext-mbstring": "*", + "masterminds/html5": "^2.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ext-gd": "*", + "ext-json": "*", + "ext-zip": "*", + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" + }, + "suggest": { + "ext-gd": "Needed to process images", + "ext-gmagick": "Improves image processing performance", + "ext-imagick": "Improves image processing performance", + "ext-zlib": "Needed for pdf stream compression" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "The Dompdf Community", + "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "support": { + "issues": "https://github.com/dompdf/dompdf/issues", + "source": "https://github.com/dompdf/dompdf/tree/v3.1.0" + }, + "time": "2025-01-15T14:09:04+00:00" + }, + { + "name": "dompdf/php-font-lib", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "The FontLib Community", + "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/dompdf/php-font-lib", + "support": { + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.1" + }, + "time": "2024-12-02T14:37:59+00:00" + }, + { + "name": "dompdf/php-svg-lib", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The SvgLib Community", + "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/dompdf/php-svg-lib", + "support": { + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" + }, + "time": "2024-04-29T13:26:35+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.4.0", @@ -3068,6 +3300,73 @@ ], "time": "2024-09-21T08:32:55+00:00" }, + { + "name": "masterminds/html5", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" + }, + "time": "2024-03-31T07:05:07+00:00" + }, { "name": "monolog/monolog", "version": "3.8.1", @@ -4539,6 +4838,71 @@ ], "time": "2024-11-27T12:13:42+00:00" }, + { + "name": "sabberworm/php-css-parser", + "version": "v8.8.0", + "source": { + "type": "git", + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "3de493bdddfd1f051249af725c7e0d2c38fed740" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/3de493bdddfd1f051249af725c7e0d2c38fed740", + "reference": "3de493bdddfd1f051249af725c7e0d2c38fed740", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + }, + "require-dev": { + "phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.8.0" + }, + "time": "2025-03-23T17:59:05+00:00" + }, { "name": "symfony/cache", "version": "v7.2.3", diff --git a/resources/views/export/reports-pdf.blade.php b/resources/views/export/reports-pdf.blade.php new file mode 100644 index 0000000..c00f175 --- /dev/null +++ b/resources/views/export/reports-pdf.blade.php @@ -0,0 +1,164 @@ + + + + + {{ $title }} + + + +
+
{{ $title }}
+
Laporan Keamanan dan Monitoring System
+
Periode: {{ $startDate }} - {{ $endDate }}
+
+ + + + + + + + + + + + + @if(count($reports) > 0) + @foreach($reports as $index => $report) + + + + + + + + @endforeach + @else + + + + @endif + +
NoTanggalPerubahanStatus KeamananStatus Perangkat
{{ $index + 1 }}{{ date('d/m/Y H:i', strtotime($report['timestamp'])) }} + @php + $changes = []; + // Detect changes based on your logic + // This is a simplified example + if(isset($report['security']['motion'])) { + $changes[] = ['type' => 'Motion', 'badge' => 'badge-motion']; + } + if(isset($report['security']['status'])) { + $changes[] = ['type' => 'Status', 'badge' => 'badge-status']; + } + if(isset($report['security']['fan'])) { + $changes[] = ['type' => 'Fan', 'badge' => 'badge-fan']; + } + if(isset($report['smartcab']['servo_status'])) { + $changes[] = ['type' => 'Servo', 'badge' => 'badge-servo-status']; + } + // Add more change types as needed + @endphp + + @foreach($changes as $change) + {{ $change['type'] }} + @endforeach + + @if(isset($report['security'])) +
Gerakan: {{ ucfirst($report['security']['motion'] ?? 'N/A') }}
+
Status: {{ ucfirst($report['security']['status'] ?? 'N/A') }}
+
Fan: {{ $report['security']['fan'] ?? 'N/A' }}
+ @else + N/A + @endif +
+ @if(isset($report['smartcab'])) +
Servo: {{ $report['smartcab']['servo_status'] ?? 'N/A' }}
+
Last Access: {{ $report['smartcab']['last_access'] ?? 'N/A' }}
+ @endif + @if(isset($report['dht11'])) +
Suhu: {{ $report['dht11']['temperature'] ?? 'N/A' }}°C
+
Kelembaban: {{ $report['dht11']['humidity'] ?? 'N/A' }}%
+ @endif +
Tidak ada data laporan untuk periode yang dipilih
+ + + + + + diff --git a/resources/views/reports.blade.php b/resources/views/reports.blade.php index 47e7006..a924e1d 100644 --- a/resources/views/reports.blade.php +++ b/resources/views/reports.blade.php @@ -57,12 +57,20 @@

Laporan Keamanan dan Monitoring

- - - - - Kembali ke Dashboard - +
+ + + + + + Kembali ke Dashboard + +
@@ -308,6 +316,61 @@ class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:
+ + +