diff --git a/app/Http/Controllers/Admin/AdminController.php b/app/Http/Controllers/Admin/AdminController.php index ebdd874..7449f61 100644 --- a/app/Http/Controllers/Admin/AdminController.php +++ b/app/Http/Controllers/Admin/AdminController.php @@ -27,7 +27,7 @@ public function dashboard() ->toArray(); // Pastikan semua status memiliki nilai, jika tidak ada datanya - $allStatuses = ['Menunggu', 'Diterima', 'Diproses', 'Selesai']; + $allStatuses = ['Menunggu', 'Diterima', 'Diproses', 'Selesai', 'Ditolak']; foreach ($allStatuses as $status) { if (!isset($serviceStats[$status])) { $serviceStats[$status] = 0; @@ -182,11 +182,20 @@ public function update(Request $request, User $admin) 'gender' => $request->gender, ]); + // Jika password baru diisi, validasi password lama if ($request->filled('password')) { $request->validate([ + 'current_password' => 'required|string', 'password' => 'required|string|min:8|confirmed', ]); + // Verifikasi password lama + if (!Hash::check($request->current_password, $admin->password)) { + return back() + ->withErrors(['current_password' => 'Password lama tidak sesuai']) + ->withInput(); + } + $admin->update([ 'password' => Hash::make($request->password), ]); diff --git a/app/Http/Controllers/ComplaintController.php b/app/Http/Controllers/ComplaintController.php index efd51e3..bd38845 100644 --- a/app/Http/Controllers/ComplaintController.php +++ b/app/Http/Controllers/ComplaintController.php @@ -7,6 +7,7 @@ use App\Http\Requests\UpdateComplaintRequest; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Barryvdh\DomPDF\Facade\PDF; class ComplaintController extends Controller { @@ -120,4 +121,60 @@ public function destroy(Complaint $complaint) return redirect()->route('complaints.index') ->with('success', 'Keluhan berhasil dihapus!'); } + + /** + * Generate PDF for a single complaint + */ + public function pdf(Complaint $complaint) + { + // Pastikan pengguna hanya bisa melihat keluhan miliknya sendiri atau admin + if (Auth::user()->role === 'pelanggan') { + if ($complaint->user_id !== Auth::id()) { + abort(403, 'Unauthorized action.'); + } + } + + $pdf = PDF::loadView('complaints.pdf', compact('complaint')); + return $pdf->download('keluhan-' . $complaint->id . '.pdf'); + } + + /** + * Generate PDF for all complaints (admin only) + */ + public function allPdf(Request $request) + { + // Hanya admin yang bisa akses + if (Auth::user()->role !== 'admin') { + abort(403, 'Unauthorized action.'); + } + + // Ambil semua data atau filter jika diperlukan + $complaints = Complaint::latest()->get(); + + // Jika ada filter, tambahkan ke array filters + $filters = []; + if ($request->filled('tanggal_mulai')) { + $complaints = $complaints->filter(function ($item) use ($request) { + return $item->created_at->format('Y-m-d') >= $request->tanggal_mulai; + }); + $filters['tanggal_mulai'] = $request->tanggal_mulai; + } + + if ($request->filled('tanggal_selesai')) { + $complaints = $complaints->filter(function ($item) use ($request) { + return $item->created_at->format('Y-m-d') <= $request->tanggal_selesai; + }); + $filters['tanggal_selesai'] = $request->tanggal_selesai; + } + + if ($request->filled('jenis_layanan')) { + $complaints = $complaints->filter(function ($item) use ($request) { + return $item->jenis_layanan == $request->jenis_layanan; + }); + $filters['jenis_layanan'] = $request->jenis_layanan; + } + + $pdf = PDF::loadView('complaints.all-pdf', compact('complaints', 'filters')); + return $pdf->download('semua-keluhan.pdf'); + } } diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index c1aeff6..2a7e1bc 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -26,6 +26,9 @@ public function home() $completedServices = Service::where('user_id', $user->id) ->where('status', 'Selesai') ->count(); + $rejectedServices = Service::where('user_id', $user->id) + ->where('status', 'Ditolak') + ->count(); // Mengambil layanan terbaru milik customer $latestServices = Service::where('user_id', $user->id) @@ -39,6 +42,7 @@ public function home() 'pendingServices', 'processedServices', 'completedServices', + 'rejectedServices', 'latestServices' )); } diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 5526b50..52a47b3 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -25,18 +25,18 @@ public function edit() public function update(Request $request) { $user = Auth::user(); - + // Validasi berbeda untuk admin dan customer if ($user->role === 'admin') { $request->validate([ 'name' => 'required|string|max:255', 'password' => 'nullable|string|min:8|confirmed', ]); - + // Data yang dapat diubah untuk admin - $data = [ - 'name' => $request->name, - ]; + User::where('id', $user->id)->update([ + 'name' => $request->name + ]); } else { // Untuk customer $request->validate([ @@ -45,20 +45,30 @@ public function update(Request $request) 'business_name' => 'required|string|max:255', 'business_address' => 'required|string', ]); - + // Data yang dapat diubah untuk customer - $data = [ + User::where('id', $user->id)->update([ 'name' => $request->name, 'business_name' => $request->business_name, - 'business_address' => $request->business_address, - ]; + 'business_address' => $request->business_address + ]); } - - $user->update($data); // Update password jika diisi if ($request->filled('password')) { - $user->update([ + // Validasi password lama + $request->validate([ + 'current_password' => 'required|string', + ]); + + // Verifikasi password lama + if (!Hash::check($request->current_password, $user->password)) { + return back() + ->withErrors(['current_password' => 'Password lama tidak sesuai']) + ->withInput(); + } + + User::where('id', $user->id)->update([ 'password' => Hash::make($request->password) ]); } diff --git a/app/Http/Controllers/SatisfactionController.php b/app/Http/Controllers/SatisfactionController.php index 9a1778a..fcb2a63 100644 --- a/app/Http/Controllers/SatisfactionController.php +++ b/app/Http/Controllers/SatisfactionController.php @@ -7,6 +7,7 @@ use App\Http\Requests\UpdateSatisfactionRequest; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Barryvdh\DomPDF\Facade\PDF; class SatisfactionController extends Controller { @@ -15,9 +16,9 @@ class SatisfactionController extends Controller */ public function index() { - if(Auth::user()->role === 'admin'){ + if (Auth::user()->role === 'admin') { $satisfactions = Satisfaction::latest()->paginate(10); - }else{ + } else { $satisfactions = Satisfaction::where('user_id', Auth::id())->latest()->paginate(10); } return view('satisfactions.index', compact('satisfactions')); @@ -28,13 +29,7 @@ public function index() */ public function create() { - // Cek apakah user sudah pernah mengisi kuesioner - $hasSurvey = Satisfaction::where('user_id', Auth::id())->exists(); - if ($hasSurvey) { - return redirect()->route('satisfactions.index') - ->with('warning', 'Anda sudah pernah mengisi kuesioner kepuasan pelanggan.'); - } - + // Kode lama yang membatasi satu kali pengisian per user telah dihapus return view('satisfactions.create'); } @@ -77,7 +72,7 @@ public function store(Request $request) public function show(Satisfaction $satisfaction) { // Pastikan pengguna hanya bisa melihat data survei miliknya sendiri - if(Auth::user()->role === 'pelanggan'){ + if (Auth::user()->role === 'pelanggan') { if ($satisfaction->user_id !== Auth::id()) { abort(403, 'Unauthorized action.'); } @@ -150,6 +145,69 @@ public function destroy(Satisfaction $satisfaction) ->with('success', 'Penilaian kepuasan pelanggan berhasil dihapus.'); } + /** + * Generate PDF for a single satisfaction + */ + public function pdf(Satisfaction $satisfaction) + { + // Pastikan pengguna hanya bisa melihat data survei miliknya sendiri atau admin + if (Auth::user()->role === 'pelanggan') { + if ($satisfaction->user_id !== Auth::id()) { + abort(403, 'Unauthorized action.'); + } + } + + $pdf = PDF::loadView('satisfactions.pdf', compact('satisfaction')); + return $pdf->download('penilaian-kepuasan-' . $satisfaction->id . '.pdf'); + } + + /** + * Generate PDF for all satisfactions (admin only) + */ + public function allPdf(Request $request) + { + // Hanya admin yang bisa akses + if (Auth::user()->role !== 'admin') { + abort(403, 'Unauthorized action.'); + } + + // Ambil semua data atau filter jika diperlukan + $satisfactions = Satisfaction::latest()->get(); + + // Jika ada filter, tambahkan ke array filters + $filters = []; + if ($request->filled('tanggal_mulai')) { + $satisfactions = $satisfactions->filter(function ($item) use ($request) { + return $item->created_at->format('Y-m-d') >= $request->tanggal_mulai; + }); + $filters['tanggal_mulai'] = $request->tanggal_mulai; + } + + if ($request->filled('tanggal_selesai')) { + $satisfactions = $satisfactions->filter(function ($item) use ($request) { + return $item->created_at->format('Y-m-d') <= $request->tanggal_selesai; + }); + $filters['tanggal_selesai'] = $request->tanggal_selesai; + } + + if ($request->filled('rating_min')) { + $satisfactions = $satisfactions->filter(function ($item) use ($request) { + return $item->average_score >= $request->rating_min; + }); + $filters['rating_min'] = $request->rating_min; + } + + if ($request->filled('rating_max')) { + $satisfactions = $satisfactions->filter(function ($item) use ($request) { + return $item->average_score <= $request->rating_max; + }); + $filters['rating_max'] = $request->rating_max; + } + + $pdf = PDF::loadView('satisfactions.all-pdf', compact('satisfactions', 'filters')); + return $pdf->download('semua-penilaian-kepuasan.pdf'); + } + /** * Display the admin dashboard for survey results */ diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php index fc0f8ce..91ad74f 100644 --- a/app/Http/Controllers/ServiceController.php +++ b/app/Http/Controllers/ServiceController.php @@ -184,6 +184,13 @@ public function update(Request $request, Service $service) $rules['biaya_retribusi_jarak'] = 'nullable|integer|min:0'; $rules['biaya_retribusi'] = 'nullable|integer|min:0'; + // Validasi keterangan jika status Diterima atau Ditolak + if (in_array($request->status, ['Diterima', 'Ditolak'])) { + $rules['keterangan'] = 'required|string|min:5'; + } else { + $rules['keterangan'] = 'nullable|string'; + } + // Validasi file hasil uji jika ada if ($request->hasFile('file_hasil_uji')) { $rules['file_hasil_uji'] = 'file|mimes:pdf,doc,docx,png,jpg,jpeg|max:10240'; diff --git a/app/Models/Service.php b/app/Models/Service.php index 78f948c..df5b2a5 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -23,6 +23,7 @@ class Service extends Model 'biaya_retribusi_jarak', 'biaya_retribusi', 'file_hasil_uji', + 'keterangan', ]; /** diff --git a/config/app.php b/config/app.php index 9207160..f43851e 100644 --- a/config/app.php +++ b/config/app.php @@ -70,7 +70,7 @@ | */ - 'timezone' => 'UTC', + 'timezone' => 'Asia/Jakarta', /* |-------------------------------------------------------------------------- @@ -83,7 +83,7 @@ | */ - 'locale' => 'en', + 'locale' => 'id', /* |-------------------------------------------------------------------------- @@ -96,7 +96,7 @@ | */ - 'fallback_locale' => 'en', + 'fallback_locale' => 'id', /* |-------------------------------------------------------------------------- @@ -109,7 +109,7 @@ | */ - 'faker_locale' => 'en_US', + 'faker_locale' => 'id_ID', /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2025_04_26_120229_add_keterangan_to_services_table.php b/database/migrations/2025_04_26_120229_add_keterangan_to_services_table.php new file mode 100644 index 0000000..af071a5 --- /dev/null +++ b/database/migrations/2025_04_26_120229_add_keterangan_to_services_table.php @@ -0,0 +1,49 @@ +text('keterangan')->nullable()->after('file_hasil_uji'); + + // Drop dan recreate kolom status untuk menambahkan opsi 'Ditolak' + $table->dropColumn('status'); + }); + + // Membuat ulang kolom status dengan enum yang diperbarui + Schema::table('services', function (Blueprint $table) { + $table->enum('status', ['Menunggu', 'Diterima', 'Diproses', 'Selesai', 'Ditolak']) + ->default('Menunggu') + ->nullable() + ->after('jarak_pengambilan_sampel'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('services', function (Blueprint $table) { + $table->dropColumn('keterangan'); + + // Drop dan recreate kolom status tanpa opsi 'Ditolak' + $table->dropColumn('status'); + }); + + // Membuat ulang kolom status dengan enum original + Schema::table('services', function (Blueprint $table) { + $table->enum('status', ['Menunggu', 'Diterima', 'Diproses', 'Selesai']) + ->default('Menunggu') + ->nullable() + ->after('jarak_pengambilan_sampel'); + }); + } +}; diff --git a/public/images/logo1.png b/public/images/logo1.png index 95498c6..fdcba6b 100644 Binary files a/public/images/logo1.png and b/public/images/logo1.png differ diff --git a/public/images/logo4.png b/public/images/logo4.png new file mode 100644 index 0000000..53d7b52 Binary files /dev/null and b/public/images/logo4.png differ diff --git a/public/images/logo5.png b/public/images/logo5.png new file mode 100644 index 0000000..7ac54da Binary files /dev/null and b/public/images/logo5.png differ diff --git a/public/images/logobulat.jpg b/public/images/logobulat.jpg index 15e24b4..c68e16f 100644 Binary files a/public/images/logobulat.jpg and b/public/images/logobulat.jpg differ diff --git a/resources/views/Dashboard/layouts/main.blade.php b/resources/views/Dashboard/layouts/main.blade.php index ba91638..b140f17 100644 --- a/resources/views/Dashboard/layouts/main.blade.php +++ b/resources/views/Dashboard/layouts/main.blade.php @@ -2,13 +2,13 @@
-Diterima
-Diproses
Selesai
Ditolak
+Dicetak pada: {{ date('d-m-Y H:i:s') }}
+Filter yang digunakan:
+No | +Nama | +Jenis Layanan | +Tanggal Keluhan | +Tanggal Dibuat | +Uraian Keluhan | +Saran | +
---|---|---|---|---|---|---|
{{ $key + 1 }} | +{{ $complaint->user->name }} | +{{ $complaint->jenis_layanan }} | +{{ \Carbon\Carbon::parse($complaint->tanggal_keluhan)->format('d M Y') }} | +{{ $complaint->created_at->format('d M Y') }} | +{{ Str::limit($complaint->uraian_keluhan, 100) }} | +{{ Str::limit($complaint->saran, 100) }} | +
Tidak ada data keluhan | +
Total Keluhan | +{{ $complaints->count() }} | +
Keluhan Bulan Ini | +{{ $complaints->filter(function($item) { return $item->created_at->isCurrentMonth(); })->count() }} | +
Jenis Layanan Terbanyak | ++ @php + $serviceCounts = []; + foreach ($complaints as $complaint) { + if (!isset($serviceCounts[$complaint->jenis_layanan])) { + $serviceCounts[$complaint->jenis_layanan] = 0; + } + $serviceCounts[$complaint->jenis_layanan]++; + } + arsort($serviceCounts); + $topService = key($serviceCounts); + $topCount = reset($serviceCounts); + @endphp + {{ $complaints->count() > 0 ? $topService . ' (' . $topCount . ')' : '-' }} + | +
No | Jenis Layanan | Tanggal Keluhan | -Uraian Keluhan | Tanggal Dibuat | Aksi | @@ -60,24 +132,22 @@{{ $index + $complaints->firstItem() }} | {{ $complaint->jenis_layanan }} | {{ \Carbon\Carbon::parse($complaint->tanggal_keluhan)->format('d-m-Y') }} | -{{ \Illuminate\Support\Str::limit($complaint->uraian_keluhan, 50) }} | {{ $complaint->created_at->format('d-m-Y H:i') }} | @@ -102,4 +172,7 @@ + + +@include('layouts.delete-modal') @endsection \ No newline at end of file diff --git a/resources/views/complaints/pdf.blade.php b/resources/views/complaints/pdf.blade.php new file mode 100644 index 0000000..01a2837 --- /dev/null +++ b/resources/views/complaints/pdf.blade.php @@ -0,0 +1,130 @@ + + + + + |
---|
Nama | +{{ $complaint->user->name }} | +
{{ $complaint->user->email }} | +|
No. HP | +{{ $complaint->user->phone ?? '-' }} | +
Nama Badan Usaha | +{{ $complaint->user->business_name ?? '-' }} | +
Jenis Layanan | +{{ $complaint->jenis_layanan }} | +
Tanggal Keluhan | +{{ \Carbon\Carbon::parse($complaint->tanggal_keluhan)->format('d F Y') }} | +
Tanggal Dibuat | +{{ $complaint->created_at->format('d F Y, H:i') }} | +
Sistem ini memungkinkan Anda melakukan permintaan pengambilan dan pengujian sampel air. Kami siap melayani Anda dengan profesional dan memberikan hasil uji yang akurat. + Setelah pendaftaran uji kualitas air, kami akan menginformasikan lebih lanjut mengenai proses pengujian paling lambat 3 hari kerja.
Profil Anda telah terdaftar sebagai: @@ -48,7 +49,7 @@ Ajukan Permintaan Pengujian Baru - + Edit Profil @@ -98,7 +99,7 @@ -
Dicetak pada: {{ date('d-m-Y H:i:s') }}
+Filter yang digunakan:
+No | +Nama | +Tanggal Pengisian | +Nilai Rata-rata | +Q1 | +Q2 | +Q3 | +Q4 | +Q5 | +Q6 | +Q7 | +Q8 | +Q9 | +Q10 | +Q11 | +Q12 | +Q13 | +Q14 | +Q15 | +|
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
{{ $key + 1 }} | +{{ $satisfaction->user->name }} | +{{ $satisfaction->created_at->format('d M Y') }} | ++ {{ number_format($satisfaction->average_score, 1) }} + | +{{ $satisfaction->q1 }} | +{{ $satisfaction->q2 }} | +{{ $satisfaction->q3 }} | +{{ $satisfaction->q4 }} | +{{ $satisfaction->q5 }} | +{{ $satisfaction->q6 }} | +{{ $satisfaction->q7 }} | +{{ $satisfaction->q8 }} | +{{ $satisfaction->q9 }} | +{{ $satisfaction->q10 }} | +{{ $satisfaction->q11 }} | +{{ $satisfaction->q12 }} | +{{ $satisfaction->q13 }} | +{{ $satisfaction->q14 }} | +{{ $satisfaction->q15 }} | +|
Tidak ada data penilaian kepuasan | +
Total Penilaian | +{{ $satisfactions->count() }} | +
Rata-rata Keseluruhan | +{{ number_format($satisfactions->avg('average_score'), 2) }} | +
Nilai Tertinggi | +{{ number_format($satisfactions->max('average_score'), 2) }} | +
Nilai Terendah | +{{ number_format($satisfactions->min('average_score'), 2) }} | +
Jumlah Penilaian Sangat Baik (>=4) | +{{ $satisfactions->filter(function($item) { return $item->average_score >= 4; })->count() }} | +
Jumlah Penilaian Baik (>=3) | +{{ $satisfactions->filter(function($item) { return $item->average_score >= 3 && $item->average_score < 4; })->count() }} | +
Jumlah Penilaian Cukup (>=2) | +{{ $satisfactions->filter(function($item) { return $item->average_score >= 2 && $item->average_score < 3; })->count() }} | +
Jumlah Penilaian Kurang (<2) | +{{ $satisfactions->filter(function($item) { return $item->average_score < 2; })->count() }} | +
Nama | +{{ $satisfaction->user->name }} | +
{{ $satisfaction->user->email }} | +|
Waktu Pengisian | +{{ $satisfaction->created_at->format('d F Y, H:i') }} | +
No | +Pertanyaan | +Nilai | +
---|---|---|
1 | +Kesesuaian persyarataran pelayanan dengan jenis pelayanan | +{{ $satisfaction->q1 }} | +
2 | +Kejelasan persyaratan administrasi yang dibutuhkan | +{{ $satisfaction->q2 }} | +
3 | +Kemudahan prosedur mendapatkan pelayanan di unit ini | +{{ $satisfaction->q3 }} | +
4 | +Kecepatan waktu dalam memberikan pelayanan | +{{ $satisfaction->q4 }} | +
5 | +Ketepatan waktu jam buka pelayanan sesuai standar | +{{ $satisfaction->q5 }} | +
6 | +Kewajaran biaya/tarif dalam pelayanan | +{{ $satisfaction->q6 }} | +
7 | +Kesesuaian produk hasil pelayanan dengan standar pelayanan | +{{ $satisfaction->q7 }} | +
8 | +Kompetensi/kemampuan petugas dalam pelayanan | +{{ $satisfaction->q8 }} | +
9 | +Kesopanan dan keramahan petugas dalam memberikan pelayanan | +{{ $satisfaction->q9 }} | +
10 | +Kualitas sarana dan prasarana pelayanan | +{{ $satisfaction->q10 }} | +
11 | +Kebersihan dan kenyamanan ruang pelayanan | +{{ $satisfaction->q11 }} | +
12 | +Kebersihan kamar mandi atau toilet | +{{ $satisfaction->q12 }} | +
13 | +Kecukupan luas, kenyamanan dan keamanan tempat parkir | +{{ $satisfaction->q13 }} | +
14 | +Penanganan saran dan pengaduan pengguna layanan | +{{ $satisfaction->q14 }} | +
15 | +Kemudahan akses sarana pengaduan (kotak saran/telepon/email) | +{{ $satisfaction->q15 }} | +
Dicetak pada: {{ date('d-m-Y H:i:s') }}
{{ $service->keterangan }}
+