1703 lines
46 KiB
PHP
1703 lines
46 KiB
PHP
<?php
|
|
|
|
use Illuminate\Support\Facades\Route;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use App\Http\Controllers\ChatbotController;
|
|
use App\Http\Controllers\AuthController;
|
|
use App\Http\Controllers\TransaksiController;
|
|
use App\Http\Controllers\UserController;
|
|
use App\Http\Controllers\VisitorController;
|
|
use App\Http\Controllers\MonitoringController;
|
|
use App\Http\Controllers\LaporanPenjualanController;
|
|
use App\Http\Controllers\DokumenController;
|
|
use App\Http\Controllers\PerumahanController;
|
|
use App\Http\Controllers\BlokController;
|
|
use App\Helpers\StatusHelper;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use App\Mail\NotifikasiEmail;
|
|
use App\Models\LeadEmail;
|
|
use App\Http\Controllers\Auth\GoogleController;
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| 🌐 PUBLIC ROUTES (Bisa diakses Guest & User)
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
// Home & Company Profile
|
|
Route::get('/', function () {
|
|
$unggulan = \App\Models\Properti::with('blok','gambar')
|
|
->where('status_unit', '!=', 'terjual')
|
|
->inRandomOrder()
|
|
->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');
|
|
|
|
// IKLAN
|
|
// TRACK VISITOR WEBSITE
|
|
Route::post('/track-visitor', function () {
|
|
|
|
\App\Http\Controllers\VisitorController::track('website');
|
|
|
|
return response()->json([
|
|
'success' => true
|
|
]);
|
|
|
|
})->name('track-visitor');
|
|
|
|
|
|
// TRACK VISITOR POPUP
|
|
// Route::post('/track-visitor-popup', function () {
|
|
|
|
// \App\Http\Controllers\VisitorController::track('popup_email');
|
|
|
|
// return response()->json([
|
|
// 'success' => true
|
|
// ]);
|
|
|
|
// })->name('track-visitor-popup');
|
|
|
|
|
|
// Katalog Properti (PUBLIC - Bisa dilihat tanpa login)
|
|
Route::get('/halaman-katalog', function () {
|
|
$query = \App\Models\Properti::with('blok','gambar')
|
|
->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->inRandomOrder()->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','gambar')->findOrFail($id);
|
|
return view('detail-katalog', compact('properti'));
|
|
})->name('detail-katalog');
|
|
|
|
|
|
|
|
// -- NOTIFIKASI --
|
|
// Notifikasi (Opsional: bisa public atau protected)
|
|
Route::get('/halaman-notifikasi', function () {
|
|
// tandai semua notif user sebagai sudah dibaca
|
|
\App\Models\Notifikasi::where('id_user', Auth::id())
|
|
->where('status_baca', 0)
|
|
->update([
|
|
'status_baca' => 1
|
|
]);
|
|
|
|
// ambil data notif
|
|
$notifikasi = \App\Models\Notifikasi::where('id_user', Auth::id())
|
|
->latest()
|
|
->get()
|
|
->unique('referensi_id');
|
|
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');
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| 🤖 CHATBOT
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
// halaman chatbot
|
|
Route::get(
|
|
'/halaman-chatbot',
|
|
[ChatbotController::class, 'index']
|
|
)->name('halaman-chatbot');
|
|
|
|
// kirim pesan chatbot
|
|
Route::post(
|
|
'/chatbot/kirim',
|
|
[ChatbotController::class, 'kirim']
|
|
)->name('chatbot.kirim');
|
|
|
|
// hapus riwayat chat
|
|
Route::delete(
|
|
'/chatbot/hapus-riwayat',
|
|
[ChatbotController::class, 'hapusRiwayat']
|
|
)->middleware('auth');
|
|
|
|
// =========================
|
|
// AMBIL PESAN TERBARU CHATBOT
|
|
// =========================
|
|
Route::get('/chatbot/pesan-terbaru', function(Request $request) {
|
|
|
|
return response()->json([
|
|
'session_id' => $request->session_id,
|
|
'messages' => \App\Models\ChatbotMessage::where(
|
|
'id_sessions',
|
|
$request->session_id
|
|
)->get()
|
|
]);
|
|
|
|
});
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| 🔐 AUTH ROUTES (Login, Logout, Password)
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
// LOGIN GOOGLE
|
|
Route::get('/auth/google', [GoogleController::class, 'redirect'])->name('google.login');
|
|
Route::get('/auth/google/callback', [GoogleController::class, 'callback']);
|
|
|
|
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');
|
|
|
|
// kirim chatbot
|
|
Route::post('/chatbot/kirim', [ChatbotController::class, 'kirim'])->name('chatbot.kirim');
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| 🔒 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','pemesanan')
|
|
->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}', [MonitoringController::class, 'pelanggan'])
|
|
->name('detail-pemesanan');
|
|
|
|
|
|
|
|
// ✅ Detail Properti (Hanya bisa diakses jika login)
|
|
Route::get('/detail-katalog/{id}', function ($id) {
|
|
$properti = \App\Models\Properti::with('blok','gambar')->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
|
|
|
|
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');
|
|
|
|
});
|
|
|
|
// PEMBAYARAN LUNAS
|
|
Route::get(
|
|
'/invoice/{id}',
|
|
[TransaksiController::class, 'invoice']
|
|
)->name('invoice');
|
|
|
|
Route::get('/invoice/{id}/pdf', [TransaksiController::class, 'downloadPdf'])
|
|
->name('invoice.pdf');
|
|
|
|
// Route::post(
|
|
// '/pembayaran-lunas/store',
|
|
// [TransaksiController::class, 'storePembayaranLunas']
|
|
// )->name('pembayaran.lunas.store');
|
|
|
|
|
|
// YANG LAMA INI
|
|
Route::get(
|
|
'/pembayaran-lunas/berhasil/{id}',
|
|
function ($id) {
|
|
|
|
$transaksi = \App\Models\Transaksi::with('properti')
|
|
->findOrFail($id);
|
|
|
|
return view(
|
|
'terimakasih-pembayaran',
|
|
compact('transaksi')
|
|
);
|
|
}
|
|
)->name('pembayaran.lunas.berhasil');
|
|
|
|
Route::post('/upload-bukti', [DokumenController::class, 'uploadBuktiPembayaran'])
|
|
->name('user.upload.bukti');
|
|
|
|
// EMAILLL
|
|
Route::get('/auth/google', [AuthController::class, 'redirectToGoogle'])
|
|
->name('google.login');
|
|
|
|
Route::get('/auth/google/callback', [AuthController::class, 'handleGoogleCallback'])
|
|
->name('google.callback');
|
|
|
|
// GMAIL
|
|
Route::post('/save-email-visitor', function () {
|
|
|
|
$email = request('email');
|
|
|
|
// Simpan ke database
|
|
LeadEmail::firstOrCreate(
|
|
[
|
|
'email' => $email
|
|
],
|
|
[
|
|
'sumber' => 'popup'
|
|
]
|
|
);
|
|
|
|
// Kirim email ke admin
|
|
Mail::to('aylaanputri05@gmail.com')->send(
|
|
new NotifikasiEmail([
|
|
'judul' => 'Lead Baru Masuk',
|
|
'pesan' => 'Ada calon customer baru: ' . $email
|
|
])
|
|
);
|
|
|
|
return back()->with(
|
|
'success',
|
|
'Terima kasih, data berhasil dikirim.'
|
|
);
|
|
|
|
})->name('save-email-visitor');
|
|
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| 👨💻 ADMIN ROUTES (Hanya Admin)
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
Route::prefix('admin')->middleware(['auth'])->group(function () {
|
|
|
|
// ========================
|
|
// DASHBOARD
|
|
// =======================
|
|
Route::get('/', function () {
|
|
|
|
// ========================
|
|
// CARD DASHBOARD
|
|
// ========================
|
|
|
|
$totalVisitor = \App\Models\VisitorLog::count();
|
|
|
|
$totalLeads = \App\Models\LeadEmail::count();
|
|
|
|
$totalTransaksi = \App\Models\Transaksi::where(
|
|
'status_transaksi',
|
|
'berhasil'
|
|
)->count();
|
|
|
|
$totalUser = \App\Models\User::count();
|
|
|
|
|
|
// ========================
|
|
// AKTIVITAS TERBARU
|
|
// ========================
|
|
|
|
$recentActivities = \App\Models\LogAktivitas::with('user')
|
|
->latest()
|
|
->take(5)
|
|
->get()
|
|
->map(function ($item) {
|
|
|
|
return [
|
|
'icon' => $item->icon,
|
|
'text' => ($item->user->nama_user ?? '-') . ' - ' . $item->aktivitas,
|
|
'created_at' => $item->created_at
|
|
? $item->created_at->toISOString()
|
|
: null,
|
|
'time' => $item->created_at
|
|
];
|
|
});
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| CHART PENJUALAN BULANAN
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
$labelBulanan = [
|
|
'Jan',
|
|
'Feb',
|
|
'Mar',
|
|
'Apr',
|
|
'Mei',
|
|
'Jun',
|
|
'Jul',
|
|
'Agu',
|
|
'Sep',
|
|
'Okt',
|
|
'Nov',
|
|
'Des'
|
|
];
|
|
|
|
$dataTransaksi = [];
|
|
$dataPendapatan = [];
|
|
|
|
for ($bulan = 1; $bulan <= 12; $bulan++) {
|
|
|
|
// Total transaksi per bulan
|
|
$totalTransaksiBulanan = \App\Models\Transaksi::whereMonth(
|
|
'tanggal_transaksi',
|
|
$bulan
|
|
)
|
|
->whereYear(
|
|
'tanggal_transaksi',
|
|
now()->year
|
|
)
|
|
->count();
|
|
|
|
// Total pendapatan per bulan
|
|
$totalPendapatanBulanan = \App\Models\Transaksi::whereMonth(
|
|
'tanggal_transaksi',
|
|
$bulan
|
|
)
|
|
->whereYear(
|
|
'tanggal_transaksi',
|
|
now()->year
|
|
)
|
|
->where('status_transaksi', 'berhasil')
|
|
->sum('total_harga');
|
|
|
|
$dataTransaksi[] = $totalTransaksiBulanan;
|
|
|
|
$dataPendapatan[] = $totalPendapatanBulanan;
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| CHART PENJUALAN TAHUNAN
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
$labelTahunan = [];
|
|
|
|
$dataTahunanTransaksi = [];
|
|
|
|
$dataTahunanPendapatan = [];
|
|
|
|
$tahunSekarang = now()->year;
|
|
|
|
for ($tahun = $tahunSekarang - 4; $tahun <= $tahunSekarang; $tahun++) {
|
|
|
|
$labelTahunan[] = $tahun;
|
|
|
|
// Total transaksi tahunan
|
|
$totalTransaksiTahunan = \App\Models\Transaksi::whereYear(
|
|
'tanggal_transaksi',
|
|
$tahun
|
|
)->count();
|
|
|
|
// Total pendapatan tahunan
|
|
$totalPendapatanTahunan = \App\Models\Transaksi::whereYear(
|
|
'tanggal_transaksi',
|
|
$tahun
|
|
)
|
|
->where('status_transaksi', 'berhasil')
|
|
->sum('total_harga');
|
|
|
|
$dataTahunanTransaksi[] = $totalTransaksiTahunan;
|
|
|
|
$dataTahunanPendapatan[] = $totalPendapatanTahunan;
|
|
}
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| CHART STATUS TRANSAKSI
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
$chartStatus = [
|
|
|
|
'berhasil' => \App\Models\Transaksi::where(
|
|
'status_transaksi',
|
|
'berhasil'
|
|
)->count(),
|
|
|
|
'menunggu_pembayaran' => \App\Models\Transaksi::where(
|
|
'status_transaksi',
|
|
'menunggu_pembayaran'
|
|
)->count(),
|
|
|
|
'menunggu_verifikasi' => \App\Models\Transaksi::where(
|
|
'status_transaksi',
|
|
'menunggu_verifikasi'
|
|
)->count(),
|
|
|
|
'perlu_upload_ulang' => \App\Models\Transaksi::where(
|
|
'status_transaksi',
|
|
'perlu_upload_ulang'
|
|
)->count(),
|
|
|
|
'ditolak' => \App\Models\Transaksi::where(
|
|
'status_transaksi',
|
|
'ditolak'
|
|
)->count(),
|
|
];
|
|
|
|
|
|
return view('admin.welcome', compact(
|
|
'totalVisitor',
|
|
'totalLeads',
|
|
'totalTransaksi',
|
|
'totalUser',
|
|
'recentActivities',
|
|
|
|
'labelBulanan',
|
|
'dataTransaksi',
|
|
'dataPendapatan',
|
|
|
|
'labelTahunan',
|
|
'dataTahunanTransaksi',
|
|
'dataTahunanPendapatan',
|
|
'chartStatus'
|
|
));
|
|
|
|
})->name('admin.welcome');
|
|
|
|
// AKTIVITI SEMUA
|
|
Route::get('/aktivitas', function () {
|
|
|
|
$recentActivities = \App\Models\LogAktivitas::with('user')
|
|
->latest()
|
|
->get()
|
|
->map(function ($item) {
|
|
|
|
return [
|
|
'id' => $item->id,
|
|
'type' => $item->tipe,
|
|
'icon' => $item->icon,
|
|
'user' => $item->user->nama_user ?? '-',
|
|
'role' => $item->user->role_user ?? 'user',
|
|
'email' => $item->user->email_user ?? '-',
|
|
'desc' => $item->aktivitas,
|
|
'created_at' => $item->created_at
|
|
? $item->created_at->toISOString()
|
|
: null,
|
|
];
|
|
|
|
});
|
|
|
|
return view('admin.aktivitas', compact('recentActivities'));
|
|
|
|
})->name('admin.aktivitas');
|
|
|
|
|
|
// ========================
|
|
// CLEAR LOG
|
|
// ========================
|
|
// HAPUS LOG AKTIVITAS PENGGUNA
|
|
Route::delete('/clear-logs', function () {
|
|
|
|
\App\Models\LogAktivitas::truncate();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Semua log aktivitas berhasil dihapus.'
|
|
]);
|
|
|
|
})->name('admin.clear_logs');
|
|
|
|
|
|
// ========================
|
|
// PESAN PELANGGAN
|
|
// ========================
|
|
Route::get('/pesan-pelanggan', function () {
|
|
|
|
$allChats = \App\Models\ChatbotMessage::orderBy(
|
|
'created_at',
|
|
'desc'
|
|
)->get();
|
|
|
|
$totalActiveChats = $allChats
|
|
->pluck('id_sessions')
|
|
->unique()
|
|
->count();
|
|
|
|
$newChatsToday = $allChats
|
|
->filter(function($chat){
|
|
|
|
return \Carbon\Carbon::parse(
|
|
$chat->created_at
|
|
)->isToday();
|
|
|
|
})
|
|
->pluck('id_sessions')
|
|
->unique()
|
|
->count();
|
|
|
|
|
|
// ========================
|
|
// AMBIL SESSION + USER + MESSAGE
|
|
// ========================
|
|
$sessions = \App\Models\ChatSession::with([
|
|
|
|
'user',
|
|
|
|
'messages' => function($q){
|
|
|
|
$q->orderBy(
|
|
'created_at',
|
|
'asc'
|
|
);
|
|
|
|
}
|
|
|
|
])->get();
|
|
|
|
|
|
// ========================
|
|
// SORT SESSION BERDASARKAN CHAT TERBARU
|
|
// ========================
|
|
$sessions = $sessions->sortByDesc(function($session){
|
|
|
|
return optional(
|
|
$session->messages->last()
|
|
)->created_at;
|
|
|
|
});
|
|
|
|
|
|
// ========================
|
|
// DATA UNTUK LIST CHAT KIRI
|
|
// ========================
|
|
$chatSessions = $sessions->map(function($session){
|
|
|
|
$lastMessage = $session->messages->last();
|
|
|
|
$user = $session->user;
|
|
|
|
return [
|
|
|
|
'session_id' => $session->id_sessions,
|
|
|
|
'avatar' => $user?->foto_profil
|
|
? asset(
|
|
'storage/' .
|
|
$user->foto_profil
|
|
)
|
|
: strtoupper(
|
|
substr(
|
|
$user?->nama_user ?? 'U',
|
|
0,
|
|
1
|
|
)
|
|
),
|
|
|
|
'nama' => $user?->nama_user
|
|
?? 'Pengguna',
|
|
|
|
// preview chat terakhir
|
|
'preview' => $lastMessage?->message
|
|
?? 'Belum ada pesan',
|
|
|
|
// waktu chat terakhir
|
|
'time' => $lastMessage?->created_at
|
|
?? $session->created_at,
|
|
|
|
// status
|
|
'status' => $session->status_chat
|
|
|
|
];
|
|
|
|
});
|
|
|
|
|
|
// ========================
|
|
// CHAT YANG DIPILIH
|
|
// ========================
|
|
$selectedSessionId = request()->get(
|
|
'chat_session'
|
|
);
|
|
|
|
$selectedChat = $sessions
|
|
->where(
|
|
'id_sessions',
|
|
$selectedSessionId
|
|
)
|
|
->first();
|
|
|
|
|
|
// default ambil chat paling atas
|
|
if (!$selectedChat) {
|
|
|
|
$selectedChat = $sessions->first();
|
|
|
|
}
|
|
|
|
|
|
// ========================
|
|
// DATA PROPERTI UNTUK MODAL
|
|
// ========================
|
|
$allProperties = \App\Models\Properti::with([
|
|
'blok',
|
|
'gambar',
|
|
'perumahan'
|
|
])
|
|
->where('status_unit', 'tersedia')
|
|
->select(
|
|
'id_properti',
|
|
'id_perumahan', // 🔥 TAMBAH INI
|
|
'id_blok',
|
|
'nama_properti',
|
|
'jenis_properti',
|
|
'kategori_properti',
|
|
'tipe_properti',
|
|
'harga_properti',
|
|
'luas_bangunan',
|
|
'luas_tanah',
|
|
'stok_unit'
|
|
)
|
|
->get();
|
|
|
|
|
|
return view(
|
|
'admin.pesan_pelanggan',
|
|
compact(
|
|
'chatSessions',
|
|
'totalActiveChats',
|
|
'newChatsToday',
|
|
'selectedChat',
|
|
'allProperties'
|
|
)
|
|
);
|
|
|
|
})->name('admin.pesan_pelanggan');
|
|
|
|
|
|
// ========================
|
|
// KIRIM CHAT ADMIN
|
|
// ========================
|
|
Route::post('/kirim-chat', function(\Illuminate\Http\Request $request){
|
|
|
|
$properti = [];
|
|
|
|
// ========================
|
|
// AMBIL DATA PROPERTI
|
|
// ========================
|
|
if (
|
|
$request->properti_ids &&
|
|
count($request->properti_ids) > 0
|
|
) {
|
|
|
|
// ENTAR UABH
|
|
$properti = \App\Models\Properti::with([
|
|
'blok',
|
|
'perumahan',
|
|
'gambar'
|
|
])
|
|
->whereIn(
|
|
'id_properti',
|
|
$request->properti_ids
|
|
)
|
|
->select(
|
|
'id_properti',
|
|
'id_perumahan', // 🔥 TAMBAH INI
|
|
'id_blok',
|
|
'nama_properti',
|
|
'jenis_properti',
|
|
'kategori_properti',
|
|
'tipe_properti',
|
|
'harga_properti',
|
|
'luas_bangunan',
|
|
'luas_tanah',
|
|
'stok_unit'
|
|
)
|
|
->get();
|
|
}
|
|
|
|
|
|
// ========================
|
|
// SIMPAN CHAT
|
|
// ========================
|
|
$chat = \App\Models\ChatbotMessage::create([
|
|
|
|
'id_sessions' => $request->session_id,
|
|
'sender' => 'admin',
|
|
'message' => $request->message
|
|
?: 'Berikut rekomendasi properti untuk Anda 😊',
|
|
'properti_data' => json_encode($properti),
|
|
|
|
'created_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
// ========================
|
|
// RESPONSE
|
|
// ========================
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => $chat->message,
|
|
'time' => now()->format('H:i'),
|
|
'properti' => $properti
|
|
]);
|
|
|
|
})->name('admin.kirim_chat');
|
|
|
|
|
|
// ========================
|
|
// 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',
|
|
'gambar'
|
|
])
|
|
->withCount('gambar')
|
|
->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-datarumah',
|
|
compact('properti')
|
|
);
|
|
|
|
})->name('admin.edit_rumah');
|
|
|
|
Route::put('/edit_rumah/{id}', function (\Illuminate\Http\Request $request, $id) {
|
|
|
|
$properti = \App\Models\Properti::findOrFail($id);
|
|
|
|
// ======================
|
|
// HAPUS GAMBAR YANG DICENTANG HAPUS
|
|
// ======================
|
|
if ($request->filled('gambar_hapus')) {
|
|
|
|
$gambarHapus = \App\Models\GambarProperti::whereIn(
|
|
'id_gambar',
|
|
$request->gambar_hapus
|
|
)->get();
|
|
|
|
foreach ($gambarHapus as $gambar) {
|
|
|
|
Storage::disk('public')->delete(
|
|
'images/' . $gambar->path_gambar
|
|
);
|
|
|
|
$gambar->delete();
|
|
}
|
|
}
|
|
|
|
// ======================
|
|
// UPDATE DATA PROPERTI
|
|
// ======================
|
|
$properti->update([
|
|
'nama_properti' => $request->nama_properti,
|
|
'jenis_properti' => $request->jenis_properti,
|
|
'kategori_properti' => $request->kategori_properti,
|
|
'tipe_properti' => $request->tipe_properti,
|
|
'harga_properti' => $request->harga_properti,
|
|
'luas_bangunan' => $request->luas_bangunan,
|
|
'luas_tanah' => $request->luas_tanah,
|
|
'stok_unit' => $request->stok_unit,
|
|
'status_unit' => $request->status_unit,
|
|
]);
|
|
|
|
// ======================
|
|
// TAMBAH GAMBAR BARU
|
|
// ======================
|
|
|
|
if ($request->hasFile('gambar')) {
|
|
|
|
foreach ($request->file('gambar') as $file) {
|
|
|
|
$namaFile =
|
|
time().'_'.
|
|
uniqid().'.'.
|
|
$file->getClientOriginalExtension();
|
|
|
|
$file->storeAs(
|
|
'images',
|
|
$namaFile,
|
|
'public'
|
|
);
|
|
|
|
\App\Models\GambarProperti::create([
|
|
'id_properti' => $properti->id_properti,
|
|
'path_gambar' => $namaFile
|
|
]);
|
|
}
|
|
}
|
|
|
|
return redirect()
|
|
->route('admin.data_rumah')
|
|
->with(
|
|
'success',
|
|
'Data berhasil diupdate'
|
|
);
|
|
|
|
})->name('admin.update_rumah');
|
|
|
|
|
|
|
|
// ========================
|
|
// TAMBAH DATA RUMAH
|
|
// ========================
|
|
|
|
// BLOK
|
|
Route::get('/get-blok/{id_perumahan}', [BlokController::class, 'getByPerumahan']);
|
|
|
|
// FORM TAMBAH RUMAH
|
|
Route::get('/tambah-rumah', function () {
|
|
$blok = \App\Models\Blok::with('perumahan')->get();
|
|
$perumahan = \App\Models\Perumahan::all();
|
|
|
|
return view('admin.tambah-rumah', compact('blok', 'perumahan'));
|
|
|
|
})->name('admin.tambah-rumah');
|
|
|
|
|
|
// SIMPAN DATA RUMAH
|
|
Route::post('/tambah-rumah', function (
|
|
\Illuminate\Http\Request $request
|
|
) {
|
|
$request->validate([
|
|
'nama_properti' => 'required',
|
|
'jenis_properti' => 'required',
|
|
'kategori_properti' => 'required',
|
|
'tipe_properti' => 'required',
|
|
'id_blok' => 'required|exists:blok,id_blok',
|
|
'harga_properti' => 'required|numeric',
|
|
'luas_bangunan' => 'required|numeric',
|
|
'luas_tanah' => 'required|numeric',
|
|
'stok_unit' => 'required|numeric',
|
|
'status_unit' => 'required',
|
|
'gambar_properti.*' => 'nullable|image|mimes:jpg,jpeg,png|max:5120'
|
|
]);
|
|
|
|
$blok = \App\Models\Blok::findOrFail(
|
|
$request->id_blok
|
|
);
|
|
|
|
// ========================
|
|
// SIMPAN PROPERTI
|
|
// ========================
|
|
$bookingFee = (int) str_replace(['.', ',', 'Rp', ' '], '', 1000000);
|
|
$properti = \App\Models\Properti::create([
|
|
|
|
'id_perumahan' => $blok->id_perumahan,
|
|
'id_blok' => $blok->id_blok,
|
|
|
|
'nama_properti' => $request->nama_properti,
|
|
'jenis_properti' => $request->jenis_properti,
|
|
'kategori_properti' => $request->kategori_properti,
|
|
'tipe_properti' => $request->tipe_properti,
|
|
|
|
'harga_properti' => $request->harga_properti,
|
|
|
|
'bookingFee' => $bookingFee,
|
|
|
|
'luas_bangunan' => $request->luas_bangunan,
|
|
'luas_tanah' => $request->luas_tanah,
|
|
|
|
'stok_unit' => max(0, (int) $request->stok_unit),
|
|
'status_unit' => $request->status_unit,
|
|
]);
|
|
|
|
// ========================
|
|
// SIMPAN GAMBAR
|
|
// ========================
|
|
if ($request->hasFile('gambar')) {
|
|
|
|
foreach (
|
|
$request->file('gambar')
|
|
as $file
|
|
) {
|
|
|
|
$namaFile =
|
|
time() . '_' .
|
|
uniqid() . '_' .
|
|
$file->getClientOriginalName();
|
|
|
|
$file->storeAs(
|
|
'images',
|
|
$namaFile,
|
|
'public'
|
|
);
|
|
|
|
\App\Models\GambarProperti::create([
|
|
'id_properti' => $properti->id_properti,
|
|
'path_gambar' => $namaFile
|
|
]);
|
|
}
|
|
}
|
|
|
|
return redirect()
|
|
->route('admin.data_rumah')
|
|
->with(
|
|
'success',
|
|
'Properti berhasil ditambahkan.'
|
|
);
|
|
|
|
})->name('admin.simpan-rumah');
|
|
|
|
// PERUMAHAN
|
|
Route::get('/admin/perumahan', [PerumahanController::class, 'index'])
|
|
->name('admin.perumahan');
|
|
|
|
Route::get('/tambah-perumahan', function () {
|
|
return view('admin.tambah_perumahan');
|
|
})->name('admin.tambah-perumahan');
|
|
|
|
Route::put('/perumahan/{id}', [PerumahanController::class, 'update'])
|
|
->name('admin.update-perumahan');
|
|
|
|
Route::get('/perumahan/{id}/edit', [PerumahanController::class, 'edit'])
|
|
->name('admin.edit-perumahan');
|
|
|
|
Route::delete('/perumahan/{id}', [PerumahanController::class, 'destroy'])
|
|
->name('admin.hapus-perumahan');
|
|
|
|
Route::post('/simpan-perumahan', [PerumahanController::class, 'store'])
|
|
->name('admin.simpan-perumahan');
|
|
|
|
// KELOLA BLOK
|
|
Route::get('/perumahan/{id}/blok', [BlokController::class, 'index'])
|
|
->name('admin.kelola-blok');
|
|
|
|
Route::post('/perumahan/{id}/blok', [BlokController::class, 'store'])
|
|
->name('admin.tambah-blok');
|
|
|
|
Route::put('/blok/{id}', [BlokController::class, 'update'])
|
|
->name('admin.update-blok');
|
|
|
|
Route::delete('/blok/{id}', [BlokController::class, 'destroy'])
|
|
->name('admin.hapus-blok');
|
|
|
|
|
|
// ========================
|
|
// 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');
|
|
|
|
// UPLOAD BUKTI PELUNASAN
|
|
Route::post('/bukti/{id}/approve', [DokumenController::class, 'approveBukti'])
|
|
->name('admin.bukti.approve');
|
|
|
|
Route::post('/bukti/{id}/reject', [DokumenController::class, 'rejectBukti'])
|
|
->name('admin.bukti.reject');
|
|
|
|
// ========================
|
|
// VERIFIKASI
|
|
// ========================
|
|
|
|
// ✅ HALAMAN LIST VERIFIKASI (Query by Transaksi, bukan User)
|
|
Route::get('/halaman_verifikasi', function () {
|
|
|
|
$status = request('status');
|
|
$search = request('search');
|
|
|
|
// ✅ Query utama: ambil dari tabel Transaksi
|
|
$query = \App\Models\Transaksi::with([
|
|
'user',
|
|
'dokumen'
|
|
]);
|
|
|
|
// Filter search (cari di data user yang terkait transaksi)
|
|
if ($search) {
|
|
$query->whereHas('user', function($q) use ($search) {
|
|
$q->where('nama_user', 'like', "%{$search}%")
|
|
->orWhere('email_user', 'like', "%{$search}%")
|
|
->orWhere('no_hp', 'like', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
// Filter status (berdasarkan status dokumen)
|
|
if ($status == 'pending') {
|
|
$query->whereHas('dokumen', function($q) {
|
|
$q->where('status_verifikasi', 'pending');
|
|
});
|
|
} elseif ($status == 'diterima') {
|
|
$query->whereHas('dokumen', function($q) {
|
|
$q->where('status_verifikasi', 'diterima');
|
|
});
|
|
} elseif ($status == 'ditolak') {
|
|
$query->whereHas('dokumen', function($q) {
|
|
$q->where('status_verifikasi', 'ditolak');
|
|
});
|
|
}
|
|
|
|
// ✅ Pagination: setiap transaksi = 1 baris
|
|
$verifications = $query
|
|
->orderBy('id_transaksi', 'desc') // ✅ Urutkan dari pengajuan terbaru
|
|
->paginate(5)
|
|
->withQueryString();
|
|
|
|
// ✅ Kirim sebagai 'user' agar kompatibel dengan view lama
|
|
$transaksiLunas = \App\Models\Transaksi::with([
|
|
'user',
|
|
'properti'
|
|
])
|
|
->whereNotNull('bukti_transaksi')
|
|
->orderBy('id_transaksi', 'desc')
|
|
->paginate(5, ['*'], 'lunas_page');
|
|
|
|
return view('admin.halaman_verifikasi', [
|
|
'user' => $verifications,
|
|
'transaksi' => $verifications,
|
|
'transaksiLunas' => $transaksiLunas
|
|
]);
|
|
|
|
})->name('admin.halaman_verifikasi');
|
|
|
|
|
|
// ✅ APPROVE DOKUMEN
|
|
Route::post('/verifikasi/{id}/approve', function ($id) {
|
|
|
|
// ambil dokumen
|
|
$dokumen = \App\Models\Dokumen::findOrFail($id);
|
|
|
|
// update status
|
|
$dokumen->update([
|
|
'status_verifikasi' => 'diterima',
|
|
'verified_at' => now()
|
|
]);
|
|
|
|
// ambil transaksi dari id_transaksi
|
|
$transaksi = \App\Models\Transaksi::with('dokumen')
|
|
->findOrFail($dokumen->id_transaksi);
|
|
|
|
// cek apakah semua dokumen sudah diterima
|
|
$masihPending = $transaksi->dokumen()
|
|
->where('status_verifikasi', '!=', 'diterima')
|
|
->exists();
|
|
|
|
return back()->with(
|
|
'success',
|
|
'Dokumen berhasil disetujui'
|
|
);
|
|
|
|
})->name('admin.verifikasi.approve');
|
|
|
|
|
|
// ✅ TOLAK DOKUMEN
|
|
Route::post('/verifikasi/{id}/tolak', function ($id) {
|
|
|
|
$dokumen = \App\Models\Dokumen::findOrFail($id);
|
|
|
|
$catatan = request('catatan') ?: 'Dokumen ditolak oleh admin';
|
|
|
|
// update dokumen
|
|
$dokumen->update([
|
|
'status_verifikasi' => 'ditolak',
|
|
'catatan_verifikasi' => $catatan,
|
|
'verified_at' => now()
|
|
]);
|
|
|
|
// ambil transaksi user
|
|
$transaksi = \App\Models\Transaksi::find($dokumen->id_transaksi);
|
|
|
|
if($transaksi){
|
|
|
|
// reset transaksi agar user isi ulang
|
|
$transaksi->update([
|
|
'status_transaksi' => 'perlu_upload_ulang'
|
|
]);
|
|
|
|
// buat notifikasi sistem
|
|
\App\Models\Notifikasi::create([
|
|
'id_user' => $transaksi->id_user,
|
|
'judul' => 'Dokumen Ditolak',
|
|
'pesan' => 'Dokumen Anda ditolak admin. Silakan upload ulang dokumen dan isi ulang form pemesanan.',
|
|
'tipe' => 'verifikasi',
|
|
'referensi_id' => $transaksi->id_transaksi,
|
|
'referensi_tipe' => 'transaksi',
|
|
'status_baca' => 0
|
|
]);
|
|
|
|
// kirim email
|
|
$user = \App\Models\User::find($transaksi->id_user);
|
|
|
|
if($user && $user->email){
|
|
Mail::raw(
|
|
"Dokumen Anda ditolak.\n\nCatatan Admin: ".$catatan."\n\nSilakan login kembali dan isi ulang form pemesanan.",
|
|
function($message) use ($user){
|
|
$message->to($user->email)
|
|
->subject('Dokumen Pemesanan Ditolak');
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
return back()->with('success', 'Dokumen berhasil ditolak');
|
|
|
|
})->name('admin.verifikasi.tolak');
|
|
|
|
|
|
// ✅ DETAIL VERIFIKASI PER TRANSAKSI (Fix: kirim $transaksi ke view)
|
|
Route::get('/verifikasi/{id_transaksi}', function ($id_transaksi) {
|
|
|
|
// ✅ Ambil transaksi + relasi user & dokumen
|
|
$transaksi = \App\Models\Transaksi::with(['user', 'dokumen'])
|
|
->findOrFail($id_transaksi);
|
|
|
|
// ✅ Kirim 3 variabel ke view
|
|
return view('admin.verifikasi_dokumen', [
|
|
'user' => $transaksi->user,
|
|
'dokumen' => $transaksi->dokumen,
|
|
'transaksi' => $transaksi // ✅ INI YANG DIBUTUHKAN VIEW
|
|
]);
|
|
|
|
})->name('admin.verifikasi_dokumen');
|
|
|
|
|
|
// ✅ SELESAI VERIFIKASI
|
|
Route::post('/verifikasi/{id_transaksi}/selesai', function ($id_transaksi) {
|
|
|
|
// Optional: update status transaksi jika perlu
|
|
// $transaksi = \App\Models\Transaksi::findOrFail($id_transaksi);
|
|
// $transaksi->status_transaksi = 'diverifikasi';
|
|
// $transaksi->save();
|
|
|
|
return redirect()
|
|
->route('admin.halaman_verifikasi')
|
|
->with('success', 'Verifikasi selesai');
|
|
|
|
})->name('admin.verifikasi.selesai');
|
|
|
|
// verifikasi admin
|
|
|
|
|
|
// ========================
|
|
// LAPORAN PENJUALAN
|
|
// ========================
|
|
|
|
Route::get('/laporan-penjualan', [LaporanPenjualanController::class, 'index'])
|
|
->name('admin.laporan_penjualan');
|
|
Route::get(
|
|
'/admin/laporan-penjualan/export',
|
|
[LaporanPenjualanController::class, 'export']
|
|
)->name('laporan.penjualan.export');
|
|
|
|
// ========================
|
|
// MONITORING PEMESANAN
|
|
// ========================
|
|
Route::get('/monitoring-pemesanan',
|
|
[MonitoringController::class, 'index'])
|
|
->name('admin.monitoring-pemesanan');
|
|
|
|
Route::get('/admin/detail-monitoring/{id}', [App\Http\Controllers\MonitoringController::class, 'show'])
|
|
->name('monitoring.show');
|
|
|
|
// UPDATE MONITORING
|
|
Route::put('/admin/monitoring/{id}',
|
|
[MonitoringController::class, 'update']
|
|
)->name('monitoring.update');
|
|
|
|
// UPLOAD DOKUMEN ADMIN (MONITORING)
|
|
Route::post('/admin/upload-dokumen/{id_pemesanan}', function (
|
|
Illuminate\Http\Request $request,
|
|
$id_pemesanan
|
|
) {
|
|
|
|
$request->validate([
|
|
'dokumen_admin' => 'required|file|mimes:pdf,jpg,jpeg,png|max:5120'
|
|
]);
|
|
|
|
$pemesanan = \App\Models\Pemesanan::findOrFail($id_pemesanan);
|
|
|
|
$file = $request->file('dokumen_admin');
|
|
|
|
$namaFile = time() . '_admin_' . $file->getClientOriginalName();
|
|
|
|
$path = $file->storeAs('dokumen/admin', $namaFile, 'public');
|
|
|
|
/* =========================
|
|
1. DOKUMEN ADMIN
|
|
========================= */
|
|
\App\Models\Dokumen::create([
|
|
'id_user' => $pemesanan->id_user,
|
|
'id_pemesanan' => $pemesanan->id_pemesanan,
|
|
'id_transaksi' => $pemesanan->id_transaksi,
|
|
'jenis_dokumen' => 'dokumen_admin',
|
|
'nama_file' => $namaFile,
|
|
'path_file' => $path,
|
|
'tipe_file' => $file->getClientMimeType(),
|
|
'ukuran_file' => $file->getSize(),
|
|
'status_verifikasi' => 'diterima',
|
|
'catatan_verifikasi' => '',
|
|
'sumber_dokumen' => 'admin',
|
|
]);
|
|
|
|
/* =========================
|
|
LOG AKTIVITAS
|
|
========================= */
|
|
\App\Models\LogAktivitas::create([
|
|
'id_user' => auth()->id(),
|
|
'aktivitas' => 'Admin mengupload dokumen "' . $namaFile . '"',
|
|
'icon' => 'fa-upload',
|
|
'tipe' => 'dokumen',
|
|
'ref_id' => $pemesanan->id_pemesanan
|
|
]);
|
|
|
|
/* =========================
|
|
NOTIFIKASI
|
|
========================= */
|
|
\App\Models\Notifikasi::create([
|
|
'id_user' => $pemesanan->id_user,
|
|
'judul' => 'Dokumen Baru Dari Admin',
|
|
'pesan' => 'Admin mengupload dokumen baru untuk pemesanan Anda.',
|
|
'tipe' => 'dokumen',
|
|
'status_baca' => 0,
|
|
'status_kirim' => 'terkirim',
|
|
'channel' => 'in_app',
|
|
|
|
// 🔥 INI YANG BENAR
|
|
'referensi_id' => $pemesanan->id_pemesanan,
|
|
'referensi_tipe' => 'pemesanan',
|
|
]);
|
|
|
|
return back()->with('success', 'Dokumen berhasil diupload');
|
|
|
|
})->name('admin.upload.dokumen');
|
|
|
|
// HAPUS DOKUMEN ADMIN
|
|
Route::delete('/admin/hapus-dokumen/{id}', function ($id) {
|
|
|
|
$dokumen = \App\Models\Dokumen::findOrFail($id);
|
|
|
|
// hapus file dari storage
|
|
if (\Storage::disk('public')->exists($dokumen->path_file)) {
|
|
|
|
\Storage::disk('public')->delete($dokumen->path_file);
|
|
}
|
|
|
|
// hapus data db
|
|
$dokumen->delete();
|
|
|
|
return back()->with(
|
|
'success',
|
|
'Dokumen berhasil dihapus'
|
|
);
|
|
|
|
})->name('admin.hapus.dokumen');
|
|
});
|
|
|
|
// ========================
|
|
// VERIFIKASI PEMBAYARAN LUNAS
|
|
// ========================
|
|
Route::post('/admin/kirim-notif-pelunasan/{id_transaksi}', function ($id_transaksi) {
|
|
|
|
$transaksi = \App\Models\Transaksi::findOrFail($id_transaksi);
|
|
|
|
// update transaksi
|
|
StatusHelper::sync(
|
|
$transaksi,
|
|
'menunggu_pelunasan',
|
|
'Pelunasan Pembayaran'
|
|
);
|
|
|
|
// update pemesanan juga
|
|
$transaksi->update([
|
|
'progres' => 'pelunasan',
|
|
'tahap_saat_ini' => 'Pelunasan Pembayaran',
|
|
'status' => 'Proses'
|
|
]);
|
|
|
|
if ($transaksi->pemesanan) {
|
|
|
|
$transaksi->pemesanan->update([
|
|
'progres' => 'pelunasan',
|
|
'tahap_saat_ini' => 'Pelunasan Pembayaran',
|
|
'status' => 'Proses'
|
|
]);
|
|
|
|
}
|
|
|
|
// notif pelanggan
|
|
\App\Models\Notifikasi::create([
|
|
'id_user' => $transaksi->id_user,
|
|
'judul' => 'Pelunasan Pembayaran',
|
|
'pesan' =>
|
|
'Silakan lakukan pelunasan pembayaran dan upload bukti transfer.',
|
|
'tipe' => 'pelunasan',
|
|
'status_baca' => 0,
|
|
'status_kirim' => 'terkirim',
|
|
'channel' => 'in_app',
|
|
'referensi_id' => $transaksi->id_transaksi,
|
|
'referensi_tipe' => 'transaksi'
|
|
]);
|
|
|
|
return back()->with(
|
|
'success',
|
|
'Notifikasi pelunasan berhasil dikirim'
|
|
);
|
|
|
|
})->name('admin.kirim.notif.pelunasan');
|
|
|
|
Route::post('/admin/pembayaran_lunas/{id_transaksi}', function ($id_transaksi) {
|
|
|
|
$transaksi = \App\Models\Transaksi::findOrFail($id_transaksi);
|
|
|
|
// update status pembayaran
|
|
StatusHelper::sync(
|
|
$transaksi,
|
|
'selesai',
|
|
'Selesai'
|
|
);
|
|
|
|
// notif ke pelanggan
|
|
\App\Models\Notifikasi::create([
|
|
'id_user' => $transaksi->id_user,
|
|
'judul' => 'Pembayaran Diverifikasi',
|
|
'pesan' =>
|
|
'Pembayaran lunas Anda berhasil diverifikasi admin.',
|
|
'tipe' => 'transaksi',
|
|
|
|
'status_baca' => 0,
|
|
|
|
'status_kirim' => 'terkirim',
|
|
|
|
'channel' => 'in_app',
|
|
|
|
'referensi_id' => $transaksi->id_transaksi,
|
|
|
|
'referensi_tipe' => 'transaksi'
|
|
]);
|
|
|
|
// log aktivitas
|
|
\App\Models\LogAktivitas::create([
|
|
|
|
'id_user' => auth()->id(),
|
|
|
|
'aktivitas' =>
|
|
'Admin memverifikasi pembayaran lunas transaksi #' .
|
|
$transaksi->id_transaksi,
|
|
|
|
'icon' => 'fa-check-circle',
|
|
|
|
'tipe' => 'verifikasi',
|
|
|
|
'ref_id' => $transaksi->id_transaksi
|
|
]);
|
|
|
|
return back()->with(
|
|
'success',
|
|
'Pembayaran berhasil diverifikasi'
|
|
);
|
|
|
|
})->name('admin.verifikasi.pembayaran');
|
|
|
|
|
|
|
|
|
|
// ========================
|
|
// TEST EMAIL
|
|
// ========================
|
|
Route::get('/test-email', function () {
|
|
|
|
// Ganti email perus
|
|
Mail::to('naylawardhani96@gmail.com')->send(
|
|
new NotifikasiEmail([
|
|
'judul' => 'Tes Notifikasi',
|
|
'pesan' => 'Ini email dari sistem 🚀'
|
|
])
|
|
);
|
|
|
|
return 'Email terkirim!';
|
|
|
|
});
|
|
|
|
|