This commit is contained in:
alfinfadli16 2025-06-13 03:30:09 +07:00
parent eb637d4fed
commit 660d53ad8a
4 changed files with 108 additions and 246 deletions

View File

@ -9,162 +9,63 @@
class RiwayatController extends Controller
{
/**
* Menampilkan daftar riwayat pemesanan
*/
public function index()
{
// Ambil data sewa yang terkait dengan user yang sedang login dan bukan draft
$sewas = Sewa::with(['paket', 'kota'])
->where('user_id', Auth::id())
->where('status', '!=', 'draft')
->orderBy('created_at', 'desc')
->get();
->where('user_id', Auth::id())
->where('status', '!=', 'draft')
->orderBy('created_at', 'desc')
->get();
return view('riwayat', compact('sewas'));
}
/**
* Menampilkan detail riwayat pemesanan
*/
public function show($id)
{
$sewa = Sewa::with(['paket', 'kota', 'user'])
->findOrFail($id);
// Pastikan yang melihat adalah pemilik pesanan
if ($sewa->user_id != Auth::id() && !Auth::user()->tipe_pengguna == 'admin') {
return redirect()->route('riwayat')
->with('error', 'Anda tidak memiliki akses untuk melihat pesanan ini.');
}
// Jika request adalah AJAX, kembalikan response JSON
if (request()->ajax()) {
return response()->json([
'id' => $sewa->id,
'tanggal_pembayaran' => $sewa->tanggal_pembayaran ? $sewa->tanggal_pembayaran->format('d/m/Y H:i') : null,
'status_pembayaran' => $sewa->nominal_pembayaran
? ($sewa->nominal_pembayaran >= $sewa->total_harga ? 'Lunas' : 'DP ' . number_format(($sewa->nominal_pembayaran / $sewa->total_harga) * 100, 0) . '%')
: 'Belum Bayar',
'lokasi' => $sewa->lokasi,
'kota' => $sewa->kota,
'ongkir' => $sewa->ongkir,
'bukti_pembayaran' => $sewa->bukti_pembayaran,
'jenis_jaminan' => $sewa->jenis_jaminan,
'foto_jaminan' => $sewa->foto_jaminan
]);
}
return view('detail-riwayat', compact('sewa'));
}
/**
* Membatalkan pemesanan
*/
public function cancel($id)
{
$sewa = Sewa::findOrFail($id);
// Pastikan yang membatalkan adalah pemilik pesanan
if ($sewa->user_id != Auth::id()) {
return redirect()->route('riwayat')
->with('error', 'Anda tidak memiliki akses untuk membatalkan pesanan ini.');
}
// Izinkan pembatalan untuk status yang belum selesai atau dibatalkan
if (in_array($sewa->status, ['completed', 'dibatalkan', 'ongoing'])) {
return redirect()->route('riwayat')
->with('error', 'Pesanan ini tidak dapat dibatalkan karena status sudah ' . $sewa->status);
}
// Tambahkan catatan jika pembatalan setelah disetujui
if ($sewa->status === 'confirmed') {
$sewa->catatan = ($sewa->catatan ? $sewa->catatan . "\n" : '') .
"[DIBATALKAN OLEH PENYEWA SETELAH DISETUJUI] - " . now();
}
$sewa->status = 'dibatalkan';
$sewa->save();
$message = 'Pesanan berhasil dibatalkan.';
if ($sewa->status === 'confirmed') {
$message .= ' Mohon hubungi admin untuk informasi biaya pembatalan.';
}
return redirect()->route('riwayat')
->with('success', $message);
}
/**
* Halaman untuk admin melihat semua riwayat pesanan
*/
public function adminIndex()
{
// Hanya admin yang bisa akses
if (!Auth::user()->tipe_pengguna == 'admin') {
return redirect()->route('dashboard');
}
$sewas = Sewa::with(['paket', 'user'])
->orderBy('created_at', 'desc')
->get();
return view('admin.riwayat', compact('sewas'));
}
/**
* Mengubah status pemesanan (khusus admin)
*/
public function updateStatus(Request $request, $id)
{
if (Auth::user()->tipe_pengguna !== 'admin') {
return redirect()->route('dashboard')->with('error', 'Akses ditolak.');
{
if (Auth::user()->tipe_pengguna !== 'admin') {
return redirect()->route('dashboard')->with('error', 'Akses ditolak.');
}
$request->validate([
'status' => 'required|in:completed'
]);
$sewa = Sewa::findOrFail($id);
if ($sewa->status !== 'confirmed') {
return back()->with('error', 'Status hanya bisa diubah jika saat ini adalah confirmed.');
}
$sewa->status = $request->status;
$sewa->save();
return back()->with('success', 'Status berhasil diperbarui menjadi completed.');
}
$sewa = Sewa::findOrFail($id);
if ($sewa->status !== 'confirmed') {
return back()->with('error', 'Status hanya bisa diubah jika saat ini adalah confirmed.');
}
if ($request->status !== 'completed') {
return back()->with('error', 'Status hanya bisa diubah menjadi completed.');
}
$sewa->status = 'completed';
$sewa->save();
return back()->with('success', 'Status berhasil diperbarui menjadi completed.');
}
public function hapus($id)
{
$sewa = Sewa::findOrFail($id);
// Pastikan yang menghapus adalah pemilik pesanan
if ($sewa->user_id != Auth::id()) {
return redirect()->route('riwayat')
->with('error', 'Anda tidak memiliki akses untuk menghapus pesanan ini.');
}
// Hanya bisa menghapus pesanan yang sudah selesai atau dibatalkan
if (!in_array($sewa->status, ['completed', 'dibatalkan'])) {
return redirect()->route('riwayat')
->with('error', 'Hanya pesanan yang sudah selesai atau dibatalkan yang dapat dihapus.');
}
// Hapus file bukti pembayaran dan jaminan jika ada
if ($sewa->bukti_pembayaran) {
Storage::disk('public')->delete($sewa->bukti_pembayaran);
}
if ($sewa->foto_jaminan) {
Storage::disk('public')->delete($sewa->foto_jaminan);
}
$sewa->delete();
return redirect()->route('riwayat')
->with('success', 'Riwayat pesanan berhasil dihapus.');
}
}
}

View File

@ -13,21 +13,37 @@ class Chat extends Model
'sewa_id',
'sender_id',
'receiver_id',
'admin_id', // tambahkan
'message',
'is_read'
'is_read',
];
protected $casts = [
'is_read' => 'boolean'
'is_read' => 'boolean',
];
/**
* Relasi ke model Sewa.
*/
public function sewa()
{
return $this->belongsTo(Sewa::class);
}
/**
* Relasi ke pengirim pesan (User).
*/
public function sender()
{
return $this->belongsTo(User::class, 'sender_id');
}
}
/**
* Relasi ke penerima pesan (User).
*/
public function receiver()
{
return $this->belongsTo(User::class, 'receiver_id');
}
}

View File

@ -1,123 +1,63 @@
@extends('layouts.app')
@section('title', 'Riwayat Sewa - Admin INUFA')
@section('header', 'Manajemen Riwayat Sewa')
@section('content')
<div class="bg-white rounded-lg shadow-lg p-6">
@if(count($sewas) > 0)
<div class="overflow-x-auto">
<table class="min-w-full bg-white">
<thead>
<tr class="bg-gray-100">
<th class="py-3 px-4 text-left">No</th>
<th class="py-3 px-4 text-left">Tanggal</th>
<th class="py-3 px-4 text-left">Customer</th>
<th class="py-3 px-4 text-left">Paket</th>
<th class="py-3 px-4 text-left">Total Harga</th>
<th class="py-3 px-4 text-left">Nominal Pembayaran</th>
<th class="py-3 px-4 text-left">Sisa Pembayaran</th>
<th class="py-3 px-4 text-left">Status</th>
<th class="py-3 px-4 text-center">Aksi</th>
</tr>
</thead>
<tbody>
@foreach($sewas as $index => $sewa)
@php
$user = optional($sewa->user);
$paket = optional($sewa->paket);
$sisaPembayaran = $sewa->total_harga - ($sewa->nominal_pembayaran ?? 0);
@endphp
<tr class="border-b hover:bg-gray-50">
<td class="py-3 px-4">{{ $index + 1 }}</td>
<td class="py-3 px-4">{{ $sewa->created_at->format('d/m/Y') }}</td>
<td class="py-3 px-4">
<div class="text-sm">
<p class="font-medium text-gray-900">{{ $user->name ?? '-' }}</p>
<p class="text-gray-500">{{ $user->email ?? '-' }}</p>
</div>
<div class="container">
<h2>Riwayat Pemesanan</h2>
@if(session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
@if(session('error'))
<div class="alert alert-danger">{{ session('error') }}</div>
@endif
<table class="table table-bordered">
<thead>
<tr>
<th>No</th>
<th>Paket</th>
<th>Kota</th>
<th>Status</th>
<th>Total Harga</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@forelse($sewas as $index => $sewa)
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $sewa->paket->nama_paket ?? '-' }}</td>
<td>{{ $sewa->kota->nama_kota ?? '-' }}</td>
<td>
<span class="badge bg-info">{{ ucfirst($sewa->status) }}</span>
</td>
<td class="py-3 px-4">{{ $paket->nama_paket ?? '-' }}</td>
<td class="py-3 px-4">Rp {{ number_format($sewa->total_harga, 0, ',', '.') }}</td>
<td class="py-3 px-4">
Rp {{ number_format($sewa->nominal_pembayaran ?? 0, 0, ',', '.') }}
</td>
<td class="py-3 px-4">
@if($sisaPembayaran > 0)
<span class="text-red-600 font-medium">
Rp {{ number_format($sisaPembayaran, 0, ',', '.') }}
</span>
@else
<span class="text-green-600 font-medium">Lunas</span>
<td>Rp {{ number_format($sewa->total_harga, 0, ',', '.') }}</td>
<td>
<!-- Tombol tandai completed (hanya admin & status confirmed) -->
@if(Auth::user()->tipe_pengguna === 'admin' && $sewa->status === 'confirmed')
<form action="{{ route('riwayat.updateStatus', $sewa->id) }}" method="POST" style="display:inline;">
@csrf
<input type="hidden" name="status" value="completed">
<button type="submit" class="btn btn-success btn-sm" onclick="return confirm('Tandai sebagai LUNAS / completed?')">Tandai Lunas</button>
</form>
@endif
<!-- Tombol hapus (jika status sudah selesai atau dibatalkan) -->
@if($sewa->user_id == Auth::id() && in_array($sewa->status, ['completed', 'dibatalkan']))
<form action="{{ url('/riwayat/hapus/'.$sewa->id) }}" method="POST" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Yakin ingin menghapus riwayat ini?')">Hapus</button>
</form>
@endif
</td>
<td class="py-3 px-4">
<span class="px-2 py-1 rounded-full text-xs font-semibold
@if($sewa->status == 'pending') bg-yellow-100 text-yellow-800
@elseif($sewa->status == 'confirmed') bg-blue-100 text-blue-800
@elseif($sewa->status == 'ongoing') bg-indigo-100 text-indigo-800
@elseif($sewa->status == 'completed') bg-green-100 text-green-800
@elseif($sewa->status == 'dibatalkan') bg-red-100 text-red-800
@endif">
{{ ucfirst($sewa->status) }}
</span>
</td>
<td class="py-3 px-4">
<div class="flex flex-col sm:flex-row justify-center sm:space-x-2 space-y-2 sm:space-y-0">
<!-- Tombol Detail -->
<a href="{{ route('admin.riwayat.show', $sewa->id) }}"
class="bg-blue-600 text-white px-3 py-1 rounded hover:bg-blue-700 text-sm">
Detail
</a>
<!-- Tombol Chat -->
<a href="{{ route('chat.show', $sewa->user_id) }}"
class="bg-green-500 text-white px-3 py-1 rounded hover:bg-green-600 text-sm">
Chat
</a>
@if($sewa->status === 'confirmed')
<!-- Tombol Tandai Selesai -->
<form action="{{ route('admin.riwayat.status', $sewa->id) }}" method="POST" class="inline">
@csrf
@method('PUT')
<input type="hidden" name="status" value="completed">
<button type="submit"
onclick="return confirm('Ubah status menjadi Completed?')"
class="bg-purple-600 text-white px-3 py-1 rounded hover:bg-purple-700 text-sm">
Tandai Selesai
</button>
</form>
@endif
@if(!in_array($sewa->status, ['completed', 'dibatalkan']))
<!-- Form Update Status -->
<form action="{{ route('admin.riwayat.status', $sewa->id) }}" method="POST">
@csrf
@method('PUT')
<select name="status"
onchange="this.form.submit()"
class="rounded-md border-gray-300 text-sm shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
<option value="pending" {{ $sewa->status == 'pending' ? 'selected' : '' }}>Pending</option>
<option value="confirmed" {{ $sewa->status == 'confirmed' ? 'selected' : '' }}>Confirmed</option>
<option value="ongoing" {{ $sewa->status == 'ongoing' ? 'selected' : '' }}>Ongoing</option>
<option value="completed" {{ $sewa->status == 'completed' ? 'selected' : '' }}>Completed</option>
<option value="dibatalkan" {{ $sewa->status == 'dibatalkan' ? 'selected' : '' }}>Dibatalkan</option>
</select>
</form>
@endif
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div class="text-center py-8">
<p class="text-gray-500">Belum ada riwayat pemesanan</p>
</div>
@endif
@empty
<tr>
<td colspan="6">Tidak ada riwayat pemesanan.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@endsection

View File

@ -150,7 +150,12 @@
Route::get('/riwayat/{id}', [RiwayatController::class, 'show'])->name('riwayat.show');
Route::put('/riwayat/{id}/status', [RiwayatController::class, 'updateStatus'])->name('riwayat.status');
Route::get('/riwayat/{id}/update-payment', [RiwayatController::class, 'showUpdatePaymentForm'])->name('riwayat.show-update-payment');
Route::put('/riwayat/{id}/update-payment', [RiwayatController::class, 'updatePayment'])->name('riwayat.update-payment');
// Route::put('/riwayat/{id}/update-payment', [RiwayatController::class, 'updatePayment'])->name('riwayat.update-payment');
// Route::post('/riwayat/update-status/{id}', [RiwayatController::class, 'updateStatus'])->name('riwayat.updateStatus');
Route::post('/riwayat/update-status/{id}', [\App\Http\Controllers\RiwayatController::class, 'updateStatus'])->name('riwayat.updateStatus');
Route::delete('/riwayat/hapus/{id}', [\App\Http\Controllers\RiwayatController::class, 'hapus']);
Route::get('/riwayat', [\App\Http\Controllers\RiwayatController::class, 'index'])->name('riwayat');
// Verifikasi Pembayaran
Route::get('/verifikasi', [App\Http\Controllers\Admin\VerifikasiController::class, 'index'])->name('verifikasi.index');