[ ['id' => 'ditolak', 'label' => 'Izin Ditolak', 'value' => 8, 'color' => 'danger'], ['id' => 'selesai', 'label' => 'Izin Selesai', 'value' => 45, 'color' => 'success'], ['id' => 'proses', 'label' => 'Dalam Proses', 'value' => 12, 'color' => 'info'], ], 'amdal' => [ ['id' => 'ditolak', 'label' => 'Izin Ditolak', 'value' => 3, 'color' => 'danger'], ['id' => 'selesai', 'label' => 'Izin Selesai', 'value' => 15, 'color' => 'success'], ['id' => 'proses', 'label' => 'Dalam Proses', 'value' => 9, 'color' => 'info'], ], 'rintek' => [ ['id' => 'ditolak', 'label' => 'Izin Ditolak', 'value' => 5, 'color' => 'danger'], ['id' => 'selesai', 'label' => 'Izin Selesai', 'value' => 28, 'color' => 'success'], ['id' => 'proses', 'label' => 'Dalam Proses', 'value' => 7, 'color' => 'info'], ], 'izin_angkut' => [ ['id' => 'ditolak', 'label' => 'Izin Ditolak', 'value' => 12, 'color' => 'danger'], ['id' => 'selesai', 'label' => 'Izin Selesai', 'value' => 67, 'color' => 'success'], ['id' => 'proses', 'label' => 'Dalam Proses', 'value' => 18, 'color' => 'info'], ], 'uji_emisi' => [ ['id' => 'ditolak', 'label' => 'Izin Ditolak', 'value' => 6, 'color' => 'danger'], ['id' => 'selesai', 'label' => 'Izin Selesai', 'value' => 89, 'color' => 'success'], ['id' => 'proses', 'label' => 'Dalam Proses', 'value' => 23, 'color' => 'info'], ], ]; return $data[$type] ?? []; } /** * Get status data by type from database or fallback */ public static function getStatusDataByType(string $type): array { // Cek apakah ada data di database untuk hari ini $dbData = PerizinanStatus::getLatestByKategori($type); if ($dbData->isNotEmpty()) { $data = []; $colorMap = [ 'ditolak' => 'danger', 'selesai' => 'success', 'proses' => 'info', 'total' => 'primary' ]; foreach ($dbData as $item) { $data[] = [ 'id' => $item->StatusID, 'label' => $item->Label, 'value' => $item->Value, 'color' => $colorMap[$item->StatusID] ?? 'secondary' ]; } return $data; } // Fallback ke data statis jika tidak ada data di database return self::getFallbackDataByType($type); } /** * Menambahkan total ke data statuses */ public static function addTotalToStatuses(array $statuses): array { // Cek apakah sudah ada total di data $hasTotal = collect($statuses)->contains('id', 'total'); if (!$hasTotal) { $total = array_sum(array_column($statuses, 'value')); $statuses[] = [ 'id' => 'total', 'label' => 'Total Pengajuan', 'value' => $total, 'color' => 'primary' ]; } return $statuses; } /** * Mendapatkan label untuk tipe izin */ public static function getTypeLabel(string $type): string { $labels = [ 'pertek' => 'PERTEK', 'rintek' => 'RINTEK', 'amdal' => 'AMDAL', 'izin_angkut' => 'IZIN ANGKUT & OLAH', 'uji_emisi' => 'IZIN TEMPAT UJI EMISI', ]; return $labels[$type] ?? strtoupper($type); } /** * Mendapatkan icon untuk status */ public static function getStatusIcon(string $statusId): string { $icons = [ 'ditolak' => 'circle-x', 'selesai' => 'circle-check', 'proses' => 'refresh-cw', 'total' => 'equal', ]; return $icons[$statusId] ?? 'circle'; } /** * Mendapatkan background color untuk card */ public static function getCardBackground(string $statusId): string { $backgrounds = [ 'ditolak' => 'bg-gradient-start-4', 'selesai' => 'bg-gradient-start-2', 'proses' => 'bg-gradient-start-3', 'total' => 'bg-gradient-start-1', ]; return $backgrounds[$statusId] ?? 'bg-gradient-start-1'; } /** * Mendapatkan warna lingkaran icon */ public static function getIconCircleColor(string $statusId): string { $colors = [ 'ditolak' => 'bg-red', 'selesai' => 'bg-green', 'proses' => 'bg-info', 'total' => 'bg-yellow', ]; return $colors[$statusId] ?? 'bg-primary'; } /** * Mendapatkan semua tipe izin yang tersedia */ public static function getAllTypes(): array { return ['pertek', 'rintek', 'amdal', 'izin_angkut', 'uji_emisi']; } /** * Mendapatkan statistik lengkap untuk semua tipe */ public static function getAllStatistics(): array { $types = self::getAllTypes(); $allData = []; foreach ($types as $type) { $statuses = self::getStatusDataByType($type); $statuses = self::addTotalToStatuses($statuses); $allData[$type] = [ 'type' => $type, 'label' => self::getTypeLabel($type), 'data' => $statuses ]; } return $allData; } /** * Format percentage dari total */ public static function calculatePercentage(int $value, int $total): float { return $total > 0 ? round(($value / $total) * 100, 2) : 0; } /** * Mendapatkan trend indicator (simulasi) */ public static function getTrendIndicator(string $type, string $statusId): array { // Simulasi data trend (bisa diganti dengan data real dari database) $trends = [ 'pertek' => ['ditolak' => -2.5, 'selesai' => 5.3, 'proses' => 1.2], 'rintek' => ['ditolak' => -1.8, 'selesai' => 3.7, 'proses' => 0.5], 'amdal' => ['ditolak' => -0.9, 'selesai' => 2.1, 'proses' => -0.3], 'izin_angkut' => ['ditolak' => -3.2, 'selesai' => 7.8, 'proses' => 2.1], 'uji_emisi' => ['ditolak' => -1.5, 'selesai' => 12.4, 'proses' => 4.2], ]; $value = $trends[$type][$statusId] ?? 0; return [ 'value' => $value, 'direction' => $value > 0 ? 'up' : ($value < 0 ? 'down' : 'same'), 'color' => $value > 0 ? 'success' : ($value < 0 ? 'danger' : 'secondary') ]; } /** * Mendapatkan badge color untuk tipe izin */ public static function getBadgeColor(string $type): string { $colors = [ 'pertek' => 'primary', 'rintek' => 'success', 'amdal' => 'info', 'izin_angkut' => 'warning', 'uji_emisi' => 'secondary', ]; return $colors[$type] ?? 'primary'; } /** * Mendapatkan data untuk chart */ public static function getChartData(string $type): array { $statuses = self::getStatusDataByType($type); return [ 'labels' => array_column($statuses, 'label'), 'values' => array_column($statuses, 'value'), 'colors' => array_map(function($status) { return self::getChartColor($status['id']); }, $statuses) ]; } /** * Mendapatkan warna untuk chart */ private static function getChartColor(string $statusId): string { $colors = [ 'ditolak' => '#ef4444', 'selesai' => '#22c55e', 'proses' => '#3b82f6', 'total' => '#f59e0b', ]; return $colors[$statusId] ?? '#6b7280'; } /** * Get fastest permohonan data from database or fallback */ public static function getFastestPermohonanByType(string $type): array { // Try to get data from database first $dbData = FastestPermohonan::getLatestByKategori($type); if ($dbData->isNotEmpty()) { $data = []; $index = 1; foreach ($dbData as $item) { $data[] = [ 'Nama' => $item->Nama, 'Total' => $item->Total, 'DurasiPemohon' => $item->DurasiPemohon, 'DurasiPetugas' => $item->DurasiPetugas, 'rank_order' => $index++ // Generate rank_order dinamis untuk display ]; } return $data; } // Fallback to static data if no database data available return self::getFallbackFastestData($type); } /** * Fallback static data for fastest permohonan */ private static function getFallbackFastestData(string $type): array { $fallbackData = [ 'pertek' => [ ['Nama' => 'Izin Pengelolaan Limbah B3', 'Total' => 45, 'DurasiPemohon' => '2 Hari 3 Jam', 'DurasiPetugas' => '5 Hari 2 Jam', 'rank_order' => 1], ['Nama' => 'Izin Emisi Kendaraan', 'Total' => 67, 'DurasiPemohon' => '3 Hari 1 Jam', 'DurasiPetugas' => '7 Hari 4 Jam', 'rank_order' => 2], ['Nama' => 'SPPL Industri', 'Total' => 23, 'DurasiPemohon' => '4 Hari 2 Jam', 'DurasiPetugas' => '8 Hari 1 Jam', 'rank_order' => 3], ['Nama' => 'Izin Penyimpanan B3', 'Total' => 34, 'DurasiPemohon' => '5 Hari', 'DurasiPetugas' => '9 Hari 3 Jam', 'rank_order' => 4], ['Nama' => 'Izin Pengolahan Limbah', 'Total' => 19, 'DurasiPemohon' => '6 Hari 4 Jam', 'DurasiPetugas' => '10 Hari 2 Jam', 'rank_order' => 5], ], 'amdal' => [ ['Nama' => 'AMDAL Bangunan Tinggi', 'Total' => 12, 'DurasiPemohon' => '15 Hari', 'DurasiPetugas' => '30 Hari', 'rank_order' => 1], ['Nama' => 'AMDAL Infrastruktur', 'Total' => 8, 'DurasiPemohon' => '18 Hari', 'DurasiPetugas' => '35 Hari', 'rank_order' => 2], ['Nama' => 'AMDAL Industri', 'Total' => 15, 'DurasiPemohon' => '20 Hari', 'DurasiPetugas' => '40 Hari', 'rank_order' => 3], ['Nama' => 'AMDAL Perumahan', 'Total' => 25, 'DurasiPemohon' => '22 Hari', 'DurasiPetugas' => '42 Hari', 'rank_order' => 4], ['Nama' => 'AMDAL Komersial', 'Total' => 18, 'DurasiPemohon' => '25 Hari', 'DurasiPetugas' => '45 Hari', 'rank_order' => 5], ] ]; return $fallbackData[$type] ?? []; } /** * Get fastest data for all supported types */ public static function getAllFastestData(): array { $supportedTypes = ['pertek', 'amdal']; // Only types with API endpoints $allData = []; foreach ($supportedTypes as $type) { $allData[$type] = [ 'type' => $type, 'label' => self::getTypeLabel($type), 'data' => self::getFastestPermohonanByType($type) ]; } return $allData; } /** * Format duration text for display */ public static function formatDuration(string $duration): string { // API returns format like "03 Jam 54 Menit 13 Detik" or "2 Hari 01 Jam 02 Menit 04 Detik" return $duration; } /** * Get rank badge color based on ranking */ public static function getRankBadgeColor(int $rank): string { $colors = [ 1 => 'success', 2 => 'info', 3 => 'warning', 4 => 'secondary', 5 => 'dark' ]; return $colors[$rank] ?? 'secondary'; } /** * Get terakhir terbit data from database or fallback */ public static function getTerakhirTerbitByType(string $type): array { // Try to get data from database first $dbData = TerakhirTerbit::getLatestByKategori($type); if ($dbData->isNotEmpty()) { $data = []; $index = 1; foreach ($dbData as $item) { $data[] = [ 'NamaIzin' => $item->NamaIzin, 'Pemohon' => $item->Pemohon, 'TanggalTerbit' => $item->TanggalTerbit, 'rank_order' => $index++ // Generate rank_order dinamis untuk display ]; } return $data; } // Fallback to static data if no database data available return self::getFallbackTerakhirTerbitData($type); } /** * Fallback static data for terakhir terbit */ private static function getFallbackTerakhirTerbitData(string $type): array { $fallbackData = [ 'pertek' => [ ['NamaIzin' => 'SERTIFIKAT LAIK OPERASI - PEMENUHAN BAKU MUTU EMISI', 'Pemohon' => 'PT. MAJU BERSAMA', 'TanggalTerbit' => Carbon::parse('2025-07-15'), 'rank_order' => 1], ['NamaIzin' => 'PERSETUJUAN TEKNIS - PEMENUHAN BAKU MUTU AIR LIMBAH', 'Pemohon' => 'CV. KARYA MANDIRI', 'TanggalTerbit' => Carbon::parse('2025-07-14'), 'rank_order' => 2], ['NamaIzin' => 'SERTIFIKAT LAIK OPERASI - PEMENUHAN BAKU MUTU AIR LIMBAH', 'Pemohon' => 'PT. INDUSTRI SEJAHTERA', 'TanggalTerbit' => Carbon::parse('2025-07-13'), 'rank_order' => 3], ['NamaIzin' => 'PERSETUJUAN TEKNIS - PEMENUHAN BAKU MUTU AIR LIMBAH', 'Pemohon' => 'PT. TEKNOLOGI MODERN', 'TanggalTerbit' => Carbon::parse('2025-07-12'), 'rank_order' => 4], ['NamaIzin' => 'SERTIFIKAT LAIK OPERASI - PEMENUHAN BAKU MUTU EMISI', 'Pemohon' => 'CV. BERKAH JAYA', 'TanggalTerbit' => Carbon::parse('2025-07-11'), 'rank_order' => 5], ], 'amdal' => [ ['NamaIzin' => 'AMDAL BANGUNAN TINGGI', 'Pemohon' => 'PT. KONSTRUKSI PRIMA', 'TanggalTerbit' => Carbon::parse('2025-07-10'), 'rank_order' => 1], ['NamaIzin' => 'AMDAL INFRASTRUKTUR', 'Pemohon' => 'CV. INFRATEK', 'TanggalTerbit' => Carbon::parse('2025-07-09'), 'rank_order' => 2], ['NamaIzin' => 'AMDAL INDUSTRI', 'Pemohon' => 'PT. INDUSTRI MODERN', 'TanggalTerbit' => Carbon::parse('2025-07-08'), 'rank_order' => 3], ['NamaIzin' => 'AMDAL PERUMAHAN', 'Pemohon' => 'PT. PROPERTI SEJAHTERA', 'TanggalTerbit' => Carbon::parse('2025-07-07'), 'rank_order' => 4], ['NamaIzin' => 'AMDAL KOMERSIAL', 'Pemohon' => 'CV. KOMERSIAL JAYA', 'TanggalTerbit' => Carbon::parse('2025-07-06'), 'rank_order' => 5], ] ]; return $fallbackData[$type] ?? []; } /** * Get terakhir terbit data for all supported types */ public static function getAllTerakhirTerbitData(): array { $supportedTypes = ['pertek', 'amdal']; // Only types with API endpoints $allData = []; foreach ($supportedTypes as $type) { $allData[$type] = [ 'type' => $type, 'label' => self::getTypeLabel($type), 'data' => self::getTerakhirTerbitByType($type) ]; } return $allData; } /** * Format tanggal terbit for display */ public static function formatTanggalTerbit($tanggal): string { if ($tanggal instanceof Carbon) { return $tanggal->format('d M Y'); } return Carbon::parse($tanggal)->format('d M Y'); } }