search and pagination
|
|
@ -10,13 +10,25 @@
|
|||
|
||||
class TpsController extends Controller
|
||||
{
|
||||
public function index()
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$title = 'Data TPS';
|
||||
$tps = LokasiTps::with('kategori')->withCount('aduan')->get();
|
||||
return view('admin.tps.index', compact('title', 'tps'));
|
||||
|
||||
$search = $request->search;
|
||||
|
||||
$tps = LokasiTps::with('kategori')
|
||||
->withCount('aduan')
|
||||
->when($search, function ($query) use ($search) {
|
||||
$query->where('nama_tps', 'like', '%' . $search . '%');
|
||||
})
|
||||
->orderBy('id_tps', 'desc') // supaya data terbaru muncul di atas
|
||||
->paginate(10);
|
||||
|
||||
return view('admin.tps.index', compact('title', 'tps', 'search'));
|
||||
}
|
||||
|
||||
|
||||
public function create()
|
||||
{
|
||||
$title = 'Tambah TPS';
|
||||
|
|
@ -24,6 +36,7 @@ public function create()
|
|||
return view('admin.tps.create', compact('title', 'kategori'));
|
||||
}
|
||||
|
||||
|
||||
private function convertToDecimal($coordinate)
|
||||
{
|
||||
if (is_numeric($coordinate)) {
|
||||
|
|
@ -49,9 +62,12 @@ private function convertToDecimal($coordinate)
|
|||
return $decimal;
|
||||
}
|
||||
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
|
||||
'kategori_tps_id' => 'required|exists:kategori_tps,id_kategori_tps',
|
||||
'nama_tps' => 'required|string|max:255',
|
||||
'alamat_tps' => 'required|string|max:255',
|
||||
|
|
@ -61,7 +77,9 @@ public function store(Request $request)
|
|||
'latitude' => 'required',
|
||||
'longitude' => 'required',
|
||||
'foto_tps' => 'required|image|mimes:jpg,jpeg,png|max:2048',
|
||||
|
||||
], [
|
||||
|
||||
'kategori_tps_id.required' => 'Kategori TPS wajib dipilih.',
|
||||
'kategori_tps_id.exists' => 'Kategori TPS tidak valid.',
|
||||
'nama_tps.required' => 'Nama TPS wajib diisi.',
|
||||
|
|
@ -78,33 +96,48 @@ public function store(Request $request)
|
|||
'foto_tps.required' => 'Foto TPS wajib diunggah.',
|
||||
'foto_tps.image' => 'Foto TPS harus berupa gambar.',
|
||||
'foto_tps.mimes' => 'Format foto harus jpg, jpeg, atau png.',
|
||||
|
||||
]);
|
||||
|
||||
if ($validator->fails()) return back()->withErrors($validator)->withInput();
|
||||
if ($validator->fails()) {
|
||||
return back()->withErrors($validator)->withInput();
|
||||
}
|
||||
|
||||
|
||||
$latitude = $this->convertToDecimal($request->latitude);
|
||||
$longitude = $this->convertToDecimal($request->longitude);
|
||||
|
||||
if ($latitude === null || $latitude < -90 || $latitude > 90)
|
||||
|
||||
if ($latitude === null || $latitude < -90 || $latitude > 90) {
|
||||
$validator->errors()->add('latitude', 'Latitude tidak valid.');
|
||||
}
|
||||
|
||||
if ($longitude === null || $longitude < -180 || $longitude > 180)
|
||||
if ($longitude === null || $longitude < -180 || $longitude > 180) {
|
||||
$validator->errors()->add('longitude', 'Longitude tidak valid.');
|
||||
}
|
||||
|
||||
if ($validator->fails()) {
|
||||
return back()->withErrors($validator)->withInput();
|
||||
}
|
||||
|
||||
if ($validator->fails()) return back()->withErrors($validator)->withInput();
|
||||
|
||||
// Upload foto ke public/assets/admin/images/tps
|
||||
$foto = null;
|
||||
|
||||
if ($request->hasFile('foto_tps')) {
|
||||
|
||||
$file = $request->file('foto_tps');
|
||||
$namaTps = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $request->nama_tps));
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = strtolower(str_replace(' ', '_', $request->nama_tps)) . '_' . time() . '.' . $file->getClientOriginalExtension();
|
||||
|
||||
$filename = strtolower(str_replace(' ', '_', $request->nama_tps))
|
||||
. '_' . time() . '.' . $file->getClientOriginalExtension();
|
||||
|
||||
$file->move(public_path('assets/admin/images/tps'), $filename);
|
||||
|
||||
$foto = $filename;
|
||||
}
|
||||
|
||||
|
||||
LokasiTps::create([
|
||||
|
||||
'kategori_tps_id' => $request->kategori_tps_id,
|
||||
'nama_tps' => $request->nama_tps,
|
||||
'alamat_tps' => $request->alamat_tps,
|
||||
|
|
@ -114,24 +147,36 @@ public function store(Request $request)
|
|||
'latitude' => $latitude,
|
||||
'longitude' => $longitude,
|
||||
'foto_tps' => $foto,
|
||||
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.tps.index')->with('success', 'Data TPS berhasil ditambahkan.');
|
||||
|
||||
return redirect()->route('admin.tps.index')
|
||||
->with('success', 'Data TPS berhasil ditambahkan.');
|
||||
}
|
||||
|
||||
|
||||
public function edit($id)
|
||||
{
|
||||
|
||||
$title = 'Edit TPS';
|
||||
|
||||
$tps = LokasiTps::findOrFail($id);
|
||||
|
||||
$kategori = KategoriTps::all();
|
||||
|
||||
return view('admin.tps.edit', compact('title', 'tps', 'kategori'));
|
||||
}
|
||||
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
|
||||
$tps = LokasiTps::findOrFail($id);
|
||||
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
|
||||
'kategori_tps_id' => 'required|exists:kategori_tps,id_kategori_tps',
|
||||
'nama_tps' => 'required|string|max:255',
|
||||
'alamat_tps' => 'required|string|max:255',
|
||||
|
|
@ -141,38 +186,53 @@ public function update(Request $request, $id)
|
|||
'latitude' => 'required',
|
||||
'longitude' => 'required',
|
||||
'foto_tps' => 'nullable|image|mimes:jpg,jpeg,png|max:4096',
|
||||
|
||||
]);
|
||||
|
||||
if ($validator->fails()) return back()->withErrors($validator)->withInput();
|
||||
|
||||
if ($validator->fails()) {
|
||||
return back()->withErrors($validator)->withInput();
|
||||
}
|
||||
|
||||
|
||||
$latitude = $this->convertToDecimal($request->latitude);
|
||||
$longitude = $this->convertToDecimal($request->longitude);
|
||||
|
||||
if ($latitude === null || $latitude < -90 || $latitude > 90)
|
||||
|
||||
if ($latitude === null || $latitude < -90 || $latitude > 90) {
|
||||
$validator->errors()->add('latitude', 'Latitude tidak valid.');
|
||||
}
|
||||
|
||||
if ($longitude === null || $longitude < -180 || $longitude > 180)
|
||||
if ($longitude === null || $longitude < -180 || $longitude > 180) {
|
||||
$validator->errors()->add('longitude', 'Longitude tidak valid.');
|
||||
}
|
||||
|
||||
if ($validator->fails()) {
|
||||
return back()->withErrors($validator)->withInput();
|
||||
}
|
||||
|
||||
if ($validator->fails()) return back()->withErrors($validator)->withInput();
|
||||
|
||||
// Upload foto baru jika ada
|
||||
$foto = $tps->foto_tps;
|
||||
|
||||
if ($request->hasFile('foto_tps')) {
|
||||
if ($tps->foto_tps && file_exists(public_path($tps->foto_tps))) {
|
||||
unlink(public_path($tps->foto_tps)); // hapus foto lama
|
||||
|
||||
if ($tps->foto_tps && file_exists(public_path('assets/admin/images/tps/' . $tps->foto_tps))) {
|
||||
unlink(public_path('assets/admin/images/tps/' . $tps->foto_tps));
|
||||
}
|
||||
|
||||
$file = $request->file('foto_tps');
|
||||
$namaTps = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $request->nama_tps));
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = strtolower(str_replace(' ', '_', $request->nama_tps)) . '_' . time() . '.' . $file->getClientOriginalExtension();
|
||||
|
||||
$filename = strtolower(str_replace(' ', '_', $request->nama_tps))
|
||||
. '_' . time() . '.' . $file->getClientOriginalExtension();
|
||||
|
||||
$file->move(public_path('assets/admin/images/tps'), $filename);
|
||||
|
||||
$foto = $filename;
|
||||
}
|
||||
|
||||
|
||||
$tps->update([
|
||||
|
||||
'kategori_tps_id' => $request->kategori_tps_id,
|
||||
'nama_tps' => $request->nama_tps,
|
||||
'alamat_tps' => $request->alamat_tps,
|
||||
|
|
@ -182,27 +242,34 @@ public function update(Request $request, $id)
|
|||
'latitude' => $latitude,
|
||||
'longitude' => $longitude,
|
||||
'foto_tps' => $foto,
|
||||
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.tps.index')->with('success', 'Data TPS berhasil diperbarui.');
|
||||
|
||||
return redirect()->route('admin.tps.index')
|
||||
->with('success', 'Data TPS berhasil diperbarui.');
|
||||
}
|
||||
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
{
|
||||
|
||||
$tps = LokasiTps::findOrFail($id);
|
||||
|
||||
// Path lengkap foto TPS
|
||||
$fotoPath = $tps->foto_tps ? public_path('assets/admin/images/tps/' . $tps->foto_tps) : null;
|
||||
$fotoPath = $tps->foto_tps
|
||||
? public_path('assets/admin/images/tps/' . $tps->foto_tps)
|
||||
: null;
|
||||
|
||||
|
||||
// Hapus file jika ada
|
||||
if ($fotoPath && file_exists($fotoPath)) {
|
||||
unlink($fotoPath);
|
||||
}
|
||||
|
||||
// Hapus data dari database
|
||||
|
||||
$tps->delete();
|
||||
|
||||
|
||||
return redirect()->route('admin.tps.index')
|
||||
->with('success', 'Data TPS berhasil dihapus.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\View; // wajib
|
||||
use App\Models\KategoriTps; // wajib
|
||||
use Illuminate\Pagination\Paginator;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -21,6 +22,7 @@ public function register(): void
|
|||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
Paginator::useBootstrap();
|
||||
View::composer('user.template', function ($view) {
|
||||
$view->with('kategoriTps', KategoriTps::all());
|
||||
});
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 316 KiB |
|
After Width: | Height: | Size: 409 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 980 KiB |
|
After Width: | Height: | Size: 914 KiB |
|
After Width: | Height: | Size: 695 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 260 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 950 KiB |
|
After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 246 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
|
@ -10,15 +10,30 @@
|
|||
<div class="card-body">
|
||||
|
||||
<div class="mb-3 d-flex justify-content-between align-items-center">
|
||||
|
||||
<div>
|
||||
<h4 class="mb-0 card-title">Data TPS</h4>
|
||||
<p class="mb-0 card-description">
|
||||
Daftar Tempat Pembuangan Sampah (TPS)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 d-flex align-items-center">
|
||||
|
||||
<!-- SEARCH -->
|
||||
<form action="{{ route('admin.tps.index') }}" method="GET"
|
||||
style="width:300px; margin-right:20px;">
|
||||
<input type="text" name="search" value="{{ request('search') }}"
|
||||
class="form-control" placeholder="Cari nama TPS...">
|
||||
</form>
|
||||
|
||||
<!-- BUTTON TAMBAH -->
|
||||
<a href="{{ route('admin.tps.create') }}" class="btn btn-primary">
|
||||
<i class="bi bi-plus-lg"></i> Tambah
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
|
|
@ -29,29 +44,29 @@
|
|||
<th>Kategori</th>
|
||||
<th>Foto</th>
|
||||
<th>Status</th>
|
||||
<th>Aksi</th>
|
||||
<th class="text-center">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@forelse ($tps as $item)
|
||||
<tr>
|
||||
|
||||
<td>{{ $item->nama_tps }}</td>
|
||||
|
||||
<td>
|
||||
{{ $item->kategori->nama_kategori ?? '-' }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if ($item->foto_tps)
|
||||
<img src="{{ asset('assets/admin/images/tps/' . $item->foto_tps) }}"
|
||||
alt="Foto TPS"
|
||||
style="
|
||||
width:200px;
|
||||
height:auto;
|
||||
border-radius:2px;
|
||||
">
|
||||
alt="Foto TPS" style="width:200px;height:auto;border-radius:4px;">
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if ($item->status_tps == 'Aktif')
|
||||
<label class="badge badge-success">Aktif</label>
|
||||
|
|
@ -61,21 +76,30 @@
|
|||
<label class="badge badge-warning">Pembangunan</label>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
|
||||
<!-- EDIT -->
|
||||
<a href="{{ route('admin.tps.edit', $item->id_tps) }}"
|
||||
class="btn btn-warning btn-sm me-1">
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</a>
|
||||
|
||||
<!-- DELETE -->
|
||||
<form action="{{ route('admin.tps.destroy', $item->id_tps) }}"
|
||||
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">
|
||||
|
|
@ -83,19 +107,27 @@ class="btn btn-warning btn-sm me-1">
|
|||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- PAGINATION -->
|
||||
<div class="mt-3">
|
||||
{{ $tps->appends(request()->query())->links() }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
document.querySelectorAll('.form-hapus').forEach(form => {
|
||||
form.addEventListener('submit', function(e) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
Swal.fire({
|
||||
|
|
@ -111,11 +143,15 @@ class="btn btn-warning btn-sm me-1">
|
|||
document.querySelector('.swal2-popup').style.fontFamily =
|
||||
'Nunito, sans-serif';
|
||||
}
|
||||
|
||||
}).then((result) => {
|
||||
|
||||
if (result.isConfirmed) {
|
||||
form.submit();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -132,4 +168,5 @@ class="btn btn-warning btn-sm me-1">
|
|||
});
|
||||
</script>
|
||||
@endif
|
||||
|
||||
@endsection
|
||||
|
|
|
|||