MIF_E31231070/routes/web.php

446 lines
16 KiB
PHP

<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\ChatbotController;
use App\Http\Controllers\AuthController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\VisitorController;
use Illuminate\Support\Facades\Http;
/*
|--------------------------------------------------------------------------
| 🌐 PUBLIC ROUTES (Bisa diakses Guest & User)
|--------------------------------------------------------------------------
*/
// Home & Company Profile
Route::get('/', function () {
$unggulan = \App\Models\Properti::with('blok')
->where('status_unit', '!=', 'terjual')
->limit(3)
->get();
return view('welcome', compact('unggulan'));
})->name('welcome');
Route::get('/tentang-kami', function () {
return view('tentang-kami');
})->name('tentang-kami');
Route::get('/halaman-kontak', function () {
return view('halaman-kontak');
})->name('halaman-kontak');
Route::get('/halaman-chatbot', function () {
return view('halaman-chatbot');
})->name('halaman-chatbot');
Route::post('/save-email-visitor', [VisitorController::class, 'store'])
->name('save-email-visitor');
// Katalog Properti (PUBLIC - Bisa dilihat tanpa login)
Route::get('/halaman-katalog', function () {
$query = \App\Models\Properti::with('blok')
->where('status_unit', '!=', 'terjual');
// Filter logic
if (request('perumahan')) {
$query->where('id_perumahan', request('perumahan'));
}
if (request('jenis')) {
$query->where('jenis_properti', request('jenis'));
}
if (request('kategori')) {
$query->where('kategori_properti', request('kategori'));
}
if (request('tipe')) {
$query->where('tipe_properti', request('tipe'));
}
if (request('harga')) {
$harga = request('harga');
if ($harga == '0-200') {
$query->whereBetween('harga_properti', [0, 200000000]);
} elseif ($harga == '200-300') {
$query->whereBetween('harga_properti', [200000000, 300000000]);
} elseif ($harga == '300-500') {
$query->whereBetween('harga_properti', [300000000, 500000000]);
} elseif ($harga == '500+') {
$query->where('harga_properti', '>', 500000000);
}
}
$properti = $query->paginate(9);
return view('halaman-katalog', compact('properti'));
})->name('halaman-katalog');
// Detail Properti (PUBLIC - Bisa dilihat tanpa login)
Route::get('/detail-katalog/{id}', function ($id) {
$properti = \App\Models\Properti::with('blok')->findOrFail($id);
return view('detail-katalog', compact('properti'));
})->name('detail-katalog');
// -- NOTIFIKASI --
// Notifikasi (Opsional: bisa public atau protected)
Route::get('/halaman-notifikasi', function () {
$notifikasi = \App\Models\Notifikasi::where('id_user', Auth::id())
->latest()
->get()
->unique('referensi_id'); // 🔥 biar tidak numpuk
return view('halaman-notifikasi', compact('notifikasi'));
})->name('halaman-notifikasi')->middleware('auth');
// Mark notifikasi sebagai sudah dibaca
Route::post('/notifikasi/{id}/read', function ($id) {
$notif = \App\Models\Notifikasi::where('id_user', Auth::id())
->findOrFail($id);
$notif->update(['status_baca' => 1]);
return response()->json(['success' => true]);
})->name('notifikasi.read')->middleware('auth');
Route::delete('/notifikasi-massal', function () {
$ids = explode(',', request('ids'));
\App\Models\Notifikasi::whereIn('id_notifikasi', $ids)
->where('id_user', auth()->id())
->delete();
return back()->with('success', 'Notifikasi berhasil dihapus');
})->name('notifikasi.hapus.massal')->middleware('auth');
/*
|--------------------------------------------------------------------------
| 🔐 AUTH ROUTES (Login, Logout, Password)
|--------------------------------------------------------------------------
*/
Route::get('/login', [AuthController::class, 'index'])->name('login');
Route::post('/login', [AuthController::class, 'login'])->name('login.proses');
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
Route::get('/gantipass', [AuthController::class, 'formGantiPassword'])->name('ganti-password');
Route::post('/gantipass', [AuthController::class, 'updatePassword'])->name('ganti-password.proses');
// Route untuk halaman register
Route::get('/register', function () {
return view('register'); // Pastikan file register.blade.php ada
})->name('register');
// Route untuk memproses register
Route::post('/register', [AuthController::class, 'register'])->name('register.proses');
/*
|--------------------------------------------------------------------------
| 🔒 PROTECTED ROUTES (Hanya User Login)
|--------------------------------------------------------------------------
*/
Route::middleware(['auth'])->group(function () {
// --- FORM PEMESANAN ---
// Halaman form booking (Hanya bisa diakses jika sudah login)
Route::get('/form-pemesanan/{id}', function ($id) {
$properti = \App\Models\Properti::where('id_properti', $id)->firstOrFail();
return view('form-pemesanan', compact('properti'));
})->name('form-pemesanan');
// Proses submit pemesanan
Route::post('/pemesanan/proses', [App\Http\Controllers\PemesananController::class, 'proses'])
->name('pemesanan.proses');
// --- RIWAYAT & DETAIL PEMESANAN ---
Route::get('/riwayat-pemesanan', function () {
$transaksi = \App\Models\Transaksi::with('properti')
->where('id_user', Auth::id())
->orderBy('tanggal_transaksi', 'desc')
->paginate(10);
return view('riwayat-pemesanan', compact('transaksi'));
})->name('riwayat-pemesanan');
Route::get('/detail-pemesanan/{id}', function ($id) {
$transaksi = \App\Models\Transaksi::with(['properti', 'user', 'pembayaran', 'kpr'])
->where('id_transaksi', $id)
->where('id_user', Auth::id())
->firstOrFail();
return view('detail-pemesanan', compact('transaksi'));
})->name('detail-pemesanan');
// ✅ Detail Properti (Hanya bisa diakses jika login)
Route::get('/detail-katalog/{id}', function ($id) {
$properti = \App\Models\Properti::with('blok')->findOrFail($id);
return view('detail-katalog', compact('properti'));
})->name('detail-katalog');
// --- HALAMAN TERIMS PEMESANAN ---
// Halaman terima kasih setelah pemesanan
Route::get('/pemesanan/terima-kasih/{id}', function ($id) {
$transaksi = \App\Models\Transaksi::with('properti')
->where('id_transaksi', $id)
->where('id_user', Auth::id())
->firstOrFail();
return view('terima-kasih', compact('transaksi'));
})->name('pemesanan.terima-kasih');
// --- CHATBOT & PROFIL ---
// 💡 Chatbot saya letakkan di sini agar bisa akses data user
// CHATBOT
Route::post('/chat/send', [ChatBotController::class, 'sendMessage'])->name('chat.send');
Route::get('/halaman-profil', function () {
return view('halaman-profil');
})->name('halaman-profil');
// 🔥 TAMBAHAN INI
Route::post('/upload-pp', [UserController::class, 'uploadPP'])->name('upload.pp');
Route::post('/update-profile', [UserController::class, 'updateProfile'])->name('profile.update');
});
/*
|--------------------------------------------------------------------------
| 👨‍💻 ADMIN ROUTES (Hanya Admin)
|--------------------------------------------------------------------------
*/
Route::prefix('admin')->middleware(['auth'])->group(function () {
Route::get('/', function () {
return view('admin.welcome');
})->name('admin.welcome');
Route::get('/halaman_chatbot', function () {
return view('admin.halaman_chatbot');
})->name('admin.halaman_chatbot');
// ========================
// DATA RUMAH
// ========================
Route::get('/data_rumah', function () {
$search = request('search');
if ($search) {
$properti = \App\Models\Properti::with(['blok', 'perumahan'])
->where('nama_properti', 'like', "%$search%")
->orWhere('tipe_properti', 'like', "%$search%")
->orWhere('jenis_properti', 'like', "%$search%")
->orWhere('status_unit', 'like', "%$search%")
->orWhereHas('perumahan', function($q) use ($search) {
$q->where('nama_perumahan', 'like', "%$search%");
})
->orWhereHas('blok', function($q) use ($search) {
$q->where('nama_blok', 'like', "%$search%");
})
->get();
$isPaginated = false;
} else {
$properti = \App\Models\Properti::with(['blok', 'perumahan'])
->paginate(10);
$isPaginated = true;
}
return view('admin.data_rumah', compact('properti', 'isPaginated'));
})->name('admin.data_rumah');
Route::delete('/hapus_rumah/{id}', function ($id) {
\App\Models\Properti::where('id_properti', $id)->delete();
return redirect()->route('admin.data_rumah')->with('success', 'Properti berhasil dihapus.');
})->name('admin.hapus_rumah');
Route::get('/edit_rumah/{id}', function ($id) {
$properti = \App\Models\Properti::with(['blok', 'perumahan'])
->where('id_properti', $id)->firstOrFail();
return view('admin.edit_rumah', compact('properti'));
})->name('admin.edit_rumah');
Route::get('/tambah-rumah', function () {
return view('admin.tambah-rumah');
})->name('admin.tambah-rumah');
// ========================
// DATA USER
// ========================
Route::get('/data_user', function () {
$search = request('search');
if ($search) {
$users = \App\Models\User::where('nama_user', 'like', "%$search%")
->orWhere('email_user', 'like', "%$search%")
->orWhere('no_hp', 'like', "%$search%")
->get();
$isPaginated = false;
} else {
$users = \App\Models\User::paginate(10);
$isPaginated = true;
}
return view('admin.data_user', compact('users', 'isPaginated'));
})->name('admin.data_user');
Route::get('/tambah-datauser', function () {
return view('admin.tambah-datauser');
})->name('admin.tambah-datauser');
Route::post('/tambah-datauser', function () {
\App\Models\User::create([
'nama_user' => request('nama_user'),
'email_user' => request('email_user'),
'no_hp' => request('no_hp'),
'password_user' => bcrypt(request('password_user')),
'role_user' => request('role_user'),
]);
return redirect()->route('admin.data_user')
->with('success', 'User berhasil ditambahkan.');
})->name('admin.tambah-datauser.simpan');
Route::get('/edit_user/{id}', function ($id) {
$user = \App\Models\User::where('id_user', $id)->firstOrFail();
return view('admin.edit_user', compact('user'));
})->name('admin.edit_user');
Route::post('/edit_user/{id}', function ($id) {
$user = \App\Models\User::where('id_user', $id)->firstOrFail();
$user->nama_user = request('nama_user');
$user->email_user = request('email_user');
$user->no_hp = request('no_hp');
$user->role_user = request('role_user');
if (request('password_user')) {
$user->password_user = bcrypt(request('password_user'));
}
$user->save();
return redirect()->route('admin.data_user')->with('success', 'User berhasil diupdate.');
})->name('admin.edit_user.update');
Route::delete('/hapus_user/{id}', function ($id) {
\App\Models\User::where('id_user', $id)->delete();
return redirect()->route('admin.data_user')
->with('success', 'User berhasil dihapus.');
})->name('admin.hapus_user');
// ========================
// VERIFIKASI
// ========================
Route::get('/halaman_verifikasi', function () {
$status = request('status');
$queryTransaksi = \App\Models\Transaksi::with(['user', 'properti']);
$queryDokumen = \App\Models\Dokumen::with('user');
if ($status == 'pending') {
$queryTransaksi->where('status_transaksi', 'menunggu_verifikasi');
$queryDokumen->where('status_verifikasi', 'pending');
} elseif ($status == 'diterima') {
$queryTransaksi->where('status_transaksi', 'menunggu_pembayaran');
$queryDokumen->where('status_verifikasi', 'diterima');
} elseif ($status == 'ditolak') {
$queryTransaksi->where('status_transaksi', 'ditolak');
$queryDokumen->where('status_verifikasi', 'ditolak');
}
$transaksi = $queryTransaksi->orderBy('tanggal_transaksi', 'desc')->get();
$user = \App\Models\User::with('dokumen')->get();
return view('admin.halaman_verifikasi', compact('transaksi', 'user'));
})->name('admin.halaman_verifikasi');
Route::post('/verifikasi/{id}/approve', function ($id) {
$dokumen = \App\Models\Dokumen::findOrFail($id);
$dokumen->status_verifikasi = 'diterima';
$dokumen->verified_at = now();
$dokumen->save();
\App\Models\Notifikasi::create([
'id_user' => $dokumen->id_user,
'judul' => 'Dokumen Disetujui',
'pesan' => 'Dokumen ' . $dokumen->jenis_dokumen . ' kamu telah diterima.',
'tipe' => 'dokumen',
'status_baca' => 0,
'status_kirim' => 'terkirim',
'channel' => 'in_app',
'referensi_id' => $dokumen->id_dokumen,
'referensi_tipe' => 'dokumen',
]);
return back()->with('success', 'Dokumen disetujui');
})->name('admin.verifikasi.approve');
Route::post('/verifikasi/{id}/tolak', function ($id) {
$dokumen = \App\Models\Dokumen::findOrFail($id);
$dokumen->status_verifikasi = 'ditolak';
$dokumen->catatan_verifikasi = request('catatan');
$dokumen->verified_at = now();
$dokumen->save();
return back()->with('success', 'Dokumen ditolak');
})->name('admin.verifikasi.tolak');
// MELIHAT DOKUMEN
Route::get('/verifikasi/{id}', function ($id) {
$user = \App\Models\User::with('dokumen')->findOrFail($id);
return view('admin.verifikasi_dokumen', compact('user'));
})->name('admin.verifikasi_dokumen');
Route::post('/verifikasi/{id}/selesai', function ($id) {
$user = \App\Models\User::with('dokumen')->findOrFail($id);
// contoh: cek apakah semua dokumen sudah diterima
$allApproved = $user->dokumen->every(function ($d) {
return $d->status_verifikasi === 'diterima';
});
// kirim notifikasi ke user
\App\Models\Notifikasi::create([
'id_user' => $user->id_user,
'judul' => 'Verifikasi Selesai',
'pesan' => $allApproved
? 'Semua dokumen kamu telah diverifikasi.'
: 'Verifikasi selesai, tapi masih ada dokumen yang perlu diperbaiki.',
'tipe' => 'dokumen',
'status_baca' => 0,
'status_kirim' => 'terkirim',
'channel' => 'in_app',
'referensi_id' => $user->id_user,
'referensi_tipe' => 'user',
]);
return redirect()->route('admin.halaman_verifikasi')
->with('success', 'Verifikasi selesai');
})->name('admin.verifikasi.selesai');
});
// TEST
Route::get('/test-gemini', function () {
$apiKey = env('GOOGLE_GEMINI_API_KEY');
$model = env('GOOGLE_GEMINI_MODEL', 'gemini-2.0-flash');
$url = "https://generativelanguage.googleapis.com/v1/models/{$model}:generateContent?key={$apiKey}";
$response = Http::post($url, [
'contents' => [[
'parts' => [['text' => 'Halo, apakah API key Gemini saya berfungsi?']]
]]
]);
if ($response->successful()) {
$text = $response->json('candidates.0.content.parts.0.text') ?? 'No response';
return '✅ API Key Gemini Berhasil! Response: ' . $text;
}
return '❌ Error ' . $response->status() . ': ' . $response->body();
});