This commit is contained in:
ilhamrandikesuma 2025-04-26 20:56:24 +08:00
parent f7c0f9b83f
commit 1315c02a87
39 changed files with 1552 additions and 113 deletions

View File

@ -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),
]);

View File

@ -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');
}
}

View File

@ -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'
));
}

View File

@ -34,9 +34,9 @@ public function update(Request $request)
]);
// Data yang dapat diubah untuk admin
$data = [
'name' => $request->name,
];
User::where('id', $user->id)->update([
'name' => $request->name
]);
} else {
// Untuk customer
$request->validate([
@ -47,18 +47,28 @@ public function update(Request $request)
]);
// 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)
]);
}

View File

@ -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
{
@ -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');
}
@ -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
*/

View File

@ -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';

View File

@ -23,6 +23,7 @@ class Service extends Model
'biaya_retribusi_jarak',
'biaya_retribusi',
'file_hasil_uji',
'keterangan',
];
/**

View File

@ -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',
/*
|--------------------------------------------------------------------------

View File

@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('services', function (Blueprint $table) {
$table->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');
});
}
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
public/images/logo4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 KiB

BIN
public/images/logo5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 158 KiB

View File

@ -2,13 +2,13 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@yield('title') | YudhaAsrama</title>
<title>@yield('title') | UPTD. LABLING DLH KOTA PROBOLINGGO</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="Sistem Informasi Manajemen Asrama" name="description" />
<meta content="Yudha Developer" name="author" />
<meta content="UPTD. LABLING DLH KOTA PROBOLINGGO" name="description" />
<meta content="UPTD. LABLING DLH KOTA PROBOLINGGO" name="author" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- App favicon -->
<link rel="shortcut icon" href="{{ asset('DB/assets/images/favicon.ico') }}">
<link rel="shortcut icon" href="{{ asset('images/logo2.png') }}">
<!-- Datatables css -->
<link href="{{ asset('DB/assets/libs/datatables/dataTables.bootstrap4.css') }}" rel="stylesheet" type="text/css" />

View File

@ -3,7 +3,10 @@
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
&copy; {{ date('Y') }} - YudhaAsrama by <a href="">Yudha Developer</a>
&copy; {{ date('Y') }}
-
{{-- - Pengujian Air by --}}
<a href="">UPTD Laboratorium Lingkungan Pada Dinas Lingkungan Hidup Kota Probolinggo</a>
</div>
</div>
</div>

View File

@ -64,14 +64,14 @@ function toggleFullScreen() {
<!-- LOGO -->
<div class="logo-box">
<a href="index.html" class="logo text-center">
<a href="/" class="logo text-center">
<span class="logo-lg">
<img src="{{ asset('images/logo3.png') }}" alt="" height="75" style="margin-top: 10px;">
<img src="{{ asset('images/logo5.png') }}" alt="" height="75" style="margin-top: 10px;">
{{-- <span class="logo-lg-text-light">UPTD Laboratorium Lingkungan Pada Dinas Lingkungan Hidup Kota Probolinggo</span> --}}
</span>
<span class="logo-sm">
<span class="logo-sm-text-dark"></span>
<img src="{{ asset('images/logo2.png') }}" alt="" height="28">
<img src="{{ asset('images/logo4.png') }}" alt="" height="28">
</span>
</a>
</div>

View File

@ -126,18 +126,24 @@
</h3>
<p class="text-muted font-13 mb-0">Diterima</p>
</div>
<div class="col-md-6">
<div class="col-md-4">
<h3 class="font-weight-light">
<span data-plugin="counterup">{{ $serviceStats['Diproses'] }}</span>
</h3>
<p class="text-muted font-13 mb-0">Diproses</p>
</div>
<div class="col-md-6">
<div class="col-md-4">
<h3 class="font-weight-light">
<span data-plugin="counterup">{{ $serviceStats['Selesai'] }}</span>
</h3>
<p class="text-muted font-13 mb-0">Selesai</p>
</div>
<div class="col-md-4">
<h3 class="font-weight-light">
<span data-plugin="counterup">{{ $serviceStats['Ditolak'] }}</span>
</h3>
<p class="text-muted font-13 mb-0">Ditolak</p>
</div>
</div>
<div id="morris-donut-example" style="height: 320px;" class="morris-chart mt-3"></div>
@ -197,6 +203,8 @@
<span class="badge badge-primary">Diproses</span>
@elseif($service->status == 'Selesai')
<span class="badge badge-success">Selesai</span>
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@endif
</td>
<td>
@ -264,12 +272,24 @@
{label: "Menunggu", value: {{ $serviceStats['Menunggu'] }}},
{label: "Diterima", value: {{ $serviceStats['Diterima'] }}},
{label: "Diproses", value: {{ $serviceStats['Diproses'] }}},
{label: "Selesai", value: {{ $serviceStats['Selesai'] }}}
{label: "Selesai", value: {{ $serviceStats['Selesai'] }}},
{label: "Ditolak", value: {{ $serviceStats['Ditolak'] }}}
],
colors: ['#ffbd4a', '#4fc6e1', '#6658dd', '#1abc9c'],
colors: ['#ffbd4a', '#4fc6e1', '#6658dd', '#1abc9c', '#d9534f'],
resize: true
});
// Menentukan nilai maksimum untuk grafik bar
var maxValue = Math.max(
@foreach($waterTestTypes as $type => $count)
{{ $count }},
@endforeach
0
);
// Menentukan jumlah garis untuk grafik berdasarkan nilai maksimum
var numLines = maxValue <= 1 ? 2 : Math.ceil(maxValue) + 1;
// Morris Bar Chart - Distribusi Pengujian Kualitas Air
Morris.Bar({
element: 'morris-bar-example',
@ -285,7 +305,13 @@
hideHover: 'auto',
resize: true,
gridLineColor: '#eef0f2',
barColors: ['#4a81d4']
barColors: ['#4a81d4'],
ymax: maxValue <= 1 ? 1 : Math.ceil(maxValue),
ymin: 0,
numLines: numLines,
yLabelFormat: function(y) {
return Math.round(y); // Hanya menampilkan angka bulat
}
});
// Morris Pie Chart - Jenis Permintaan

View File

@ -56,9 +56,34 @@
</div>
<div class="form-group">
<label for="password">Password <small class="text-muted">(Kosongkan jika tidak ingin mengubah password)</small></label>
<label for="current_password">Password Lama <small class="text-muted">(Diperlukan untuk mengubah password)</small></label>
<div class="input-group">
<input type="password" class="form-control @error('current_password') is-invalid @enderror"
id="current_password" name="current_password">
<div class="input-group-append">
<button class="btn btn-secondary toggle-password" type="button" data-target="current_password">
<i class="mdi mdi-eye"></i>
</button>
</div>
</div>
@error('current_password')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
<div class="form-group">
<label for="password">Password Baru <small class="text-muted">(Kosongkan jika tidak ingin mengubah password)</small></label>
<div class="input-group">
<input type="password" class="form-control @error('password') is-invalid @enderror"
id="password" name="password">
<div class="input-group-append">
<button class="btn btn-secondary toggle-password" type="button" data-target="password">
<i class="mdi mdi-eye"></i>
</button>
</div>
</div>
@error('password')
<div class="invalid-feedback">
{{ $message }}
@ -67,9 +92,16 @@
</div>
<div class="form-group">
<label for="password_confirmation">Konfirmasi Password</label>
<label for="password_confirmation">Konfirmasi Password Baru</label>
<div class="input-group">
<input type="password" class="form-control"
id="password_confirmation" name="password_confirmation">
<div class="input-group-append">
<button class="btn btn-secondary toggle-password" type="button" data-target="password_confirmation">
<i class="mdi mdi-eye"></i>
</button>
</div>
</div>
</div>
<div class="form-group text-right mb-0">
@ -81,3 +113,23 @@
</div>
</div>
@endsection
@section('scripts')
<script>
$(document).ready(function() {
$('.toggle-password').click(function() {
var target = $(this).data('target');
var input = $('#' + target);
var icon = $(this).find('i');
if (input.attr('type') === 'password') {
input.attr('type', 'text');
icon.removeClass('mdi-eye').addClass('mdi-eye-off');
} else {
input.attr('type', 'password');
icon.removeClass('mdi-eye-off').addClass('mdi-eye');
}
});
});
</script>
@endsection

View File

@ -65,13 +65,9 @@
</a>
@if(auth()->id() !== $admin->id)
<form action="{{ route('admin.admins.destroy', $admin->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Anda yakin ingin menghapus admin ini?')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger">
<button type="button" class="btn btn-sm btn-danger" onclick="confirmDelete('{{ route('admin.admins.destroy', $admin->id) }}')">
<i class="fe-trash-2"></i> Hapus
</button>
</form>
@endif
</td>
</tr>
@ -82,6 +78,9 @@
</div>
</div>
</div>
<!-- Sertakan Modal Konfirmasi Hapus -->
@include('layouts.delete-modal')
@endsection
@section('scripts')

View File

@ -24,9 +24,13 @@
@enderror
</div>
<div class="mb-3">
<div class="mb-3 position-relative">
<input type="password" class="form-control @error('password') is-invalid @enderror"
placeholder="Masukkan Password Anda" name="password" required>
placeholder="Masukkan Password Anda" name="password" id="password" required>
<span class="position-absolute top-50 end-0 translate-middle-y me-2 password-toggle"
onclick="togglePassword('password')" style="cursor: pointer;">
<i class="bi bi-eye-slash" id="password-icon"></i>
</span>
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>

View File

@ -83,9 +83,13 @@
@enderror
</div>
<div class="mb-3">
<div class="mb-3 position-relative">
<input type="password" class="form-control @error('password') is-invalid @enderror"
placeholder="Masukkan Password" name="password" required>
placeholder="Masukkan Password" name="password" id="password" required>
<span class="position-absolute top-50 end-0 translate-middle-y me-2 password-toggle"
onclick="togglePassword('password')" style="cursor: pointer;">
<i class="bi bi-eye-slash" id="password-icon"></i>
</span>
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
@ -93,9 +97,13 @@
@enderror
</div>
<div class="mb-3">
<div class="mb-3 position-relative">
<input type="password" class="form-control"
placeholder="Konfirmasi Password" name="password_confirmation" required>
placeholder="Konfirmasi Password" name="password_confirmation" id="password_confirmation" required>
<span class="position-absolute top-50 end-0 translate-middle-y me-2 password-toggle"
onclick="togglePassword('password_confirmation')" style="cursor: pointer;">
<i class="bi bi-eye-slash" id="password_confirmation-icon"></i>
</span>
</div>
<button type="submit" class="btn btn-auth">REGISTER</button>

View File

@ -0,0 +1,158 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Daftar Keluhan</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.header {
text-align: center;
margin-bottom: 20px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.logo {
max-width: 150px;
margin-bottom: 10px;
}
h1 {
font-size: 20px;
margin-bottom: 5px;
}
.info-section {
margin-bottom: 20px;
}
.info-section h2 {
font-size: 16px;
margin-bottom: 10px;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
font-size: 12px;
}
table th, table td {
padding: 8px;
border: 1px solid #ddd;
text-align: left;
}
table th {
background-color: #f5f5f5;
font-weight: bold;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
.footer {
margin-top: 30px;
text-align: center;
font-size: 12px;
color: #777;
border-top: 1px solid #ddd;
padding-top: 10px;
}
.filter-info {
margin-bottom: 15px;
font-size: 14px;
font-style: italic;
}
</style>
</head>
<body>
<div class="header">
<h1>DAFTAR KELUHAN PELANGGAN</h1>
<p>Dicetak pada: {{ date('d-m-Y H:i:s') }}</p>
</div>
@if(isset($filters) && count($filters) > 0)
<div class="filter-info">
<p><strong>Filter yang digunakan:</strong></p>
<ul>
@foreach($filters as $key => $value)
@if($value)
<li>{{ ucfirst(str_replace('_', ' ', $key)) }}: {{ $value }}</li>
@endif
@endforeach
</ul>
</div>
@endif
<div class="info-section">
<h2>Daftar Keluhan</h2>
<table>
<thead>
<tr>
<th>No</th>
<th>Nama</th>
<th>Jenis Layanan</th>
<th>Tanggal Keluhan</th>
<th>Tanggal Dibuat</th>
<th>Uraian Keluhan</th>
<th>Saran</th>
</tr>
</thead>
<tbody>
@forelse($complaints as $key => $complaint)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $complaint->user->name }}</td>
<td>{{ $complaint->jenis_layanan }}</td>
<td>{{ \Carbon\Carbon::parse($complaint->tanggal_keluhan)->format('d M Y') }}</td>
<td>{{ $complaint->created_at->format('d M Y') }}</td>
<td>{{ Str::limit($complaint->uraian_keluhan, 100) }}</td>
<td>{{ Str::limit($complaint->saran, 100) }}</td>
</tr>
@empty
<tr>
<td colspan="7" style="text-align: center;">Tidak ada data keluhan</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="info-section">
<h2>Ringkasan</h2>
<table>
<tr>
<td style="width: 60%;"><strong>Total Keluhan</strong></td>
<td>{{ $complaints->count() }}</td>
</tr>
<tr>
<td><strong>Keluhan Bulan Ini</strong></td>
<td>{{ $complaints->filter(function($item) { return $item->created_at->isCurrentMonth(); })->count() }}</td>
</tr>
<tr>
<td><strong>Jenis Layanan Terbanyak</strong></td>
<td>
@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 . ')' : '-' }}
</td>
</tr>
</table>
</div>
<div class="footer">
<p>Dokumen ini diterbitkan secara elektronik dan tidak memerlukan tanda tangan.</p>
<p>© {{ date('Y') }} SYEBA Air - Laporan Keluhan Pelanggan</p>
</div>
</body>
</html>

View File

@ -42,9 +42,7 @@
<select class="form-control @error('jenis_layanan') is-invalid @enderror" id="jenis_layanan" name="jenis_layanan" required>
<option value="">Pilih Jenis Layanan</option>
<option value="Pengujian Kualitas Air" {{ old('jenis_layanan') == 'Pengujian Kualitas Air' ? 'selected' : '' }}>Pengujian Kualitas Air</option>
<option value="Pengambilan Sampel" {{ old('jenis_layanan') == 'Pengambilan Sampel' ? 'selected' : '' }}>Pengambilan Sampel</option>
<option value="Konsultasi Lingkungan" {{ old('jenis_layanan') == 'Konsultasi Lingkungan' ? 'selected' : '' }}>Konsultasi Lingkungan</option>
<option value="Lainnya" {{ old('jenis_layanan') == 'Lainnya' ? 'selected' : '' }}>Lainnya</option>
<option value="Pengambilan Contoh Uji" {{ old('jenis_layanan') == 'Pengambilan Contoh Uji' ? 'selected' : '' }}>Pengambilan Contoh Uji</option>
</select>
@error('jenis_layanan')
<div class="invalid-feedback">{{ $message }}</div>

View File

@ -43,9 +43,7 @@
<select class="form-control @error('jenis_layanan') is-invalid @enderror" id="jenis_layanan" name="jenis_layanan" required>
<option value="">Pilih Jenis Layanan</option>
<option value="Pengujian Kualitas Air" {{ old('jenis_layanan', $complaint->jenis_layanan) == 'Pengujian Kualitas Air' ? 'selected' : '' }}>Pengujian Kualitas Air</option>
<option value="Pengambilan Sampel" {{ old('jenis_layanan', $complaint->jenis_layanan) == 'Pengambilan Sampel' ? 'selected' : '' }}>Pengambilan Sampel</option>
<option value="Konsultasi Lingkungan" {{ old('jenis_layanan', $complaint->jenis_layanan) == 'Konsultasi Lingkungan' ? 'selected' : '' }}>Konsultasi Lingkungan</option>
<option value="Lainnya" {{ old('jenis_layanan', $complaint->jenis_layanan) == 'Lainnya' ? 'selected' : '' }}>Lainnya</option>
<option value="Pengambilan Contoh Uji" {{ old('jenis_layanan', $complaint->jenis_layanan) == 'Pengambilan Contoh Uji' ? 'selected' : '' }}>Pengambilan Contoh Uji</option>
</select>
@error('jenis_layanan')
<div class="invalid-feedback">{{ $message }}</div>

View File

@ -40,7 +40,80 @@
</a>
@endcan
</div>
@can('admin')
<div class="col-sm-8">
<div class="float-right">
<button type="button" class="btn btn-info mb-2" data-toggle="collapse" data-target="#filterForm">
<i class="fe-filter"></i> Filter
</button>
<button type="button" class="btn btn-danger mb-2 ml-1" onclick="cetakPDF()">
<i class="far fa-file-pdf"></i> Cetak PDF
</button>
</div>
</div>
@endcan
</div>
@can('admin')
<div class="collapse mb-3" id="filterForm">
<div class="card card-body">
<form action="{{ route('complaints.index') }}" method="GET" id="filter-form">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label for="jenis_layanan">Jenis Layanan</label>
<input type="text" name="jenis_layanan" id="jenis_layanan" class="form-control" value="{{ request('jenis_layanan') }}">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="tanggal_mulai">Tanggal Mulai</label>
<input type="date" name="tanggal_mulai" id="tanggal_mulai" class="form-control" value="{{ request('tanggal_mulai') }}">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="tanggal_selesai">Tanggal Selesai</label>
<input type="date" name="tanggal_selesai" id="tanggal_selesai" class="form-control" value="{{ request('tanggal_selesai') }}">
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary">
<i class="fe-filter"></i> Terapkan Filter
</button>
<a href="{{ route('complaints.index') }}" class="btn btn-secondary">
<i class="fe-refresh-cw"></i> Reset Filter
</a>
<button type="button" class="btn btn-danger" onclick="cetakPDF()">
<i class="far fa-file-pdf"></i> Cetak PDF dengan Filter
</button>
</div>
</div>
</form>
</div>
</div>
<script>
function cetakPDF() {
// Salin form filter saat ini
const form = document.getElementById('filter-form');
const formClone = form.cloneNode(true);
// Ubah action dan tambahkan target _blank
formClone.action = "{{ route('complaints.all-pdf') }}";
formClone.target = "_blank";
formClone.style.display = 'none';
// Tambahkan ke body, submit, lalu hapus
document.body.appendChild(formClone);
formClone.submit();
document.body.removeChild(formClone);
}
</script>
@endcan
<div class="table-responsive">
<table class="table table-centered table-striped dt-responsive nowrap w-100" id="datatable">
@ -49,7 +122,6 @@
<th>No</th>
<th>Jenis Layanan</th>
<th>Tanggal Keluhan</th>
<th>Uraian Keluhan</th>
<th>Tanggal Dibuat</th>
<th>Aksi</th>
</tr>
@ -60,24 +132,22 @@
<td>{{ $index + $complaints->firstItem() }}</td>
<td>{{ $complaint->jenis_layanan }}</td>
<td>{{ \Carbon\Carbon::parse($complaint->tanggal_keluhan)->format('d-m-Y') }}</td>
<td>{{ \Illuminate\Support\Str::limit($complaint->uraian_keluhan, 50) }}</td>
<td>{{ $complaint->created_at->format('d-m-Y H:i') }}</td>
<td>
<div class="btn-group">
<a href="{{ route('complaints.show', $complaint->id) }}" class="btn btn-info btn-sm">
<i class="fe-eye"></i>
</a>
<a href="{{ route('complaints.pdf', $complaint->id) }}" class="btn btn-danger btn-sm ml-1" target="_blank" data-toggle="tooltip" title="Download PDF">
<i class="far fa-file-pdf"></i>
</a>
@can('customer')
<a href="{{ route('complaints.edit', $complaint->id) }}" class="btn btn-primary btn-sm ml-1">
<i class="fe-edit"></i>
</a>
<form action="{{ route('complaints.destroy', $complaint->id) }}" method="POST" onsubmit="return confirm('Anda yakin ingin menghapus data ini?');">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm ml-1">
<button type="button" class="btn btn-danger btn-sm ml-1" onclick="confirmDelete('{{ route('complaints.destroy', $complaint->id) }}')">
<i class="fe-trash"></i>
</button>
</form>
@endcan
</div>
</td>
@ -102,4 +172,7 @@
</div>
</div>
</div>
<!-- Sertakan Modal Konfirmasi Hapus -->
@include('layouts.delete-modal')
@endsection

View File

@ -0,0 +1,130 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Detail Keluhan #{{ $complaint->id }}</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.header {
text-align: center;
margin-bottom: 20px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.logo {
max-width: 150px;
margin-bottom: 10px;
}
h1 {
font-size: 20px;
margin-bottom: 5px;
}
.info-section {
margin-bottom: 20px;
}
.info-section h2 {
font-size: 16px;
margin-bottom: 10px;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 10px;
}
table td {
padding: 5px;
vertical-align: top;
}
.label {
font-weight: bold;
width: 40%;
}
.content-box {
margin-top: 10px;
padding: 10px;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 4px;
}
.footer {
margin-top: 30px;
text-align: center;
font-size: 12px;
color: #777;
border-top: 1px solid #ddd;
padding-top: 10px;
}
</style>
</head>
<body>
<div class="header">
<h1>DETAIL KELUHAN #{{ $complaint->id }}</h1>
<p>Dicetak pada: {{ date('d-m-Y H:i:s') }}</p>
</div>
<div class="info-section">
<h2>Informasi Pelanggan</h2>
<table>
<tr>
<td class="label">Nama</td>
<td>{{ $complaint->user->name }}</td>
</tr>
<tr>
<td class="label">Email</td>
<td>{{ $complaint->user->email }}</td>
</tr>
<tr>
<td class="label">No. HP</td>
<td>{{ $complaint->user->phone ?? '-' }}</td>
</tr>
<tr>
<td class="label">Nama Badan Usaha</td>
<td>{{ $complaint->user->business_name ?? '-' }}</td>
</tr>
</table>
</div>
<div class="info-section">
<h2>Detail Keluhan</h2>
<table>
<tr>
<td class="label">Jenis Layanan</td>
<td>{{ $complaint->jenis_layanan }}</td>
</tr>
<tr>
<td class="label">Tanggal Keluhan</td>
<td>{{ \Carbon\Carbon::parse($complaint->tanggal_keluhan)->format('d F Y') }}</td>
</tr>
<tr>
<td class="label">Tanggal Dibuat</td>
<td>{{ $complaint->created_at->format('d F Y, H:i') }}</td>
</tr>
</table>
</div>
<div class="info-section">
<h2>Uraian Keluhan</h2>
<div class="content-box">
{{ $complaint->uraian_keluhan }}
</div>
</div>
<div class="info-section">
<h2>Saran</h2>
<div class="content-box">
{{ $complaint->saran }}
</div>
</div>
<div class="footer">
<p>Dokumen ini diterbitkan secara elektronik dan tidak memerlukan tanda tangan.</p>
<p>© {{ date('Y') }} SYEBA Air - Laporan Keluhan Pelanggan</p>
</div>
</body>
</html>

View File

@ -24,6 +24,7 @@
<p class="text-muted mb-3 font-16">
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.
</p>
<p class="text-muted mb-4">
Profil Anda telah terdaftar sebagai:
@ -48,7 +49,7 @@
<a href="{{ route('services.create') }}" class="btn btn-primary waves-effect waves-light">
<i class="fe-plus mr-1"></i> Ajukan Permintaan Pengujian Baru
</a>
<a href="{{ route('profile.edit') }}" class="btn btn-light waves-effect ml-2">
<a href="{{ route('profile.edit') }}" class="btn btn-light waves-effect ml-0 ml-md-2 mt-md-0 mt-2">
<i class="fe-user mr-1"></i> Edit Profil
</a>
</div>
@ -98,7 +99,7 @@
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="col-xl-2 col-md-6">
<div class="card-box">
<h4 class="header-title mt-0 mb-2">Diproses</h4>
<div class="widget-box-2">
@ -115,7 +116,7 @@
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="col-xl-2 col-md-6">
<div class="card-box">
<h4 class="header-title mt-0 mb-2">Selesai</h4>
<div class="widget-box-2">
@ -131,6 +132,23 @@
</div>
</div>
</div>
<div class="col-xl-2 col-md-6">
<div class="card-box">
<h4 class="header-title mt-0 mb-2">Ditolak</h4>
<div class="widget-box-2">
<div class="widget-detail-2 text-right">
<span class="badge badge-danger badge-pill float-left mt-3">Ditolak <i class="fe-x-circle ml-1"></i></span>
<h2 class="font-weight-normal mb-1"> {{ $rejectedServices }} </h2>
<p class="text-muted mb-3">Layanan</p>
</div>
<div class="progress progress-bar-alt-danger progress-sm">
<div class="progress-bar bg-danger" role="progressbar" aria-valuenow="{{ $totalServices > 0 ? ($rejectedServices / $totalServices) * 100 : 0 }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ $totalServices > 0 ? ($rejectedServices / $totalServices) * 100 : 0 }}%;">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
@ -168,6 +186,8 @@
<span class="badge badge-primary">Diproses</span>
@elseif($service->status == 'Selesai')
<span class="badge badge-success">Selesai</span>
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@endif
</td>
<td>

View File

@ -5,6 +5,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title') - UPTD Laboratorium Lingkungan</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta content="UPTD. LABLING DLH KOTA PROBOLINGGO" name="description" />
<meta content="UPTD. LABLING DLH KOTA PROBOLINGGO" name="author" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- App favicon -->
<link rel="shortcut icon" href="{{ asset('images/logo2.png') }}">
<style>
body {
background-color: #f5f5f5;
@ -85,6 +92,9 @@
color: #28a745;
text-decoration: none;
}
.password-toggle {
z-index: 10;
}
</style>
</head>
<body>
@ -96,8 +106,8 @@
<div class="col-md-5">
<div class="auth-sidebar">
<div class="logo-container">
<img src="{{ asset('images/logobulat.jpg') }}" alt="Logo Kota" class="me-2">
<img src="{{ asset('images/logosegitiga.png') }}" alt="Logo Dinas">
<img src="{{ asset('images/logo4.png') }}" alt="Logo Kota" class="me-2">
<img src="{{ asset('images/logo2.png') }}" alt="Logo Dinas">
</div>
<h3>UPTD LABORATORIUM LINGKUNGAN PADA DINAS LINGKUNGAN HIDUP KOTA PROBOLINGGO</h3>
</div>
@ -114,5 +124,21 @@
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
function togglePassword(inputId) {
const passwordInput = document.getElementById(inputId);
const passwordIcon = document.getElementById(inputId + '-icon');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
passwordIcon.classList.remove('bi-eye-slash');
passwordIcon.classList.add('bi-eye');
} else {
passwordInput.type = 'password';
passwordIcon.classList.remove('bi-eye');
passwordIcon.classList.add('bi-eye-slash');
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,32 @@
<!-- Modal Konfirmasi Hapus -->
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteModalLabel">Konfirmasi Hapus</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>Anda yakin ingin menghapus data ini?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
<form id="delete-form" method="POST" action="">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">Hapus</button>
</form>
</div>
</div>
</div>
</div>
<!-- Script untuk Modal Hapus -->
<script>
function confirmDelete(url) {
document.getElementById('delete-form').action = url;
$('#deleteModal').modal('show');
}
</script>

View File

@ -67,7 +67,7 @@
id="business_name" name="business_name" value="{{ old('business_name', $user->business_name) }}" required>
@error('business_name')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
@ -78,16 +78,41 @@
id="business_address" name="business_address" rows="3" required>{{ old('business_address', $user->business_address) }}</textarea>
@error('business_address')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
@endif
<div class="form-group">
<label for="current_password">Password Lama <small class="text-muted">(Diperlukan untuk mengubah password)</small></label>
<div class="input-group">
<input type="password" class="form-control @error('current_password') is-invalid @enderror"
id="current_password" name="current_password">
<div class="input-group-append">
<button class="btn btn-secondary toggle-password" type="button" data-target="current_password">
<i class="mdi mdi-eye"></i>
</button>
</div>
</div>
@error('current_password')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
<div class="form-group">
<label for="password">Password Baru <small class="text-muted">(Kosongkan jika tidak ingin mengubah password)</small></label>
<div class="input-group">
<input type="password" class="form-control @error('password') is-invalid @enderror"
id="password" name="password">
<div class="input-group-append">
<button class="btn btn-secondary toggle-password" type="button" data-target="password">
<i class="mdi mdi-eye"></i>
</button>
</div>
</div>
@error('password')
<div class="invalid-feedback">
{{ $message }}
@ -97,8 +122,15 @@
<div class="form-group">
<label for="password_confirmation">Konfirmasi Password Baru</label>
<div class="input-group">
<input type="password" class="form-control"
id="password_confirmation" name="password_confirmation">
<div class="input-group-append">
<button class="btn btn-secondary toggle-password" type="button" data-target="password_confirmation">
<i class="mdi mdi-eye"></i>
</button>
</div>
</div>
</div>
<div class="form-group text-right mb-0">
@ -110,3 +142,23 @@
</div>
</div>
@endsection
@section('scripts')
<script>
$(document).ready(function() {
$('.toggle-password').click(function() {
var target = $(this).data('target');
var input = $('#' + target);
var icon = $(this).find('i');
if (input.attr('type') === 'password') {
input.attr('type', 'text');
icon.removeClass('mdi-eye').addClass('mdi-eye-off');
} else {
input.attr('type', 'password');
icon.removeClass('mdi-eye-off').addClass('mdi-eye');
}
});
});
</script>
@endsection

View File

@ -0,0 +1,203 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Daftar Penilaian Kepuasan Pelanggan</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.header {
text-align: center;
margin-bottom: 20px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.logo {
max-width: 150px;
margin-bottom: 10px;
}
h1 {
font-size: 20px;
margin-bottom: 5px;
}
.info-section {
margin-bottom: 20px;
}
.info-section h2 {
font-size: 16px;
margin-bottom: 10px;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
font-size: 12px;
}
table th, table td {
padding: 8px;
border: 1px solid #ddd;
text-align: left;
}
table th {
background-color: #f5f5f5;
font-weight: bold;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
.score {
text-align: center;
}
.score-1 { background-color: #FFD9D9; }
.score-2 { background-color: #FFEBD9; }
.score-3 { background-color: #F0F0F0; }
.score-4 { background-color: #D9EBD9; }
.score-5 { background-color: #C6E6C6; }
.footer {
margin-top: 30px;
text-align: center;
font-size: 12px;
color: #777;
border-top: 1px solid #ddd;
padding-top: 10px;
}
.filter-info {
margin-bottom: 15px;
font-size: 14px;
font-style: italic;
}
</style>
</head>
<body>
<div class="header">
<h1>DAFTAR PENILAIAN KEPUASAN PELANGGAN</h1>
<p>Dicetak pada: {{ date('d-m-Y H:i:s') }}</p>
</div>
@if(isset($filters) && count($filters) > 0)
<div class="filter-info">
<p><strong>Filter yang digunakan:</strong></p>
<ul>
@foreach($filters as $key => $value)
@if($value)
<li>{{ ucfirst(str_replace('_', ' ', $key)) }}: {{ $value }}</li>
@endif
@endforeach
</ul>
</div>
@endif
<div class="info-section">
<h2>Daftar Penilaian</h2>
<table>
<thead>
<tr>
<th>No</th>
<th>Nama</th>
<th>Tanggal Pengisian</th>
<th>Nilai Rata-rata</th>
<th>Q1</th>
<th>Q2</th>
<th>Q3</th>
<th>Q4</th>
<th>Q5</th>
<th>Q6</th>
<th>Q7</th>
<th>Q8</th>
<th>Q9</th>
<th>Q10</th>
<th>Q11</th>
<th>Q12</th>
<th>Q13</th>
<th>Q14</th>
<th>Q15</th>
</tr>
</thead>
<tbody>
@forelse($satisfactions as $key => $satisfaction)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $satisfaction->user->name }}</td>
<td>{{ $satisfaction->created_at->format('d M Y') }}</td>
<td class="score
@if($satisfaction->average_score >= 4) score-5
@elseif($satisfaction->average_score >= 3) score-4
@elseif($satisfaction->average_score >= 2) score-3
@elseif($satisfaction->average_score >= 1) score-2
@else score-1 @endif">
{{ number_format($satisfaction->average_score, 1) }}
</td>
<td class="score score-{{ $satisfaction->q1 }}">{{ $satisfaction->q1 }}</td>
<td class="score score-{{ $satisfaction->q2 }}">{{ $satisfaction->q2 }}</td>
<td class="score score-{{ $satisfaction->q3 }}">{{ $satisfaction->q3 }}</td>
<td class="score score-{{ $satisfaction->q4 }}">{{ $satisfaction->q4 }}</td>
<td class="score score-{{ $satisfaction->q5 }}">{{ $satisfaction->q5 }}</td>
<td class="score score-{{ $satisfaction->q6 }}">{{ $satisfaction->q6 }}</td>
<td class="score score-{{ $satisfaction->q7 }}">{{ $satisfaction->q7 }}</td>
<td class="score score-{{ $satisfaction->q8 }}">{{ $satisfaction->q8 }}</td>
<td class="score score-{{ $satisfaction->q9 }}">{{ $satisfaction->q9 }}</td>
<td class="score score-{{ $satisfaction->q10 }}">{{ $satisfaction->q10 }}</td>
<td class="score score-{{ $satisfaction->q11 }}">{{ $satisfaction->q11 }}</td>
<td class="score score-{{ $satisfaction->q12 }}">{{ $satisfaction->q12 }}</td>
<td class="score score-{{ $satisfaction->q13 }}">{{ $satisfaction->q13 }}</td>
<td class="score score-{{ $satisfaction->q14 }}">{{ $satisfaction->q14 }}</td>
<td class="score score-{{ $satisfaction->q15 }}">{{ $satisfaction->q15 }}</td>
</tr>
@empty
<tr>
<td colspan="20" style="text-align: center;">Tidak ada data penilaian kepuasan</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="info-section">
<h2>Ringkasan</h2>
<table>
<tr>
<td style="width: 60%;"><strong>Total Penilaian</strong></td>
<td>{{ $satisfactions->count() }}</td>
</tr>
<tr>
<td><strong>Rata-rata Keseluruhan</strong></td>
<td>{{ number_format($satisfactions->avg('average_score'), 2) }}</td>
</tr>
<tr>
<td><strong>Nilai Tertinggi</strong></td>
<td>{{ number_format($satisfactions->max('average_score'), 2) }}</td>
</tr>
<tr>
<td><strong>Nilai Terendah</strong></td>
<td>{{ number_format($satisfactions->min('average_score'), 2) }}</td>
</tr>
<tr>
<td><strong>Jumlah Penilaian Sangat Baik (>=4)</strong></td>
<td>{{ $satisfactions->filter(function($item) { return $item->average_score >= 4; })->count() }}</td>
</tr>
<tr>
<td><strong>Jumlah Penilaian Baik (>=3)</strong></td>
<td>{{ $satisfactions->filter(function($item) { return $item->average_score >= 3 && $item->average_score < 4; })->count() }}</td>
</tr>
<tr>
<td><strong>Jumlah Penilaian Cukup (>=2)</strong></td>
<td>{{ $satisfactions->filter(function($item) { return $item->average_score >= 2 && $item->average_score < 3; })->count() }}</td>
</tr>
<tr>
<td><strong>Jumlah Penilaian Kurang (<2)</strong></td>
<td>{{ $satisfactions->filter(function($item) { return $item->average_score < 2; })->count() }}</td>
</tr>
</table>
</div>
<div class="footer">
<p>Dokumen ini diterbitkan secara elektronik dan tidak memerlukan tanda tangan.</p>
<p>© {{ date('Y') }} SYEBA Air - Laporan Penilaian Kepuasan Pelanggan</p>
</div>
</body>
</html>

View File

@ -49,7 +49,100 @@
</a>
@endcan
</div>
@can('admin')
<div class="col-sm-8">
<div class="float-right">
<button type="button" class="btn btn-info mb-2" data-toggle="collapse" data-target="#filterForm">
<i class="fe-filter"></i> Filter
</button>
<button type="button" class="btn btn-danger mb-2 ml-1" onclick="cetakPDF()">
<i class="far fa-file-pdf"></i> Cetak PDF
</button>
</div>
</div>
@endcan
</div>
@can('admin')
<div class="collapse mb-3" id="filterForm">
<div class="card card-body">
<form action="{{ route('satisfactions.index') }}" method="GET" id="filter-form">
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label for="tanggal_mulai">Tanggal Mulai</label>
<input type="date" name="tanggal_mulai" id="tanggal_mulai" class="form-control" value="{{ request('tanggal_mulai') }}">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="tanggal_selesai">Tanggal Selesai</label>
<input type="date" name="tanggal_selesai" id="tanggal_selesai" class="form-control" value="{{ request('tanggal_selesai') }}">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="rating_min">Rating Minimal</label>
<select name="rating_min" id="rating_min" class="form-control">
<option value="">Semua</option>
<option value="1" {{ request('rating_min') == '1' ? 'selected' : '' }}>1</option>
<option value="2" {{ request('rating_min') == '2' ? 'selected' : '' }}>2</option>
<option value="3" {{ request('rating_min') == '3' ? 'selected' : '' }}>3</option>
<option value="4" {{ request('rating_min') == '4' ? 'selected' : '' }}>4</option>
<option value="5" {{ request('rating_min') == '5' ? 'selected' : '' }}>5</option>
</select>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="rating_max">Rating Maksimal</label>
<select name="rating_max" id="rating_max" class="form-control">
<option value="">Semua</option>
<option value="1" {{ request('rating_max') == '1' ? 'selected' : '' }}>1</option>
<option value="2" {{ request('rating_max') == '2' ? 'selected' : '' }}>2</option>
<option value="3" {{ request('rating_max') == '3' ? 'selected' : '' }}>3</option>
<option value="4" {{ request('rating_max') == '4' ? 'selected' : '' }}>4</option>
<option value="5" {{ request('rating_max') == '5' ? 'selected' : '' }}>5</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary">
<i class="fe-filter"></i> Terapkan Filter
</button>
<a href="{{ route('satisfactions.index') }}" class="btn btn-secondary">
<i class="fe-refresh-cw"></i> Reset Filter
</a>
<button type="button" class="btn btn-danger" onclick="cetakPDF()">
<i class="far fa-file-pdf"></i> Cetak PDF dengan Filter
</button>
</div>
</div>
</form>
</div>
</div>
<script>
function cetakPDF() {
// Salin form filter saat ini
const form = document.getElementById('filter-form');
const formClone = form.cloneNode(true);
// Ubah action dan tambahkan target _blank
formClone.action = "{{ route('satisfactions.all-pdf') }}";
formClone.target = "_blank";
formClone.style.display = 'none';
// Tambahkan ke body, submit, lalu hapus
document.body.appendChild(formClone);
formClone.submit();
document.body.removeChild(formClone);
}
</script>
@endcan
<div class="table-responsive">
<table class="table table-centered table-striped dt-responsive nowrap w-100" id="datatable">
@ -76,17 +169,16 @@
<a href="{{ route('satisfactions.show', $satisfaction->id) }}" class="btn btn-info btn-sm">
<i class="fe-eye"></i>
</a>
<a href="{{ route('satisfactions.pdf', $satisfaction->id) }}" class="btn btn-danger btn-sm ml-1" target="_blank" data-toggle="tooltip" title="Download PDF">
<i class="far fa-file-pdf"></i>
</a>
@can('customer')
<a href="{{ route('satisfactions.edit', $satisfaction->id) }}" class="btn btn-primary btn-sm ml-1">
<i class="fe-edit"></i>
</a>
<form action="{{ route('satisfactions.destroy', $satisfaction->id) }}" method="POST" onsubmit="return confirm('Anda yakin ingin menghapus data ini?');">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm ml-1">
<button type="button" class="btn btn-danger btn-sm ml-1" onclick="confirmDelete('{{ route('satisfactions.destroy', $satisfaction->id) }}')">
<i class="fe-trash"></i>
</button>
</form>
@endcan
</div>
</td>
@ -111,4 +203,7 @@
</div>
</div>
</div>
<!-- Sertakan Modal Konfirmasi Hapus -->
@include('layouts.delete-modal')
@endsection

View File

@ -0,0 +1,228 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Detail Penilaian Kepuasan #{{ $satisfaction->id }}</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.header {
text-align: center;
margin-bottom: 20px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.logo {
max-width: 150px;
margin-bottom: 10px;
}
h1 {
font-size: 20px;
margin-bottom: 5px;
}
.info-section {
margin-bottom: 20px;
}
.info-section h2 {
font-size: 16px;
margin-bottom: 10px;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 10px;
}
table td, table th {
padding: 5px;
vertical-align: top;
border: 1px solid #ddd;
}
table th {
background-color: #f5f5f5;
font-weight: bold;
text-align: left;
}
.label {
font-weight: bold;
width: 40%;
}
.score {
text-align: center;
width: 10%;
}
.kritik-saran {
margin-top: 20px;
border: 1px solid #ddd;
padding: 10px;
background-color: #f9f9f9;
}
.footer {
margin-top: 30px;
text-align: center;
font-size: 12px;
color: #777;
border-top: 1px solid #ddd;
padding-top: 10px;
}
.rating-1 { background-color: #FFD9D9; }
.rating-2 { background-color: #FFEBD9; }
.rating-3 { background-color: #F0F0F0; }
.rating-4 { background-color: #D9EBD9; }
.rating-5 { background-color: #C6E6C6; }
.average {
font-size: 16px;
font-weight: bold;
margin-top: 20px;
padding: 10px;
text-align: center;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<div class="header">
<h1>PENILAIAN KEPUASAN PELANGGAN #{{ $satisfaction->id }}</h1>
<p>Dicetak pada: {{ date('d-m-Y H:i:s') }}</p>
</div>
<div class="info-section">
<h2>Informasi Pelanggan</h2>
<table>
<tr>
<td class="label">Nama</td>
<td>{{ $satisfaction->user->name }}</td>
</tr>
<tr>
<td class="label">Email</td>
<td>{{ $satisfaction->user->email }}</td>
</tr>
<tr>
<td class="label">Waktu Pengisian</td>
<td>{{ $satisfaction->created_at->format('d F Y, H:i') }}</td>
</tr>
</table>
</div>
<div class="average">
Nilai Rata-rata: {{ number_format($satisfaction->average_score, 1) }}
@if($satisfaction->average_score >= 4)
(Sangat Baik)
@elseif($satisfaction->average_score >= 3)
(Baik)
@elseif($satisfaction->average_score >= 2)
(Cukup)
@else
(Kurang)
@endif
</div>
<div class="info-section">
<h2>Hasil Penilaian</h2>
<table>
<thead>
<tr>
<th>No</th>
<th>Pertanyaan</th>
<th>Nilai</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Kesesuaian persyarataran pelayanan dengan jenis pelayanan</td>
<td class="score rating-{{ $satisfaction->q1 }}">{{ $satisfaction->q1 }}</td>
</tr>
<tr>
<td>2</td>
<td>Kejelasan persyaratan administrasi yang dibutuhkan</td>
<td class="score rating-{{ $satisfaction->q2 }}">{{ $satisfaction->q2 }}</td>
</tr>
<tr>
<td>3</td>
<td>Kemudahan prosedur mendapatkan pelayanan di unit ini</td>
<td class="score rating-{{ $satisfaction->q3 }}">{{ $satisfaction->q3 }}</td>
</tr>
<tr>
<td>4</td>
<td>Kecepatan waktu dalam memberikan pelayanan</td>
<td class="score rating-{{ $satisfaction->q4 }}">{{ $satisfaction->q4 }}</td>
</tr>
<tr>
<td>5</td>
<td>Ketepatan waktu jam buka pelayanan sesuai standar</td>
<td class="score rating-{{ $satisfaction->q5 }}">{{ $satisfaction->q5 }}</td>
</tr>
<tr>
<td>6</td>
<td>Kewajaran biaya/tarif dalam pelayanan</td>
<td class="score rating-{{ $satisfaction->q6 }}">{{ $satisfaction->q6 }}</td>
</tr>
<tr>
<td>7</td>
<td>Kesesuaian produk hasil pelayanan dengan standar pelayanan</td>
<td class="score rating-{{ $satisfaction->q7 }}">{{ $satisfaction->q7 }}</td>
</tr>
<tr>
<td>8</td>
<td>Kompetensi/kemampuan petugas dalam pelayanan</td>
<td class="score rating-{{ $satisfaction->q8 }}">{{ $satisfaction->q8 }}</td>
</tr>
<tr>
<td>9</td>
<td>Kesopanan dan keramahan petugas dalam memberikan pelayanan</td>
<td class="score rating-{{ $satisfaction->q9 }}">{{ $satisfaction->q9 }}</td>
</tr>
<tr>
<td>10</td>
<td>Kualitas sarana dan prasarana pelayanan</td>
<td class="score rating-{{ $satisfaction->q10 }}">{{ $satisfaction->q10 }}</td>
</tr>
<tr>
<td>11</td>
<td>Kebersihan dan kenyamanan ruang pelayanan</td>
<td class="score rating-{{ $satisfaction->q11 }}">{{ $satisfaction->q11 }}</td>
</tr>
<tr>
<td>12</td>
<td>Kebersihan kamar mandi atau toilet</td>
<td class="score rating-{{ $satisfaction->q12 }}">{{ $satisfaction->q12 }}</td>
</tr>
<tr>
<td>13</td>
<td>Kecukupan luas, kenyamanan dan keamanan tempat parkir</td>
<td class="score rating-{{ $satisfaction->q13 }}">{{ $satisfaction->q13 }}</td>
</tr>
<tr>
<td>14</td>
<td>Penanganan saran dan pengaduan pengguna layanan</td>
<td class="score rating-{{ $satisfaction->q14 }}">{{ $satisfaction->q14 }}</td>
</tr>
<tr>
<td>15</td>
<td>Kemudahan akses sarana pengaduan (kotak saran/telepon/email)</td>
<td class="score rating-{{ $satisfaction->q15 }}">{{ $satisfaction->q15 }}</td>
</tr>
</tbody>
</table>
</div>
@if($satisfaction->kritik_saran)
<div class="info-section">
<h2>Kritik dan Saran</h2>
<div class="kritik-saran">
{{ $satisfaction->kritik_saran }}
</div>
</div>
@endif
<div class="footer">
<p>Dokumen ini diterbitkan secara elektronik dan tidak memerlukan tanda tangan.</p>
<p>© {{ date('Y') }} SYEBA Air - Laporan Penilaian Kepuasan Pelanggan</p>
</div>
</body>
</html>

View File

@ -62,6 +62,7 @@
.status-diterima { background-color: #5bc0de; }
.status-diproses { background-color: #0275d8; }
.status-selesai { background-color: #5cb85c; }
.status-ditolak { background-color: #d9534f; }
.footer {
margin-top: 30px;
text-align: center;
@ -128,6 +129,8 @@
<td>
@if($service->biaya_retribusi)
Rp {{ number_format($service->biaya_retribusi, 0, ',', '.') }}
@elseif($service->status == 'Ditolak')
<span style="color: #d9534f; font-weight: bold;">Ditolak</span>
@else
Menunggu
@endif
@ -151,7 +154,7 @@
</tr>
<tr>
<td><strong>Total Biaya Retribusi</strong></td>
<td>Rp {{ number_format($services->sum('biaya_retribusi'), 0, ',', '.') }}</td>
<td>Rp {{ number_format($services->whereNotIn('status', ['Ditolak'])->sum('biaya_retribusi'), 0, ',', '.') }}</td>
</tr>
<tr>
<td><strong>Layanan Status Menunggu</strong></td>
@ -169,6 +172,10 @@
<td><strong>Layanan Status Selesai</strong></td>
<td>{{ $services->where('status', 'Selesai')->count() }}</td>
</tr>
<tr>
<td><strong>Layanan Status Ditolak</strong></td>
<td>{{ $services->where('status', 'Ditolak')->count() }}</td>
</tr>
</table>
</div>

View File

@ -137,6 +137,7 @@
<option value="Diterima" {{ old('status', $service->status) == 'Diterima' ? 'selected' : '' }}>Diterima</option>
<option value="Diproses" {{ old('status', $service->status) == 'Diproses' ? 'selected' : '' }}>Diproses</option>
<option value="Selesai" {{ old('status', $service->status) == 'Selesai' ? 'selected' : '' }}>Selesai</option>
<option value="Ditolak" {{ old('status', $service->status) == 'Ditolak' ? 'selected' : '' }}>Ditolak</option>
</select>
@error('status')
<div class="invalid-feedback">{{ $message }}</div>
@ -158,6 +159,15 @@
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="form-group" id="keteranganContainer">
<label for="keterangan">Keterangan Status</label>
<textarea class="form-control @error('keterangan') is-invalid @enderror" id="keterangan" name="keterangan" rows="3" placeholder="Masukkan keterangan status layanan (wajib jika status Diterima atau Ditolak)">{{ old('keterangan', $service->keterangan) }}</textarea>
<small class="form-text text-muted">Tuliskan keterangan mengapa layanan diterima atau ditolak. Keterangan ini akan ditampilkan kepada pelanggan.</small>
@error('keterangan')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
<div class="col-md-6">
@ -213,6 +223,32 @@
@section('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
// Fungsi untuk menampilkan/menyembunyikan kolom keterangan berdasarkan status
function toggleKeterangan() {
var status = document.getElementById('status').value;
var keteranganContainer = document.getElementById('keteranganContainer');
var keteranganLabel = keteranganContainer.querySelector('label');
var keteranganHelpText = keteranganContainer.querySelector('small');
if (status === 'Diterima' || status === 'Ditolak') {
keteranganContainer.style.display = 'block';
keteranganLabel.innerHTML = 'Keterangan Status <span class="text-danger">*</span>';
if (status === 'Diterima') {
keteranganHelpText.innerText = 'Tuliskan keterangan mengapa layanan diterima. Keterangan ini akan ditampilkan kepada pelanggan.';
} else {
keteranganHelpText.innerText = 'Tuliskan alasan mengapa layanan ditolak. Keterangan ini akan ditampilkan kepada pelanggan.';
}
} else {
keteranganContainer.style.display = 'none';
}
}
// Event listener untuk perubahan status
document.getElementById('status').addEventListener('change', toggleKeterangan);
// Jalankan fungsi saat halaman dimuat
toggleKeterangan();
// Fungsi untuk menghitung total biaya
function hitungTotalBiaya() {
var biayaParameter = parseInt(document.getElementById('biaya_retribusi_parameter').value) || 0;

View File

@ -73,6 +73,7 @@
<option value="Diterima" {{ request('status') == 'Diterima' ? 'selected' : '' }}>Diterima</option>
<option value="Diproses" {{ request('status') == 'Diproses' ? 'selected' : '' }}>Diproses</option>
<option value="Selesai" {{ request('status') == 'Selesai' ? 'selected' : '' }}>Selesai</option>
<option value="Ditolak" {{ request('status') == 'Ditolak' ? 'selected' : '' }}>Ditolak</option>
</select>
</div>
</div>
@ -189,6 +190,8 @@ function cetakPDF() {
<td>
@if($service->tanggal_selesai_uji)
{{ \Carbon\Carbon::parse($service->tanggal_selesai_uji)->format('d M Y') }}
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -196,6 +199,8 @@ function cetakPDF() {
<td>
@if($service->biaya_retribusi_parameter)
Rp {{ number_format($service->biaya_retribusi_parameter, 0, ',', '.') }}
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -203,6 +208,8 @@ function cetakPDF() {
<td>
@if($service->biaya_retribusi_jarak)
Rp {{ number_format($service->biaya_retribusi_jarak, 0, ',', '.') }}
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -210,6 +217,8 @@ function cetakPDF() {
<td>
@if($service->biaya_retribusi)
Rp {{ number_format($service->biaya_retribusi, 0, ',', '.') }}
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -220,18 +229,31 @@ function cetakPDF() {
'Menunggu' => 'badge-warning',
'Diterima' => 'badge-info',
'Diproses' => 'badge-primary',
'Selesai' => 'badge-success'
'Selesai' => 'badge-success',
'Ditolak' => 'badge-danger'
];
@endphp
<span class="badge {{ $statusClass[$service->status] ?? 'badge-secondary' }}">
{{ $service->status }}
</span>
{{-- @if($service->keterangan && ($service->status == 'Diterima' || $service->status == 'Ditolak'))
<a href="#" class="ml-1 btn btn-sm {{ $service->status == 'Diterima' ? 'btn-outline-info' : 'btn-outline-danger' }}"
data-toggle="tooltip"
data-html="true"
data-placement="top"
title="<strong>Keterangan:</strong><br>{{ $service->keterangan }}"
style="padding: 1px 5px;">
<i class="fe-info"></i>
</a>
@endif --}}
</td>
<td>
@if($service->file_hasil_uji)
<a href="{{ asset('uploads/hasil_uji/'.$service->file_hasil_uji) }}" class="btn btn-success btn-sm" target="_blank">
<i class="far fa-image"></i>
</a>
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -248,13 +270,9 @@ function cetakPDF() {
<a href="{{ route('services.edit', $service->id) }}" class="btn btn-primary btn-sm" data-toggle="tooltip" title="Edit">
<i class="fe-edit"></i>
</a>
<form action="{{ route('services.destroy', $service->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Apakah Anda yakin ingin menghapus layanan ini?')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm" data-toggle="tooltip" title="Hapus">
<button type="button" class="btn btn-danger btn-sm" data-toggle="tooltip" title="Hapus" onclick="confirmDelete('{{ route('services.destroy', $service->id) }}')">
<i class="fe-trash-2"></i>
</button>
</form>
@endcan
</div>
</td>
@ -277,4 +295,15 @@ function cetakPDF() {
</div>
</div>
</div>
<!-- Sertakan Modal Konfirmasi Hapus -->
@include('layouts.delete-modal')
@endsection
@section('scripts')
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip();
});
</script>
@endsection

View File

@ -57,6 +57,7 @@
.status-diterima { background-color: #5bc0de; }
.status-diproses { background-color: #0275d8; }
.status-selesai { background-color: #5cb85c; }
.status-ditolak { background-color: #d9534f; }
.footer {
margin-top: 30px;
text-align: center;
@ -69,7 +70,17 @@
</head>
<body>
<div class="header">
<h1>LAYANAN PENGUJIAN AIR #{{ $service->id }}</h1>
<h1>LAYANAN PENGUJIAN AIR #{{ $service->id }}
@if($service->status == 'Ditolak')
<span style="color: #d9534f;">(DITOLAK)</span>
@elseif($service->status == 'Selesai')
<span style="color: #5cb85c;">(SELESAI)</span>
@elseif($service->status == 'Diproses')
<span style="color: #0275d8;">(DIPROSES)</span>
@elseif($service->status == 'Diterima')
<span style="color: #5bc0de;">(DITERIMA)</span>
@endif
</h1>
<p>Dicetak pada: {{ date('d-m-Y H:i:s') }}</p>
</div>
@ -108,6 +119,14 @@
<span class="status status-{{ strtolower($service->status) }}">{{ $service->status }}</span>
</td>
</tr>
@if($service->keterangan && ($service->status == 'Diterima' || $service->status == 'Ditolak'))
<tr>
<td class="label">Keterangan Status</td>
<td style="color: {{ $service->status == 'Ditolak' ? '#d9534f' : '#5bc0de' }};">
<strong>{{ $service->keterangan }}</strong>
</td>
</tr>
@endif
<tr>
<td class="label">Jenis Permintaan</td>
<td>{{ $service->jenis_permintaan }}</td>
@ -147,6 +166,8 @@
<td>
@if($service->tanggal_selesai_uji)
{{ \Carbon\Carbon::parse($service->tanggal_selesai_uji)->format('d F Y') }}
@elseif($service->status == 'Ditolak')
<span style="color: #d9534f; font-weight: bold;">Ditolak</span>
@else
Menunggu
@endif
@ -163,6 +184,8 @@
<td>
@if($service->biaya_retribusi_parameter)
Rp {{ number_format($service->biaya_retribusi_parameter, 0, ',', '.') }}
@elseif($service->status == 'Ditolak')
<span style="color: #d9534f; font-weight: bold;">Ditolak</span>
@else
Menunggu
@endif
@ -173,6 +196,8 @@
<td>
@if($service->biaya_retribusi_jarak)
Rp {{ number_format($service->biaya_retribusi_jarak, 0, ',', '.') }}
@elseif($service->status == 'Ditolak')
<span style="color: #d9534f; font-weight: bold;">Ditolak</span>
@else
Menunggu
@endif
@ -183,6 +208,8 @@
<td>
@if($service->biaya_retribusi)
<strong>Rp {{ number_format($service->biaya_retribusi, 0, ',', '.') }}</strong>
@elseif($service->status == 'Ditolak')
<span style="color: #d9534f; font-weight: bold;">Ditolak</span>
@else
Menunggu
@endif
@ -191,6 +218,13 @@
</table>
</div>
@if($service->status == 'Ditolak' && $service->keterangan)
<div class="info-section" style="border: 1px solid #d9534f; padding: 10px; background-color: #fdf7f7;">
<h2 style="color: #d9534f;">Alasan Penolakan</h2>
<p>{{ $service->keterangan }}</p>
</div>
@endif
<div class="footer">
<p>Dokumen ini diterbitkan secara elektronik dan tidak memerlukan tanda tangan.</p>
<p>© {{ date('Y') }} SYEBA Air - Dokumen Layanan Pengujian Air</p>

View File

@ -81,7 +81,8 @@
'Menunggu' => 'badge-warning',
'Diterima' => 'badge-info',
'Diproses' => 'badge-primary',
'Selesai' => 'badge-success'
'Selesai' => 'badge-success',
'Ditolak' => 'badge-danger'
];
@endphp
<span class="badge {{ $statusClass[$service->status] ?? 'badge-secondary' }}">
@ -89,6 +90,16 @@
</span>
</td>
</tr>
@if($service->keterangan && ($service->status == 'Diterima' || $service->status == 'Ditolak'))
<tr>
<td><strong>Keterangan Status</strong></td>
<td>
<div class="alert alert-{{ $service->status == 'Diterima' ? 'info' : 'danger' }} mb-0 py-2">
{{ $service->keterangan }}
</div>
</td>
</tr>
@endif
<tr>
<td><strong>Jenis Permintaan</strong></td>
<td>{{ $service->jenis_permintaan }}</td>
@ -127,6 +138,8 @@
<td>
@if($service->tanggal_selesai_uji)
{{ \Carbon\Carbon::parse($service->tanggal_selesai_uji)->format('d F Y') }}
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -141,6 +154,8 @@
<td>
@if($service->biaya_retribusi_parameter)
Rp {{ number_format($service->biaya_retribusi_parameter, 0, ',', '.') }}
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -151,6 +166,8 @@
<td>
@if($service->biaya_retribusi_jarak)
Rp {{ number_format($service->biaya_retribusi_jarak, 0, ',', '.') }}
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -161,6 +178,8 @@
<td>
@if($service->biaya_retribusi)
<strong>Rp {{ number_format($service->biaya_retribusi, 0, ',', '.') }}</strong>
@elseif($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
@ -190,8 +209,23 @@
<div class="card border">
<div class="card-body">
<h5 class="card-title">Hasil Uji</h5>
<p>Hasil uji belum tersedia.</p>
<p>
@if($service->status == 'Ditolak')
Hasil uji tidak tersedia karena permintaan layanan ditolak.
@if($service->keterangan)
<div class="alert alert-danger mt-2">
<strong>Alasan Penolakan:</strong> {{ $service->keterangan }}
</div>
@endif
@else
Hasil uji belum tersedia.
@endif
</p>
@if($service->status == 'Ditolak')
<span class="badge badge-danger">Ditolak</span>
@else
<span class="badge badge-warning">Menunggu</span>
@endif
</div>
</div>
</div>

View File

@ -21,22 +21,17 @@
|
*/
// Route::get('/', function () {
// if (auth()->check() && auth()->user()->role === 'admin') {
// return redirect()->route('admin.dashboard');
// }
// return view('Dashboard.dashboard');
// })->name('dashboard');
Route::get('/', function () {
if (auth()->check()) {
if (auth()->user()->role === 'admin') {
return redirect()->route('admin.dashboard');
} else {
return redirect()->route('customer.home');
return redirect('/home');
}
}
return view('Dashboard.dashboard');
return redirect('/login');
})->name('dashboard');
// Rute untuk autentikasi
@ -70,10 +65,14 @@
// Rute untuk fitur-fitur regular
Route::middleware(['auth'])->group(function () {
Route::resource('complaints', ComplaintController::class);
Route::get('complaints/{complaint}/pdf', [ComplaintController::class, 'pdf'])->name('complaints.pdf');
Route::get('complaints-pdf', [ComplaintController::class, 'allPdf'])->name('complaints.all-pdf')->middleware('admin');
Route::resource('services', ServiceController::class);
Route::get('services/{service}/pdf', [ServiceController::class, 'generatePdf'])->name('services.pdf');
Route::get('services-pdf', [ServiceController::class, 'generateAllPdf'])->name('services.all-pdf')->middleware('admin');
Route::resource('satisfactions', SatisfactionController::class);
Route::get('satisfactions/{satisfaction}/pdf', [SatisfactionController::class, 'pdf'])->name('satisfactions.pdf');
Route::get('satisfactions-pdf', [SatisfactionController::class, 'allPdf'])->name('satisfactions.all-pdf')->middleware('admin');
Route::get('satisfaction-dashboard', [SatisfactionController::class, 'dashboard'])->name('satisfactions.dashboard')->middleware('admin');
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::put('/profile', [ProfileController::class, 'update'])->name('profile.update');