pembaruan detail

This commit is contained in:
rahmagustin 2026-01-30 22:10:11 +07:00
parent 3f01fe71b1
commit b0f777db46
15 changed files with 503 additions and 364 deletions

View File

@ -8,11 +8,14 @@
class AduanController extends Controller class AduanController extends Controller
{ {
/**
* Halaman aduan TPS (user)
*/
public function index(Request $request) public function index(Request $request)
{ {
$title = 'Aduan TPS'; $title = 'Aduan TPS';
// TPS terpilih (jika dari SIG / detail) // TPS terpilih (jika dari detail / SIG)
$tps = null; $tps = null;
if ($request->filled('tps_id')) { if ($request->filled('tps_id')) {
$tps = LokasiTps::with('kategori') $tps = LokasiTps::with('kategori')
@ -20,7 +23,7 @@ public function index(Request $request)
->first(); ->first();
} }
// List TPS untuk dropdown (jika dari navbar) // List TPS untuk dropdown
$listTps = LokasiTps::orderBy('nama_tps')->get(); $listTps = LokasiTps::orderBy('nama_tps')->get();
return view('user.aduan-tps', compact( return view('user.aduan-tps', compact(
@ -30,30 +33,38 @@ public function index(Request $request)
)); ));
} }
/**
* Simpan aduan TPS
*/
public function store(Request $request) public function store(Request $request)
{ {
// VALIDASI (FOTO WAJIB)
$request->validate([ $request->validate([
'lokasi_tps_id' => 'required|exists:lokasi_tps,id_tps', 'lokasi_tps_id' => 'required|exists:lokasi_tps,id_tps',
'nama_pelapor' => 'required', 'nama_pelapor' => 'required|string|max:100',
'alamat_pelapor'=> 'required', 'alamat_pelapor'=> 'required|string',
'no_pelapor' => 'required', 'no_pelapor' => 'required|string|max:20',
'isi_aduan' => 'required', 'isi_aduan' => 'required|string',
'bukti_foto' => 'nullable|image|max:2048' 'bukti_foto' => 'required|image|mimes:jpg,jpeg,png|max:4096',
], [
'lokasi_tps_id.required' => 'TPS wajib dipilih',
'bukti_foto.required' => 'Foto bukti wajib diunggah',
'bukti_foto.image' => 'File harus berupa gambar',
]); ]);
$foto = null; // SIMPAN FOTO
if ($request->hasFile('bukti_foto')) { $fotoPath = $request->file('bukti_foto')
$foto = $request->file('bukti_foto')->store('aduan', 'public'); ->store('aduan', 'public');
}
// SIMPAN KE DATABASE
AduanTps::create([ AduanTps::create([
'lokasi_tps_id' => $request->lokasi_tps_id, 'lokasi_tps_id' => $request->lokasi_tps_id,
'nama_pelapor' => $request->nama_pelapor, 'nama_pelapor' => $request->nama_pelapor,
'alamat_pelapor'=> $request->alamat_pelapor, 'alamat_pelapor'=> $request->alamat_pelapor,
'no_pelapor' => $request->no_pelapor, 'no_pelapor' => $request->no_pelapor,
'isi_aduan' => $request->isi_aduan, 'isi_aduan' => $request->isi_aduan,
'tanggal_aduan' => now(), 'bukti_foto' => $fotoPath,
'bukti_foto' => $foto 'tanggal_aduan' => now(), // OTOMATIS
]); ]);
return redirect() return redirect()

View File

@ -11,17 +11,11 @@
class AuthenticatedSessionController extends Controller class AuthenticatedSessionController extends Controller
{ {
/**
* Display the login view.
*/
public function create(): View public function create(): View
{ {
return view('auth.login'); return view('auth.login');
} }
/**
* Handle an incoming authentication request.
*/
public function store(LoginRequest $request): RedirectResponse public function store(LoginRequest $request): RedirectResponse
{ {
$request->authenticate(); $request->authenticate();
@ -31,9 +25,6 @@ public function store(LoginRequest $request): RedirectResponse
return redirect()->intended(route('admin.dashboard', absolute: false)); return redirect()->intended(route('admin.dashboard', absolute: false));
} }
/**
* Destroy an authenticated session.
*/
public function destroy(Request $request): RedirectResponse public function destroy(Request $request): RedirectResponse
{ {
Auth::guard('web')->logout(); Auth::guard('web')->logout();
@ -42,6 +33,6 @@ public function destroy(Request $request): RedirectResponse
$request->session()->regenerateToken(); $request->session()->regenerateToken();
return redirect('user.index'); return redirect('/index');
} }
} }

View File

@ -4,6 +4,7 @@
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\LokasiTps; use App\Models\LokasiTps;
use App\Models\AduanTps;
class SIGController extends Controller class SIGController extends Controller
{ {
@ -12,7 +13,6 @@ class SIGController extends Controller
*/ */
public function index() public function index()
{ {
// Ambil semua data TPS dari database
$tps = LokasiTps::select( $tps = LokasiTps::select(
'id_tps', 'id_tps',
'nama_tps', 'nama_tps',
@ -28,12 +28,19 @@ public function index()
} }
/** /**
* Menampilkan detail TPS * Menampilkan detail TPS + aduan yang sudah ditanggapi
*/ */
public function show($id) public function show($id)
{ {
// Detail TPS
$tps = LokasiTps::with('kategori')->findOrFail($id); $tps = LokasiTps::with('kategori')->findOrFail($id);
return view('user.detail-tps', compact('tps')); // Aduan untuk TPS ini yang SUDAH ditanggapi admin
$aduanTps = AduanTps::where('lokasi_tps_id', $id)
->whereNotNull('tanggapan_admin')
->orderBy('tanggal_aduan', 'desc')
->get();
return view('user.detail-tps', compact('tps', 'aduanTps'));
} }
} }

View File

@ -21,9 +21,13 @@ class AduanTps extends Model
'tanggal_tanggapan' 'tanggal_tanggapan'
]; ];
// RELASI KE LOKASI TPS
public function lokasiTps() public function lokasiTps()
{ {
return $this->belongsTo(LokasiTps::class); return $this->belongsTo(
LokasiTps::class, // model tujuan
'lokasi_tps_id', // foreign key di aduan_tps
'id_tps' // primary key di lokasi_tps
);
} }
} }

View File

@ -29968,4 +29968,5 @@ @media (max-width: 991px) {
} }
} }
/*# sourceMappingURL=../maps/vertical-layout-light/style.css.map */ /*# sourceMappingURL=../maps/vertical-layout-light/style.css.map */

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@ -168,7 +168,7 @@ @keyframes pulsate-play-btn {
/* PHP Email Form Messages /* PHP Email Form Messages
------------------------------*/ ------------------------------*/
.php-email-form .error-message { .aduan-form .error-message {
display: none; display: none;
background: #df1529; background: #df1529;
color: #ffffff; color: #ffffff;
@ -178,7 +178,7 @@ .php-email-form .error-message {
font-weight: 600; font-weight: 600;
} }
.php-email-form .sent-message { .aduan-form .sent-message {
display: none; display: none;
color: #ffffff; color: #ffffff;
background: #059652; background: #059652;
@ -188,7 +188,7 @@ .php-email-form .sent-message {
font-weight: 600; font-weight: 600;
} }
.php-email-form .loading { .aduan-form .loading {
display: none; display: none;
background: var(--surface-color); background: var(--surface-color);
text-align: center; text-align: center;
@ -196,7 +196,7 @@ .php-email-form .loading {
margin-bottom: 24px; margin-bottom: 24px;
} }
.php-email-form .loading:before { .aduan-form .loading:before {
content: ""; content: "";
display: inline-block; display: inline-block;
border-radius: 50%; border-radius: 50%;
@ -205,10 +205,10 @@ .php-email-form .loading:before {
margin: 0 10px -6px 0; margin: 0 10px -6px 0;
border: 3px solid var(--accent-color); border: 3px solid var(--accent-color);
border-top-color: var(--surface-color); border-top-color: var(--surface-color);
animation: php-email-form-loading 1s linear infinite; animation: aduan-form-loading 1s linear infinite;
} }
@keyframes php-email-form-loading { @keyframes aduan-form-loading {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);
} }
@ -2062,17 +2062,17 @@ .contact .info-item p {
color: color-mix(in srgb, var(--default-color), transparent 40%); color: color-mix(in srgb, var(--default-color), transparent 40%);
} }
.contact .php-email-form { .contact .aduan-form {
width: 100%; width: 100%;
} }
.contact .php-email-form .form-group { .contact .aduan-form .form-group {
padding-bottom: 8px; padding-bottom: 8px;
} }
.contact .php-email-form input[type=text], .contact .aduan-form input[type=text],
.contact .php-email-form input[type=tel], .contact .aduan-form input[type=tel],
.contact .php-email-form textarea { .contact .aduan-form textarea {
border-radius: 0px; border-radius: 0px;
box-shadow: none; box-shadow: none;
font-size: 14px; font-size: 14px;
@ -2080,25 +2080,25 @@ .contact .php-email-form textarea {
border-color: color-mix(in srgb, var(--default-color), transparent 80%); border-color: color-mix(in srgb, var(--default-color), transparent 80%);
} }
.contact .php-email-form input[type=text]:focus, .contact .aduan-form input[type=text]:focus,
.contact .php-email-form input[type=tel]:focus, .contact .aduan-form input[type=tel]:focus,
.contact .php-email-form textarea:focus { .contact .aduan-form textarea:focus {
border-color: var(--accent-color); border-color: var(--accent-color);
} }
.contact .php-email-form input[type=text], .contact .aduan-form input[type=text],
.contact .php-email-form input[type=tel] { .contact .aduan-form input[type=tel] {
height: 48px; height: 48px;
padding: 10px 15px; padding: 10px 15px;
} }
.contact .php-email-form textarea { .contact .aduan-form textarea {
padding: 10px 12px; padding: 10px 12px;
height: 290px; height: 290px;
} }
/* ===== FILE INPUT (BUKTI FOTO) ===== */ /* ===== FILE INPUT (BUKTI FOTO) ===== */
.contact .php-email-form input[type=file] { .contact .aduan-form input[type=file] {
border-radius: 0px; border-radius: 0px;
box-shadow: none; box-shadow: none;
font-size: 14px; font-size: 14px;
@ -2111,13 +2111,13 @@ .contact .php-email-form input[type=file] {
} }
/* focus sama seperti input lain */ /* focus sama seperti input lain */
.contact .php-email-form input[type=file]:focus { .contact .aduan-form input[type=file]:focus {
border-color: var(--accent-color); border-color: var(--accent-color);
outline: none; outline: none;
} }
/* styling tombol file (Choose File) */ /* styling tombol file (Choose File) */
.contact .php-email-form input[type=file]::file-selector-button { .contact .aduan-form input[type=file]::file-selector-button {
border: none; border: none;
padding: 10px 15px; padding: 10px 15px;
margin-right: 10px; margin-right: 10px;
@ -2130,12 +2130,12 @@ .contact .php-email-form input[type=file]::file-selector-button {
} }
/* hover tombol */ /* hover tombol */
.contact .php-email-form input[type=file]::file-selector-button:hover { .contact .aduan-form input[type=file]::file-selector-button:hover {
opacity: 0.9; opacity: 0.9;
} }
/* fallback browser lama */ /* fallback browser lama */
.contact .php-email-form input[type=file]::-webkit-file-upload-button { .contact .aduan-form input[type=file]::-webkit-file-upload-button {
border: none; border: none;
padding: 10px 15px; padding: 10px 15px;
background-color: var(--accent-color); background-color: var(--accent-color);
@ -2143,7 +2143,7 @@ .contact .php-email-form input[type=file]::-webkit-file-upload-button {
border-radius: 0px; border-radius: 0px;
} }
.contact .php-email-form button[type=submit] { .contact .aduan-form button[type=submit] {
background: var(--accent-color); background: var(--accent-color);
color: var(--contrast-color); color: var(--contrast-color);
border: 0; border: 0;
@ -2152,7 +2152,7 @@ .contact .php-email-form button[type=submit] {
border-radius: 4px; border-radius: 4px;
} }
.contact .php-email-form button[type=submit]:hover { .contact .aduan-form button[type=submit]:hover {
background: color-mix(in srgb, var(--accent-color) 90%, black 15%); background: color-mix(in srgb, var(--accent-color) 90%, black 15%);
} }
@ -3009,3 +3009,21 @@ .tags-widget ul a span {
color: color-mix(in srgb, var(--default-color), transparent 60%); color: color-mix(in srgb, var(--default-color), transparent 60%);
font-size: 14px; font-size: 14px;
} }
.btn-aduan-tps,
.btn-aduan-tps:focus {
color: #fff;
background: #dc3545; /* merah */
font-size: 14px;
padding: 8px 26px;
margin: 0;
border-radius: 4px;
transition: 0.3s;
border: none;
text-decoration: none;
}
.btn-aduan-tps:hover {
background: #bb2d3b; /* merah lebih gelap */
color: #fff;
}

View File

@ -1,76 +1,94 @@
@extends('admin.template') @extends('admin.template')
@section('content') @section('content')
<div class="content-wrapper"> <div class="content-wrapper">
<div class="row"> <div class="row">
<div class="col-12 grid-margin stretch-card"> <div class="col-12 grid-margin stretch-card">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h4 class="card-title">Tanggapi Aduan</h4>
<p class="card-description">
Form tanggapan admin terhadap aduan masyarakat
</p>
<form class="forms-sample" <h4 class="card-title">Tanggapi Aduan TPS</h4>
action="{{ route('admin.aduan.tanggapi', $aduan->id_aduan) }}" <p class="card-description">
method="POST"> Form tanggapan admin terhadap aduan masyarakat
@csrf </p>
<!-- Nama Pelapor --> <form action="{{ route('admin.aduan.tanggapi', $aduan->id_aduan) }}"
method="POST"
class="forms-sample">
@csrf
{{-- TPS --}}
<div class="form-group">
<label>TPS yang Diadukan</label>
<input type="text" class="form-control"
value="{{ $aduan->lokasiTps->nama_tps ?? '-' }}"
readonly>
<small class="text-muted">
{{ $aduan->lokasiTps->alamat_tps ?? '' }}
</small>
</div>
{{-- Nama Pelapor --}}
<div class="form-group">
<label>Nama Pelapor</label>
<input type="text"
class="form-control"
value="{{ $aduan->nama_pelapor }}"
readonly>
</div>
{{-- Alamat Pelapor --}}
<div class="form-group">
<label>Alamat Pelapor</label>
<input type="text"
class="form-control"
value="{{ $aduan->alamat_pelapor }}"
readonly>
</div>
{{-- Isi Aduan --}}
<div class="form-group">
<label>Isi Aduan</label>
<textarea class="form-control"
rows="4"
readonly>{{ $aduan->isi_aduan }}</textarea>
</div>
{{-- Bukti Foto --}}
@if ($aduan->bukti_foto)
<div class="form-group"> <div class="form-group">
<label>Nama Pelapor</label> <label>Bukti Foto</label><br>
<input type="text" class="form-control" <img src="{{ asset('storage/' . $aduan->bukti_foto) }}"
value="{{ $aduan->nama_pelapor }}" alt="Bukti Aduan"
readonly> class="border rounded img-fluid"
style="max-height: 260px;">
</div> </div>
@endif
<!-- Alamat Pelapor --> {{-- Tanggapan Admin --}}
<div class="form-group"> <div class="form-group">
<label>Alamat Pelapor</label> <label>Tanggapan Admin</label>
<input type="text" class="form-control" <textarea name="tanggapan_admin"
value="{{ $aduan->alamat_pelapor }}" class="form-control"
readonly> rows="4"
</div> placeholder="Masukkan tanggapan admin..."
required>{{ old('tanggapan_admin', $aduan->tanggapan_admin) }}</textarea>
</div>
<!-- Isi Aduan --> {{-- Tombol --}}
<div class="form-group"> <button type="submit" class="mr-2 btn btn-primary">
<label>Isi Aduan</label> Simpan Tanggapan
<textarea class="form-control" rows="4" readonly>{{ $aduan->isi_aduan }}</textarea> </button>
</div> <a href="{{ route('admin.aduan.index') }}"
class="btn btn-light">
Kembali
</a>
<!-- Bukti Foto --> </form>
@if ($aduan->bukti_foto)
<div class="form-group">
<label>Bukti Foto</label><br>
<img src="{{ asset('storage/' . $aduan->bukti_foto) }}"
alt="Bukti Aduan"
class="img-fluid rounded"
style="max-height: 250px;">
</div>
@endif
<!-- Tanggapan Admin -->
<div class="form-group">
<label>Tanggapan Admin</label>
<textarea name="tanggapan_admin"
class="form-control"
rows="4"
placeholder="Masukkan tanggapan admin..."
required>{{ old('tanggapan_admin', $aduan->tanggapan_admin) }}</textarea>
</div>
<!-- Tombol -->
<button type="submit" class="btn btn-primary mr-2">
Simpan
</button>
<a href="{{ route('admin.aduan.index') }}" class="btn btn-light">
Batal
</a>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
@endsection @endsection

View File

@ -1,118 +1,141 @@
@extends('admin.template') @extends('admin.template')
@section('content') @section('content')
<div class="content-wrapper"> <div class="content-wrapper">
<div class="row"> <div class="row">
<div class="col-lg-12 grid-margin stretch-card"> <div class="col-lg-12 grid-margin stretch-card">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<!-- Header card --> <!-- Header -->
<div class="d-flex justify-content-between align-items-center mb-3"> <div class="mb-3 d-flex justify-content-between align-items-center">
<div> <div>
<h4 class="card-title mb-0">Data Aduan</h4> <h4 class="mb-0 card-title">Data Aduan TPS</h4>
<p class="card-description mb-0"> <p class="mb-0 card-description">
Daftar aduan masyarakat Daftar aduan masyarakat terhadap TPS
</p> </p>
</div>
</div> </div>
<!-- Tabel -->
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Nama Pelapor</th>
<th>Alamat</th>
<th>Tanggal Aduan</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@forelse ($aduan as $item)
<tr>
<td>{{ $item->nama_pelapor }}</td>
<td>{{ $item->alamat_pelapor }}</td>
<td>
{{ \Carbon\Carbon::parse($item->tanggal_aduan)->format('d M Y') }}
</td>
<td>
@if ($item->tanggapan_admin)
<label class="badge badge-success">Ditanggapi</label>
@else
<label class="badge badge-danger">Belum</label>
@endif
</td>
<td class="text-center">
<a href="{{ route('admin.aduan.show', $item->id_aduan) }}"
class="btn btn-warning btn-sm me-1" title="Tanggapi">
<i class="bi bi-pencil-square"></i>
</a>
<form action="{{ route('admin.aduan.destroy', $item->id_aduan) }}"
method="POST" class="form-hapus" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="text-center">
Data aduan belum tersedia
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div> </div>
<!-- Tabel -->
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>TPS</th>
<th>Nama Pelapor</th>
{{-- <th>Alamat Pelapor</th> --}}
<th>Tanggal Aduan</th>
<th>Status</th>
<th class="text-center">Aksi</th>
</tr>
</thead>
<tbody>
@forelse ($aduan as $item)
<tr>
<!-- TPS -->
<td>
<strong>
{{ $item->lokasiTps->nama_tps ?? '-' }}
</strong>
<br>
<small class="text-muted">
{{ $item->lokasiTps->alamat_tps ?? '' }}
</small>
</td>
<!-- Pelapor -->
<td>{{ $item->nama_pelapor }}</td>
<!-- Alamat -->
{{-- <td>{{ $item->alamat_pelapor }}</td> --}}
<!-- Tanggal -->
<td>
{{ \Carbon\Carbon::parse($item->tanggal_aduan)->format('d M Y') }}
</td>
<!-- Status -->
<td>
@if ($item->tanggapan_admin)
<span class="badge badge-success">Ditanggapi</span>
@else
<span class="badge badge-danger">Belum</span>
@endif
</td>
<!-- Aksi -->
<td class="text-center">
<a href="{{ route('admin.aduan.show', $item->id_aduan) }}"
class="btn btn-warning btn-sm"
title="Tanggapi Aduan">
<i class="bi bi-pencil-square"></i>
</a>
<form action="{{ route('admin.aduan.destroy', $item->id_aduan) }}"
method="POST"
class="d-inline form-hapus">
@csrf
@method('DELETE')
<button type="submit"
class="btn btn-danger btn-sm"
title="Hapus Aduan">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="text-center text-muted">
Data aduan belum tersedia
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script> </div>
document.querySelectorAll('.form-hapus').forEach(form => {
form.addEventListener('submit', function(e) {
e.preventDefault();
Swal.fire({ {{-- SweetAlert Hapus --}}
title: 'Hapus Data Aduan?', <script>
text: 'Data yang sudah dihapus tidak dapat dikembalikan!', document.querySelectorAll('.form-hapus').forEach(form => {
icon: 'warning', form.addEventListener('submit', function (e) {
showCancelButton: true, e.preventDefault();
confirmButtonColor: '#d33',
cancelButtonColor: '#6c757d', Swal.fire({
confirmButtonText: 'Ya, Hapus', title: 'Hapus Aduan?',
cancelButtonText: 'Batal', text: 'Data yang dihapus tidak dapat dikembalikan!',
didOpen: () => { icon: 'warning',
document.querySelector('.swal2-popup').style.fontFamily = showCancelButton: true,
'Nunito, sans-serif'; confirmButtonColor: '#d33',
} cancelButtonColor: '#6c757d',
}).then((result) => { confirmButtonText: 'Ya, Hapus',
if (result.isConfirmed) { cancelButtonText: 'Batal'
form.submit(); }).then((result) => {
} if (result.isConfirmed) {
}); form.submit();
}); }
}); });
</script> });
});
</script>
{{-- SweetAlert Success --}}
@if (session('success')) @if (session('success'))
<script> <script>
Swal.fire({ Swal.fire({
icon: 'success', icon: 'success',
title: 'Berhasil', title: 'Berhasil',
text: '{{ session('success') }}', text: '{{ session('success') }}',
timer: 2000, timer: 2000,
showConfirmButton: false showConfirmButton: false
}); });
</script> </script>
@endif @endif
@endsection @endsection

View File

@ -8,7 +8,7 @@
<div class="card-body"> <div class="card-body">
<h4 class="card-title">Tambah Data Sampah Tahunan</h4> <h4 class="card-title">Tambah Data Sampah Tahunan</h4>
<p class="card-description"> <p class="card-description">
Form input data sampah per tahun (satuan dalam Ton) Form input data sampah harian per tahun (satuan dalam Ton)
</p> </p>
<form action="{{ route('admin.sampah.store') }}" method="POST"> <form action="{{ route('admin.sampah.store') }}" method="POST">
@ -74,7 +74,7 @@ class="form-control" readonly>
</small> </small>
</div> </div>
<button type="submit" class="btn btn-primary mr-2"> <button type="submit" class="mr-2 btn btn-primary">
Simpan Simpan
</button> </button>
<a href="{{ route('admin.sampah.index') }}" class="btn btn-light"> <a href="{{ route('admin.sampah.index') }}" class="btn btn-light">

View File

@ -8,7 +8,7 @@
<div class="card-body"> <div class="card-body">
<h4 class="card-title">Edit Data Sampah Tahunan</h4> <h4 class="card-title">Edit Data Sampah Tahunan</h4>
<p class="card-description"> <p class="card-description">
Form edit data sampah per tahun (satuan Ton) Form edit data sampah harian per tahun (satuan Ton)
</p> </p>
<form action="{{ route('admin.sampah.update', $sampah->id_sampah) }}" method="POST"> <form action="{{ route('admin.sampah.update', $sampah->id_sampah) }}" method="POST">
@ -73,7 +73,7 @@ class="form-control"
</small> </small>
</div> </div>
<button type="submit" class="btn btn-primary mr-2"> <button type="submit" class="mr-2 btn btn-primary">
Simpan Simpan
</button> </button>
<a href="{{ route('admin.sampah.index') }}" class="btn btn-light"> <a href="{{ route('admin.sampah.index') }}" class="btn btn-light">

View File

@ -7,11 +7,11 @@
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3"> <div class="mb-3 d-flex justify-content-between align-items-center">
<div> <div>
<h4 class="card-title mb-0">Data Sampah</h4> <h4 class="mb-0 card-title">Data Sampah</h4>
<p class="card-description mb-0"> <p class="mb-0 card-description">
Daftar Sampah Per Tahun di Kabupaten Nganjuk Daftar sampah harian per tahun
</p> </p>
</div> </div>

View File

@ -19,7 +19,7 @@
<!-- inject:css --> <!-- inject:css -->
<link rel="stylesheet" href="{{ asset('assets/admin/css/vertical-layout-light/style.css') }}"> <link rel="stylesheet" href="{{ asset('assets/admin/css/vertical-layout-light/style.css') }}">
<!-- endinject --> <!-- endinject -->
<link rel="shortcut icon" href="{{ asset('assets/admin/images/favicon.png') }}" /> <link rel="shortcut icon" href="{{ asset('assets/admin/images/icon-mini.png') }}" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
@ -35,17 +35,17 @@
<body> <body>
<div class="container-scroller"> <div class="container-scroller">
<nav class="navbar col-lg-12 col-12 p-0 fixed-top d-flex flex-row"> <nav class="flex-row p-0 navbar col-lg-12 col-12 fixed-top d-flex">
<div class="text-center navbar-brand-wrapper d-flex align-items-center justify-content-center"> <div class="text-center navbar-brand-wrapper d-flex align-items-center justify-content-center">
<a class="navbar-brand brand-logo mr-5" href="{{ route('admin.dashboard') }}"> <a class="mr-5 navbar-brand brand-logo" href="{{ route('admin.dashboard') }}">
<img src="{{ asset('assets/admin/images/sig-logo.png') }}" alt="logo" <img src="{{ asset('assets/admin/images/sig-logo.png') }}" alt="logo"
style="height: 55px; width: auto;" class="mr-2"> style="height: 55px; width: auto;" class="mr-2">
</a> </a>
<a class="navbar-brand brand-logo-mini" href="index.html"><img <a class="navbar-brand brand-logo-mini" href="index.html"><img
src="{{ asset('assets/admin/images/logo-mini.svg') }}" alt="logo" /></a> src="{{ asset('assets/admin/images/icon-mini.png') }}" alt="logo" /></a>
</div> </div>
<div class="navbar-menu-wrapper d-flex align-items-center justify-content-end"> <div class="navbar-menu-wrapper d-flex align-items-center justify-content-end">
<button class="navbar-toggler navbar-toggler align-self-center" type="button" data-toggle="minimize"> <button class="navbar-toggler align-self-center" type="button" data-toggle="minimize">
<span class="icon-menu"></span> <span class="icon-menu"></span>
</button> </button>
<ul class="navbar-nav navbar-nav-right"> <ul class="navbar-nav navbar-nav-right">

View File

@ -2,150 +2,160 @@
@section('content') @section('content')
<!-- Page Title --> <!-- Page Title -->
<div class="page-title"> <div class="page-title">
<div class="container d-lg-flex justify-content-between align-items-center"> <div class="container d-lg-flex justify-content-between align-items-center">
<h1 class="mb-2 mb-lg-0">Aduan TPS</h1> <h1 class="mb-2 mb-lg-0">Aduan TPS</h1>
<nav class="breadcrumbs"> <nav class="breadcrumbs">
<ol> <ol>
<li><a href="{{ url('/') }}">Beranda</a></li> <li><a href="{{ url('/') }}">Beranda</a></li>
<li class="current">Aduan TPS</li> <li class="current">Aduan TPS</li>
</ol> </ol>
</nav> </nav>
</div>
</div>
<!-- End Page Title -->
<section id="contact" class="contact section">
<div class="container" data-aos="fade">
<div class="row gy-5 gx-lg-5">
{{-- KOLOM KIRI --}}
<div class="col-lg-4">
<div class="info">
<h3 class="mb-3">TPS yang Diadukan</h3>
{{-- FOTO TPS --}}
<div class="mb-3 d-none" id="foto-wrapper">
<img id="foto-tps" class="img-fluid w-100"
style="object-fit:cover; max-height:220px;">
</div>
{{-- INFO TPS --}}
<div id="info-tps">
@if ($tps)
<p class="mb-1"><strong>{{ $tps->nama_tps }}</strong></p>
<p class="mb-1 text-muted">{{ $tps->alamat_tps }}</p>
@else
<p class="text-muted mb-2">
Silakan pilih TPS yang akan diadukan
</p>
<select id="pilih-tps" class="form-select">
<option value="">-- Pilih TPS --</option>
@foreach ($listTps as $item)
<option value="{{ $item->id_tps }}"
data-nama="{{ $item->nama_tps }}"
data-alamat="{{ $item->alamat_tps }}"
data-foto="{{ $item->foto_tps
? asset('storage/' . $item->foto_tps)
: asset('assets/user/img/no-image.png') }}">
{{ $item->nama_tps }}
</option>
@endforeach
</select>
@endif
</div>
</div>
</div>
{{-- KOLOM KANAN --}}
<div class="col-lg-8">
<form action="{{ route('user.aduan.store') }}" method="POST"
class="php-email-form" enctype="multipart/form-data">
@csrf
{{-- PENTING --}}
<input type="hidden" name="lokasi_tps_id" id="lokasi_tps_id"
value="{{ $tps ? $tps->id_tps : '' }}">
<div class="row">
<div class="col-md-6 form-group">
<input type="text" name="nama_pelapor" class="form-control"
placeholder="Nama Pelapor" required>
</div>
<div class="col-md-6 form-group mt-3 mt-md-0">
<input type="tel" name="no_pelapor" class="form-control"
placeholder="No. Telp Pelapor" required>
</div>
</div>
<div class="form-group mt-3">
<input type="text" name="alamat_pelapor" class="form-control"
placeholder="Alamat Pelapor" required>
</div>
<div class="form-group mt-3">
<textarea name="isi_aduan" class="form-control"
placeholder="Isi Aduan" required></textarea>
</div>
{{-- FILE INPUT (SUDAH SERAGAM) --}}
<div class="form-group mt-3">
<input type="file" name="bukti_foto"
class="form-control file-input"
accept="image/*">
</div>
<div class="text-center mt-4">
<button type="submit">Kirim Aduan</button>
</div>
</form>
</div>
</div> </div>
</div> </div>
</section> <!-- End Page Title -->
{{-- SCRIPT TPS --}} <section id="contact" class="contact section">
<script>
document.addEventListener('DOMContentLoaded', function () {
const selectTps = document.getElementById('pilih-tps');
const infoTps = document.getElementById('info-tps');
const fotoWrapper = document.getElementById('foto-wrapper');
const fotoTps = document.getElementById('foto-tps');
const inputLokasi = document.getElementById('lokasi_tps_id');
if (!selectTps) return; <div class="container" data-aos="fade">
<div class="row gy-5 gx-lg-5">
selectTps.addEventListener('change', function () { {{-- KOLOM KIRI --}}
if (!this.value) return; <div class="col-lg-4">
<div class="info">
<h3 class="mb-3">TPS yang Diadukan</h3>
const option = this.options[this.selectedIndex]; {{-- FOTO TPS --}}
<div class="mb-3 d-none" id="foto-wrapper">
<img id="foto-tps" class="img-fluid w-100" style="object-fit:cover; max-height:220px;">
</div>
inputLokasi.value = this.value; {{-- INFO TPS --}}
<div id="info-tps">
@if ($tps)
<p class="mb-1"><strong>{{ $tps->nama_tps }}</strong></p>
<p class="mb-1 text-muted">{{ $tps->alamat_tps }}</p>
@else
<p class="mb-2 text-muted">
Silakan pilih TPS yang akan diadukan
</p>
fotoTps.src = option.dataset.foto; <select id="pilih-tps" class="form-select">
fotoWrapper.classList.remove('d-none'); <option value="">-- Pilih TPS --</option>
@foreach ($listTps as $item)
<option value="{{ $item->id_tps }}" data-nama="{{ $item->nama_tps }}"
data-alamat="{{ $item->alamat_tps }}"
data-foto="{{ $item->foto_tps ? asset('storage/' . $item->foto_tps) : asset('assets/user/img/no-image.png') }}">
{{ $item->nama_tps }}
</option>
@endforeach
</select>
@endif
</div>
</div>
</div>
infoTps.innerHTML = ` {{-- KOLOM KANAN --}}
<div class="col-lg-8">
@if ($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<form action="{{ route('user.aduan.store') }}" method="POST" class="aduan-form"
enctype="multipart/form-data">
@csrf
{{-- PENTING --}}
<input type="hidden" name="lokasi_tps_id" id="lokasi_tps_id"
value="{{ $tps ? $tps->id_tps : '' }}">
<div class="row">
<div class="col-md-6 form-group">
<input type="text" name="nama_pelapor" class="form-control" placeholder="Nama Pelapor"
required>
</div>
<div class="mt-3 col-md-6 form-group mt-md-0">
<input type="tel" name="no_pelapor" class="form-control" placeholder="No. Telp Pelapor"
required>
</div>
</div>
<div class="mt-3 form-group">
<input type="text" name="alamat_pelapor" class="form-control" placeholder="Alamat Pelapor"
required>
</div>
<div class="mt-3 form-group">
<textarea name="isi_aduan" class="form-control" placeholder="Isi Aduan" required></textarea>
</div>
{{-- FILE INPUT (SUDAH SERAGAM) --}}
<div class="mt-3 form-group">
<input type="file" name="bukti_foto" class="form-control file-input" accept="image/*">
</div>
<div class="mt-4 text-center">
<button type="submit" class="px-4 btn btn-success">Kirim Aduan</button>
</div>
</form>
</div>
</div>
</div>
</section>
{{-- SCRIPT TPS --}}
<script>
document.addEventListener('DOMContentLoaded', function() {
const selectTps = document.getElementById('pilih-tps');
const infoTps = document.getElementById('info-tps');
const fotoWrapper = document.getElementById('foto-wrapper');
const fotoTps = document.getElementById('foto-tps');
const inputLokasi = document.getElementById('lokasi_tps_id');
if (!selectTps) return;
selectTps.addEventListener('change', function() {
if (!this.value) return;
const option = this.options[this.selectedIndex];
inputLokasi.value = this.value;
fotoTps.src = option.dataset.foto;
fotoWrapper.classList.remove('d-none');
infoTps.innerHTML = `
<p class="mb-1"><strong>${option.dataset.nama}</strong></p> <p class="mb-1"><strong>${option.dataset.nama}</strong></p>
<p class="text-muted mb-2">${option.dataset.alamat}</p> <p class="mb-2 text-muted">${option.dataset.alamat}</p>
<button type="button" class="btn btn-sm btn-outline-secondary" id="ganti-tps"> <button type="button" class="btn btn-sm btn-outline-secondary" id="ganti-tps">
Ganti TPS Ganti TPS
</button> </button>
`; `;
document.getElementById('ganti-tps').onclick = () => { document.getElementById('ganti-tps').onclick = () => {
inputLokasi.value = ''; inputLokasi.value = '';
fotoWrapper.classList.add('d-none'); fotoWrapper.classList.add('d-none');
infoTps.innerHTML = '<p class="text-muted mb-2">Silakan pilih TPS yang akan diadukan</p>'; infoTps.innerHTML =
infoTps.appendChild(selectTps); '<p class="mb-2 text-muted">Silakan pilih TPS yang akan diadukan</p>';
selectTps.value = ''; infoTps.appendChild(selectTps);
}; selectTps.value = '';
}); };
}); });
</script> });
</script>
@endsection @endsection

View File

@ -35,12 +35,12 @@ class="img-fluid" alt="">
<div class="tab-pane fade show active" id="about-tab1"> <div class="tab-pane fade show active" id="about-tab1">
<p class="fst-italic mb-4"> <p class="mb-4 fst-italic">
{{ $tps->alamat_tps }} {{ $tps->alamat_tps }}
</p> </p>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-borderless align-middle"> <table class="table align-middle table-borderless">
<tbody> <tbody>
<tr> <tr>
<th width="40%"> <th width="40%">
@ -85,15 +85,15 @@ class="img-fluid" alt="">
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="d-flex justify-content-between align-items-center mt-4"> <div class="mt-4 d-flex justify-content-between align-items-center">
<small class="text-muted"> <small class="text-muted">
Laporkan jika TPS bermasalah atau penuh Laporkan jika TPS bermasalah atau penuh
</small> </small>
<a href="{{ route('user.aduan', ['tps_id' => $tps->id_tps]) }}" <a href="{{ route('user.aduan', ['tps_id' => $tps->id_tps]) }}" class="btn-aduan-tps">
class="btn btn-danger btn-sm d-flex align-items-center">
Adukan TPS Adukan TPS
</a> </a>
</div> </div>
</div> </div>
@ -103,10 +103,66 @@ class="btn btn-danger btn-sm d-flex align-items-center">
</div> </div>
</div> </div>
{{-- ===================== --}}
{{-- ADUAN TPS (DITANGGAPI) --}}
{{-- ===================== --}}
<section class="mt-4 section bg-light">
<div class="container">
<h5 class="mb-3 fw-semibold">Aduan yang Telah Ditanggapi</h5>
@if ($aduanTps->count())
<div class="list-group list-group-flush">
@foreach ($aduanTps as $aduan)
<div class="px-3 py-3 mb-2 bg-white rounded shadow-sm list-group-item">
{{-- HEADER --}}
<div class="mb-1 d-flex justify-content-between align-items-center">
<small class="fw-semibold text-dark">
{{ $aduan->nama_pelapor }}
</small>
<small class="text-muted">
{{ \Carbon\Carbon::parse($aduan->tanggal_aduan)->translatedFormat('d M Y') }}
</small>
</div>
{{-- ISI ADUAN --}}
<p class="mb-2 text-secondary small">
{{ $aduan->isi_aduan }}
</p>
{{-- TANGGAPAN --}}
<div class="border-start border-success ps-2">
<small class="text-success fw-semibold">
Tanggapan Admin:
</small>
<div class="small text-dark">
{{ $aduan->tanggapan_admin }}
</div>
</div>
</div>
@endforeach
</div>
@else
<small class="text-muted">
Belum ada aduan yang ditanggapi.
</small>
@endif
</div>
</section>
</div> </div>
</div> </div>
</section>
</div>
</section> </section>
@endsection @endsection