latest() ->get(); return view('sewa', compact('pakets')); } /** * Menampilkan riwayat sewa */ public function riwayat(Request $request) { $query = Sewa::with(['user', 'paket']); // Jika user biasa, hanya tampilkan sewa miliknya if (auth()->user()->tipe_pengguna !== 'admin') { $query->where('user_id', auth()->id()); } $sewas = $query->orderBy('created_at', 'desc')->get(); return view('sewa.riwayat', [ 'sewas' => $sewas, 'showDetailPenyewa' => auth()->user()->tipe_pengguna === 'admin' ]); } /** * Menampilkan form pemesanan paket */ public function create($id) { try { $paket = Paket::with('ongkirKota')->findOrFail($id); // Cek apakah paket tersedia if (!$paket->is_available) { return redirect()->route('sewa.index') ->with('error', 'Maaf, paket ini sedang tidak tersedia.'); } return view('sewa.create', compact('paket')); } catch (\Exception $e) { return redirect()->route('sewa.index') ->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } } /** * Menyimpan data sewa baru */ public function store(Request $request) { $request->validate([ 'paket_id' => 'required|exists:pakets,id', 'tanggal_mulai' => 'required|date|after_or_equal:today', 'tanggal_selesai' => 'required|date|after_or_equal:tanggal_mulai', 'lokasi' => 'required|string|max:255', 'kota_id' => 'required|exists:paket_ongkir_kota,id', 'catatan' => 'nullable|string|max:1000', ]); try { $paket = Paket::findOrFail($request->paket_id); // Cek ketersediaan paket untuk tanggal yang dipilih $activeSewa = $paket->sewas() ->whereIn('status', ['confirmed', 'ongoing']) ->where(function($query) use ($request) { $query->whereBetween('tanggal_mulai', [$request->tanggal_mulai, $request->tanggal_selesai]) ->orWhereBetween('tanggal_selesai', [$request->tanggal_mulai, $request->tanggal_selesai]) ->orWhere(function($q) use ($request) { $q->where('tanggal_mulai', '<=', $request->tanggal_mulai) ->where('tanggal_selesai', '>=', $request->tanggal_selesai); }); }) ->count(); if ($activeSewa >= $paket->stok) { return back()->with('error', 'Maaf, paket tidak tersedia untuk tanggal yang dipilih.'); } // Cek minimum order $tanggal_mulai = Carbon::parse($request->tanggal_mulai); $tanggal_selesai = Carbon::parse($request->tanggal_selesai); $durasi = $tanggal_mulai->diffInDays($tanggal_selesai) + 1; if ($paket->minimum_order && $durasi < $paket->minimum_order) { return back()->with('error', "Minimum pemesanan untuk paket ini adalah {$paket->minimum_order} hari."); } // Validasi kota tujuan $kota = PaketOngkirKota::where('id', $request->kota_id) ->where('paket_id', $request->paket_id) ->firstOrFail(); // Hitung total harga $total_harga = ($paket->harga * $durasi) + $kota->biaya_ongkir; // Buat pesanan baru $sewa = Sewa::create([ 'user_id' => auth()->id(), 'paket_id' => $request->paket_id, 'kota_id' => $kota->id, 'ongkir' => $kota->biaya_ongkir, 'tanggal_mulai' => $request->tanggal_mulai, 'tanggal_selesai' => $request->tanggal_selesai, 'lokasi' => $request->lokasi, 'catatan' => $request->catatan, 'total_harga' => $total_harga, 'status' => 'pending' ]); return redirect()->route('sewa.show', $sewa->id) ->with('success', 'Pesanan berhasil dibuat. Silakan upload bukti pembayaran dan jaminan untuk melanjutkan proses penyewaan.'); } catch (\Exception $e) { return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } } public function show($id) { $sewa = Sewa::with(['paket', 'user', 'kota'])->findOrFail($id); return view('sewa.show', compact('sewa')); } public function uploadBukti(Request $request, $id) { $request->validate([ 'nominal_pembayaran' => 'required|numeric|min:1', 'bukti_pembayaran' => 'required|image|max:2048', 'jenis_jaminan' => 'required|in:ktp,sim', 'foto_jaminan' => 'required|image|max:2048', ]); try { $sewa = Sewa::findOrFail($id); // Validasi pemilik sewa if ($sewa->user_id !== auth()->id()) { return back()->with('error', 'Anda tidak memiliki akses untuk mengupload bukti pembayaran ini.'); } // Validasi status sewa if ($sewa->status !== 'pending') { return back()->with('error', 'Status sewa tidak valid untuk upload bukti pembayaran.'); } // Validasi nominal pembayaran if ($request->nominal_pembayaran > $sewa->total_harga) { return back()->with('error', 'Nominal pembayaran tidak boleh melebihi total harga sewa.'); } // Upload bukti pembayaran if ($request->hasFile('bukti_pembayaran')) { if ($sewa->bukti_pembayaran) { Storage::disk('public')->delete($sewa->bukti_pembayaran); } $pathBukti = $request->file('bukti_pembayaran') ->store('bukti-pembayaran/' . date('Y/m'), 'public'); } // Upload foto jaminan if ($request->hasFile('foto_jaminan')) { if ($sewa->foto_jaminan) { Storage::disk('public')->delete($sewa->foto_jaminan); } $pathJaminan = $request->file('foto_jaminan') ->store('jaminan/' . date('Y/m'), 'public'); } // Update data sewa $sewa->update([ 'bukti_pembayaran' => $pathBukti ?? $sewa->bukti_pembayaran, 'jenis_jaminan' => $request->jenis_jaminan, 'foto_jaminan' => $pathJaminan ?? $sewa->foto_jaminan, 'nominal_pembayaran' => $request->nominal_pembayaran, 'tanggal_pembayaran' => now(), 'status' => 'pending' ]); return redirect()->route('riwayat') ->with('success', 'Bukti pembayaran dan jaminan berhasil diupload. Mohon tunggu verifikasi dari admin.'); } catch (\Exception $e) { return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } } public function uploadJaminan(Request $request, $id) { $request->validate([ 'jenis_jaminan' => 'required|in:ktp,sim', 'foto_jaminan' => 'required|image|max:2048', // max 2MB ]); $sewa = Sewa::findOrFail($id); if ($request->hasFile('foto_jaminan')) { // Hapus file jaminan lama jika ada if ($sewa->foto_jaminan) { Storage::disk('public')->delete($sewa->foto_jaminan); } // Simpan file jaminan baru $path = $request->file('foto_jaminan')->store('jaminan', 'public'); // Update data sewa $sewa->jenis_jaminan = $request->jenis_jaminan; $sewa->foto_jaminan = $path; $sewa->save(); return redirect()->route('sewa.show', $sewa->id) ->with('success', 'Jaminan berhasil diupload.'); } return back()->with('error', 'Terjadi kesalahan saat upload jaminan.'); } /** * Membatalkan penyewaan */ public function batal($id) { try { $sewa = Sewa::findOrFail($id); // Validasi pemilik sewa if ($sewa->user_id !== auth()->id()) { return back()->with('error', 'Anda tidak memiliki akses untuk membatalkan penyewaan ini.'); } // Validasi status sewa if (!in_array($sewa->status, ['pending', 'confirmed'])) { return back()->with('error', 'Penyewaan tidak dapat dibatalkan karena status sudah ' . $sewa->status_label); } // Jika status sudah confirmed, tambahkan catatan pembatalan if ($sewa->status === 'confirmed') { $sewa->catatan = trim($sewa->catatan . "\n[DIBATALKAN OLEH PENYEWA SETELAH DISETUJUI] - " . now()); } // Update status menjadi dibatalkan $sewa->status = 'dibatalkan'; $sewa->save(); return redirect()->route('riwayat') ->with('success', 'Penyewaan berhasil dibatalkan.' . ($sewa->status === 'confirmed' ? ' Mohon hubungi admin untuk informasi biaya pembatalan.' : '')); } catch (\Exception $e) { return back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } } /** * Mengambil detail sewa untuk ditampilkan di modal */ public function detail($id) { try { $sewa = Sewa::with(['user', 'paket', 'kota']) ->findOrFail($id); // Jika bukan admin, pastikan hanya bisa melihat sewa miliknya if (auth()->user()->tipe_pengguna !== 'admin' && $sewa->user_id !== auth()->id()) { return response()->json([ 'error' => 'Unauthorized' ], 403); } // Format tanggal $sewa->tanggal_mulai = Carbon::parse($sewa->tanggal_mulai)->format('d M Y'); $sewa->tanggal_selesai = Carbon::parse($sewa->tanggal_selesai)->format('d M Y'); // Format angka $sewa->total_harga = number_format($sewa->total_harga, 0, ',', '.'); if ($sewa->nominal_pembayaran) { $sewa->nominal_pembayaran = number_format($sewa->nominal_pembayaran, 0, ',', '.'); } return response()->json($sewa); } catch (\Exception $e) { return response()->json([ 'error' => 'Terjadi kesalahan: ' . $e->getMessage() ], 500); } } public function detailJson($id) { $sewa = Sewa::with(['paket.barangs', 'user', 'kota'])->findOrFail($id); return response()->json([ 'id' => $sewa->id, 'paket' => [ 'nama_paket' => $sewa->paket->nama_paket, 'jenis_paket' => $sewa->paket->jenis_paket, 'harga' => $sewa->paket->harga, ], 'user' => [ 'nama' => $sewa->user->nama, 'email' => $sewa->user->email, ], 'tanggal_mulai' => $sewa->tanggal_mulai, 'tanggal_selesai' => $sewa->tanggal_selesai, 'status' => $sewa->status, 'total_harga' => $sewa->total_harga, 'lokasi' => $sewa->lokasi, 'kota' => $sewa->kota ? $sewa->kota->nama_kota : null, 'catatan' => $sewa->catatan, 'barangs' => $sewa->paket->barangs->map(function($barang) { return [ 'nama_barang' => $barang->nama_barang, 'jumlah' => $barang->pivot->jumlah ]; }), ]); } }