diff --git a/app/Exports/DashboardDemografiExport.php b/app/Exports/DashboardDemografiExport.php new file mode 100644 index 0000000..a50f453 --- /dev/null +++ b/app/Exports/DashboardDemografiExport.php @@ -0,0 +1,85 @@ +data = $data; + } + + public function array(): array + { + return array_map(fn($d) => $d['row'], $this->data); + } + + public function styles(Worksheet $sheet) + { + foreach ($this->data as $index => $item) { + $rowNumber = $index + 1; + $rowType = $item['type']; + + switch ($rowType) { + + case 'title': + $sheet->getStyle("A{$rowNumber}") + ->applyFromArray([ + 'font' => [ + 'bold' => true, + 'size' => 14, + ] + ]); + break; + + case 'header': + $sheet->getStyle("A{$rowNumber}:C{$rowNumber}") + ->applyFromArray([ + 'font' => [ + 'bold' => true, + 'size' => 12 + ], + 'fill' => [ + 'fillType' => 'solid', + 'color' => ['rgb' => 'FFFF99'] + ] + ]); + break; + + case 'body': + $sheet->getStyle("A{$rowNumber}:C{$rowNumber}") + ->applyFromArray([ + 'font' => [ + 'size' => 11 + ] + ]); + break; + } + } + + // APPLY BORDER HANYA UNTUK ROW NON-EMPTY + foreach ($this->data as $i => $item) { + if ($item['type'] === 'empty') continue; // ❌ skip border + + $row = $i + 1; + $sheet->getStyle("A{$row}:C{$row}") + ->applyFromArray([ + 'borders' => [ + 'allBorders' => [ + 'borderStyle' => Border::BORDER_THIN, + 'color' => ['rgb' => '000000'] + ] + ] + ]); + } + + return []; + } +} diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index bf88fdc..2736903 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Exports\DashboardAnalisisExport; +use App\Exports\DashboardDemografiExport; use App\Exports\DashboardExport; use App\Exports\DashboardJawabanExport; use App\Models\Jawaban; @@ -386,7 +387,7 @@ class AdminController extends Controller foreach ($soal as $key => $value) { $jawaban = []; $soal_json = json_decode($value['soal'], true); - if($soal_json['is_analitic'] == 0){ + if($soal_json['is_analitic'] != 1){ continue; } @@ -568,7 +569,7 @@ class AdminController extends Controller foreach ($soal as $key => $value) { $jawaban = []; $soal_json = json_decode($value['soal'], true); - if($soal_json['is_analitic'] == 0){ + if($soal_json['is_analitic'] != 1){ continue; } @@ -862,4 +863,509 @@ class AdminController extends Controller return Excel::download(new DashboardJawabanExport($data_header, $data), 'data jawaban pegawai.xlsx'); } + + + public function get_data_pegawai_jawaban(Request $request) + { + $query = Jawaban::query(); + + if ($request->nama_pegawai) { + $query->where('nama', 'ILIKE', '%' . $request->nama_pegawai . '%'); + } + + if ($request->unit_kerja) { + $query->whereIn('unit', $request->unit_kerja); + } + + return DataTables::of($query) + ->addColumn('action', function ($row) { + return ' + + '; + }) + ->make(true); + + } + + public function dashboard_demografi() + { + $data['list_unit_kerja'] = [ + "Direktur Utama dan Direksi", + "Satuan Pengawas Internal", + "Komite Mutu", + "Komite Medik", + "Komite Keperawatan", + "Komite PPI & PRA", + "KTKL", + "KFT", + "KEH", + "ULP", + "Timker Yankep", + "Timker Yanjang", + "Timker Perencanaan, Evaluasi dan Program", + "Timker Hukum dan Humas", + "Timker Yanmed", + "Timker Perencanaan dan Evaluasi Anggaran", + "Timker Akutansi dan BMN", + "Timker Organisasi dan Sumber Daya Manusia", + "Timker TU & RT", + "Timker Diklat", + "Timker Penelitian", + "Timker Pelaksanan Keuangan", + "Instalasi Rawat Inap", + "Instalasi Rawat Jalan Reguler", + "Instalasi Rawat Intensif / ICU", + "Instalasi Rehabilitasi Medik", + "Instalasi Gizi", + "Instalasi Laboratorium Terpadu", + "Instalasi Sistem Informasi Manajemen Rumah Sakit (SIMRS)", + "Instalasi Bedah Sentral", + "Instalasi Radiologi", + "Instalasi Farmasi", + "Instalasi Rekam Medis", + "Instalasi Gawat Darurat", + "Instalasi Verifikasi dan Penjaminan Pasien", + "Instalasi KL & K3RS", + "ISSB", + "IPT", + "IPJNI", + "IPSPRS", + "IPPB", + "IPPISGB", + "Instalasi Rawat Jalan Eksekutif", + "Instalasi Teknologi Berbantu (TRB)", + "Klinik Utama Bintaro", + "KSM Anak", + "KSM Obstetri & Ginekologi", + "KSM Bedah", + "KSM Anestesi", + "KSM Gigi & Mulut", + "KSM Spesialis Lain", + "KSM Umum", + "Lainnya (Mahasiswa dan Outsourcing)" + ]; + return view('admin.dashboard_demografi', $data); + } + + public function get_data_dashboard_demografi(Request $request) + { + try { + $soal = SoalDetail::all()->sortBy('id')->values()->toArray(); + + $data = []; + $data_all = []; + $total = 0; + + foreach ($soal as $key => $value) { + $jawaban = []; + $soal_json = json_decode($value['soal'], true); + if($soal_json['is_analitic'] != 2){ + continue; + } + + $sub = DB::table('lms_mutu_jawaban_detail') + ->select('lms_mutu_soal_detail_id', DB::raw('COUNT(*) AS total_semua')) + ->join( + 'lms_mutu_jawaban', + 'lms_mutu_jawaban_detail.lms_mutu_jawaban_id', + '=', + 'lms_mutu_jawaban.id' + ) + ->where('lms_mutu_soal_detail_id', $value['id']) + ->where('jawaban', '!=', null); + if($request->unit_kerja) { + $sub->whereIn('lms_mutu_jawaban.unit', $request->unit_kerja); + } + $sub->groupBy('lms_mutu_soal_detail_id'); + + $result = DB::table('lms_mutu_jawaban_detail AS d') + ->joinSub($sub, 't', function($join) { + $join->on('t.lms_mutu_soal_detail_id', '=', 'd.lms_mutu_soal_detail_id'); + }) + ->join( + 'lms_mutu_jawaban', + 'd.lms_mutu_jawaban_id', + '=', + 'lms_mutu_jawaban.id' + ) + ->selectRaw( + 'd.lms_mutu_soal_detail_id, + d.jawaban, + COUNT(*) AS total_jawaban, + t.total_semua, + ROUND((COUNT(*)::numeric / t.total_semua::numeric) * 100) AS percent' + ) + ->where('d.lms_mutu_soal_detail_id', $value['id']) + ->where('d.jawaban', '!=', null) + ->groupBy('d.lms_mutu_soal_detail_id', 'd.jawaban', 't.total_semua'); + if($request->unit_kerja) { + $result->whereIn('lms_mutu_jawaban.unit', $request->unit_kerja); + } + $result->orderBy('d.lms_mutu_soal_detail_id', 'asc'); + + if(is_array($soal_json['options'])){ + if(count($soal_json['options']) > 0){ + foreach ($soal_json['options'] as $v) { + + if($v != 'Lainnya'){ + $row = (clone $result)->where('d.jawaban', $v) + ->first(); + + if($row) { + if($total == 0){ + $total = $row->total_semua; + } + $data_per_jawaban = [ + 'name' => $v, + 'percent' => (float) $row->percent, + 'value' => $row->total_jawaban, + 'total' => $row->total_semua + ]; + + array_push($jawaban, $data_per_jawaban); + } else { + $data_per_jawaban = [ + 'name' => $v, + 'percent' => 0 + ]; + array_push($jawaban, $data_per_jawaban); + } + } else { + $get_data = DB::table('lms_mutu_jawaban_detail AS d') + ->joinSub($sub, 't', function($join) { + $join->on('t.lms_mutu_soal_detail_id', '=', 'd.lms_mutu_soal_detail_id'); + }) + ->join( + 'lms_mutu_jawaban', + 'd.lms_mutu_jawaban_id', + '=', + 'lms_mutu_jawaban.id' + ) + ->selectRaw( + "d.lms_mutu_soal_detail_id, + STRING_AGG(d.jawaban, ', ') AS jawaban_gabungan, + t.total_semua, + COUNT(*) AS total_jawaban, + ROUND((COUNT(*)::numeric / t.total_semua::numeric) * 100) AS percent" + ) + ->where('d.lms_mutu_soal_detail_id', $value['id']) + ->where('jawaban', '!=', null) + ->whereNotIn('d.jawaban', $soal_json['options']) + ->groupBy('d.lms_mutu_soal_detail_id', 't.total_semua')->first(); + + // $get_data = (clone $result)->whereNotIn('d.jawaban', $soal_json['options']) + // ->get() + // ->toArray(); + + // foreach ($get_data as $val) { + if($get_data){ + $data_per_jawaban = [ + 'name' => 'Lainnya', + 'percent' => (float) $get_data->percent, + 'value' => $get_data->total_jawaban, + 'total' => $get_data->total_semua, + 'jawaban' => $get_data->jawaban_gabungan + ]; + } else { + $data_per_jawaban = [ + 'name' => 'Lainnya', + 'percent' => 0, + 'value' => 0, + 'jawaban' => '-' + ]; + } + // } + array_push($jawaban, $data_per_jawaban); + } + } + } else { + $get_data = $result->get() + ->toArray(); + foreach ($get_data as $val) { + $data_per_jawaban = [ + 'name' => $val->jawaban, + 'percent' => (float) $val->percent, + 'value' => $val->total_jawaban, + 'total' => $val->total_semua + ]; + array_push($jawaban, $data_per_jawaban); + } + } + + $data_persoal = [ + 'no_soal' => $soal_json['no'], + 'soal' => $soal_json['soal'], + 'jawaban' => $jawaban + ]; + + array_push($data_all, $data_persoal); + } + } + + $data = [ + 'data' => $data_all, + 'total' => $total + ]; + + return response()->json([ + 'msg' => 'Berhasil', + 'data' => $data + ], 200); + } catch (\ErrorException $th) { + dd($th); + return response()->json([ + 'msg' => 'Oops something wrong!', + 'data' => null, + 'msg_dev' => $th + ], 500); + } + } + + public function download_report_dashboard_demografi(Request $request) + { + $soal = SoalDetail::all()->sortBy('id')->values()->toArray(); + + $data = []; + $data_all = []; + $total = 0; + + foreach ($soal as $key => $value) { + $jawaban = []; + $soal_json = json_decode($value['soal'], true); + if($soal_json['is_analitic'] != 2){ + continue; + } + $sub = DB::table('lms_mutu_jawaban_detail') + ->select('lms_mutu_soal_detail_id', DB::raw('COUNT(*) AS total_semua')) + ->join( + 'lms_mutu_jawaban', + 'lms_mutu_jawaban_detail.lms_mutu_jawaban_id', + '=', + 'lms_mutu_jawaban.id' + ) + ->where('lms_mutu_soal_detail_id', $value['id']) + ->where('jawaban', '!=', null); + if($request->unit_kerja) { + $sub->whereIn('lms_mutu_jawaban.unit', $request->unit_kerja); + } + $sub->groupBy('lms_mutu_soal_detail_id'); + $result = DB::table('lms_mutu_jawaban_detail AS d') + ->joinSub($sub, 't', function($join) { + $join->on('t.lms_mutu_soal_detail_id', '=', 'd.lms_mutu_soal_detail_id'); + }) + ->join( + 'lms_mutu_jawaban', + 'd.lms_mutu_jawaban_id', + '=', + 'lms_mutu_jawaban.id' + ) + ->selectRaw( + 'd.lms_mutu_soal_detail_id, + d.jawaban, + COUNT(*) AS total_jawaban, + t.total_semua, + ROUND((COUNT(*)::numeric / t.total_semua::numeric) * 100) AS percent' + ) + ->where('d.lms_mutu_soal_detail_id', $value['id']) + ->where('d.jawaban', '!=', null) + ->groupBy('d.lms_mutu_soal_detail_id', 'd.jawaban', 't.total_semua'); + if($request->unit_kerja) { + $result->whereIn('lms_mutu_jawaban.unit', $request->unit_kerja); + } + $result->orderBy('d.lms_mutu_soal_detail_id', 'asc'); + + if(is_array($soal_json['options'])){ + if(count($soal_json['options']) > 0){ + foreach ($soal_json['options'] as $v) { + + if($v != 'Lainnya'){ + $row = (clone $result)->where('d.jawaban', $v) + ->first(); + + if($row) { + if($total == 0){ + $total = $row->total_semua; + } + $data_per_jawaban = [ + 'name' => $v, + 'percent' => (float) $row->percent, + 'value' => $row->total_jawaban, + 'total' => $row->total_semua + ]; + + array_push($jawaban, $data_per_jawaban); + } else { + $data_per_jawaban = [ + 'name' => $v, + 'percent' => 0 + ]; + array_push($jawaban, $data_per_jawaban); + } + } else { + $get_data = DB::table('lms_mutu_jawaban_detail AS d') + ->joinSub($sub, 't', function($join) { + $join->on('t.lms_mutu_soal_detail_id', '=', 'd.lms_mutu_soal_detail_id'); + }) + ->join( + 'lms_mutu_jawaban', + 'd.lms_mutu_jawaban_id', + '=', + 'lms_mutu_jawaban.id' + ) + ->selectRaw( + "d.lms_mutu_soal_detail_id, + STRING_AGG(d.jawaban, ', ') AS jawaban_gabungan, + t.total_semua, + COUNT(*) AS total_jawaban, + ROUND((COUNT(*)::numeric / t.total_semua::numeric) * 100) AS percent" + ) + ->where('d.lms_mutu_soal_detail_id', $value['id']) + ->where('jawaban', '!=', null) + ->whereNotIn('d.jawaban', $soal_json['options']) + ->groupBy('d.lms_mutu_soal_detail_id', 't.total_semua')->first(); + + // $get_data = (clone $result)->whereNotIn('d.jawaban', $soal_json['options']) + // ->get() + // ->toArray(); + + // foreach ($get_data as $val) { + if($get_data){ + $data_per_jawaban = [ + 'name' => 'Lainnya', + 'percent' => (float) $get_data->percent, + 'value' => $get_data->total_jawaban, + 'total' => $get_data->total_semua, + 'jawaban' => $get_data->jawaban_gabungan + ]; + } else { + $data_per_jawaban = [ + 'name' => 'Lainnya', + 'percent' => 0, + 'value' => 0, + 'jawaban' => '-' + ]; + } + // } + array_push($jawaban, $data_per_jawaban); + } + } + } else { + $get_data = $result->get() + ->toArray(); + foreach ($get_data as $val) { + $data_per_jawaban = [ + 'name' => $val->jawaban, + 'percent' => (float) $val->percent, + 'value' => $val->total_jawaban, + 'total' => $val->total_semua + ]; + array_push($jawaban, $data_per_jawaban); + } + } + + $data_persoal = [ + 'no_soal' => $soal_json['no'], + 'soal' => $soal_json['soal'], + 'jawaban' => $jawaban + ]; + + array_push($data_all, $data_persoal); + } + } + + $data_report = []; + foreach ($data_all as $index => $value) { + + // SOAL → tandai sebagai 'title' + $data_report[] = [ + 'type' => 'title', + 'row' => [$value['no_soal'] . ', ' . $value['soal']] + ]; + // HEADER TABLE → tandai sebagai 'header' + $data_report[] = [ + 'type' => 'header', + 'row' => ['Jawaban', 'Persentase Responden', 'Jumlah Responden'] + ]; + + if($value['no_soal'] != 7 && $value['no_soal'] != 8) { + // ISI TABEL → tandai sebagai 'body' + foreach ($value['jawaban'] as $v) { + $data_report[] = [ + 'type' => 'body', + 'row' => [$v['name'], $v['percent'] ?? '-', ($v['value'] ?? '0') .' Orang'] + ]; + } + } else { + $total = array_reduce($value['jawaban'], function($acc, $item) { + return $acc + $item['value']; + }, 0); + + $category = [ + [ + 'name' => '0 - 2 Tahun', + 'total' => $total, + 'percent' => 0, + 'value' => 0 + ], + [ + 'name' => '3 - 5 Tahun', + 'total' => $total, + 'percent' => 0, + 'value' => 0 + ], + [ + 'name' => '6 - 10 Tahun', + 'total' => $total, + 'percent' => 0, + 'value' => 0 + ], + [ + 'name' => '> 10 Tahun', + 'total' => $total, + 'percent' => 0, + 'value' => 0 + ], + ]; + + // set value + foreach ($value['jawaban'] as $v) { + $tahun = intval($v['name']); + + if($tahun <= 2){ + $category[0]['value'] += $v['value']; + } else if($tahun >= 3 && $tahun <= 5){ + $category[1]['value'] += $v['value']; + } else if($tahun >= 6 && $tahun <= 10) { + $category[2]['value'] += $v['value']; + } else { + $category[3]['value'] += $v['value']; + } + } + + $mappingPercent = array_map( + fn($val) => array_merge( + $val, + ['percent' => $val['total'] > 0 ? intval(($val['value'] / $val['total']) * 100) : null] + ), + $category + ); + + foreach ($mappingPercent as $i => $v) { + $data_report[] = [ + 'type' => 'body', + 'row' => [$v['name'], $v['percent'] ?? '-', ($v['value'] ?? '0') .' Orang'] + ]; + } + } + + // SPASER + $data_report[] = ['type' => 'empty', 'row' => ['']]; + $data_report[] = ['type' => 'empty', 'row' => ['']]; + $data_report[] = ['type' => 'empty', 'row' => ['']]; + } + + return Excel::download(new DashboardDemografiExport($data_report, 'Dashboard Demografi'), 'data demografi.xlsx'); + } } diff --git a/resources/views/admin/dashboard_demografi.blade.php b/resources/views/admin/dashboard_demografi.blade.php new file mode 100644 index 0000000..0ecd7f8 --- /dev/null +++ b/resources/views/admin/dashboard_demografi.blade.php @@ -0,0 +1,310 @@ +@extends('layouts.template_admin') + +@section('title', 'Dashboard | Mutu RSAB Harapan Kita') +@section('custom_css') +@endsection + +@section('content') +