Refactor payment handling and UI updates

- Updated `PesanBuketController` to use storage for payment proof and modified the WhatsApp contact number.
- Enhanced CSS to hide browser-specific password input features.
- Adjusted Blade templates for admin views to accommodate additional columns and improved image handling.
- Updated image paths in various user views to use the storage disk.
- Added success and error alerts in the order history view.
- Cleaned up routes by removing unused test routes and ensuring proper naming conventions for route updates.
This commit is contained in:
LailaWulandarii 2026-01-09 13:16:15 +07:00
parent 3dafb244e1
commit d1d52cd17f
29 changed files with 323 additions and 141 deletions

View File

@ -11,17 +11,49 @@ class HistoriPesananController extends Controller
{ {
public function index() public function index()
{ {
$riwayatBuket = TransaksiBuket::with(['pelanggan', 'buket']) $riwayatBuket = TransaksiBuket::whereIn('status_transaksi', ['selesai', 'ditolak'])
->where('status_transaksi', '!=', 'menunggu_verifikasi') ->latest()->get();
->latest()
->get();
// Ambil riwayat foto (selain status menunggu) $riwayatFoto = BookingFoto::whereIn('status_booking', ['selesai', 'ditolak'])
$riwayatFoto = BookingFoto::with(['pelanggan', 'paketFoto']) ->latest()->get();
->where('status_booking', '!=', 'menunggu_verifikasi')
->latest()
->get();
return view('admin.pesanan.riwayat', compact('riwayatBuket', 'riwayatFoto')); return view('admin.pesanan.riwayat', compact('riwayatBuket', 'riwayatFoto'));
} }
public function updateStatus(Request $request, $id)
{
// Cek Kategori: Apakah ini Buket atau Foto?
$kategori = $request->kategori; // 'buket' atau 'foto'
$transaksi = null;
$noInvoice = "";
// LOGIKA PEMILIHAN TABEL
if ($kategori == 'buket') {
// --- CASE BUKET ---
$transaksi = \App\Models\TransaksiBuket::findOrFail($id);
if ($request->jenis == 'selesai') {
$transaksi->status_transaksi = 'selesai'; // Nama kolom: status_transaksi
$noInvoice = $transaksi->no_invoice;
}
} elseif ($kategori == 'foto') {
// --- CASE FOTO ---
$transaksi = \App\Models\BookingFoto::findOrFail($id);
if ($request->jenis == 'selesai') {
$transaksi->status_booking = 'selesai'; // Nama kolom: status_booking
$noInvoice = $transaksi->no_invoice;
}
}
// SIMPAN PERUBAHAN
if ($transaksi) {
$transaksi->save();
session()->flash('success', "Pesanan {$noInvoice} berhasil diselesaikan!");
return response()->json(['success' => true]);
}
return response()->json(['success' => false, 'message' => 'Data tidak ditemukan'], 404);
}
} }

View File

@ -10,9 +10,8 @@ class PesananBuketController extends Controller
{ {
public function index() public function index()
{ {
$pesanan = TransaksiBuket::with(['pelanggan']) $pesanan = TransaksiBuket::whereIn('status_transaksi', ['menunggu_verifikasi', 'diterima'])
->where('status_transaksi', 'menunggu_verifikasi') ->orderBy('created_at', 'ASC')
->latest()
->get(); ->get();
return view('admin.pesanan.buket', compact('pesanan')); return view('admin.pesanan.buket', compact('pesanan'));
@ -27,10 +26,13 @@ public function updateStatus(Request $request, $id)
// 2. Tentukan status & session flash sekaligus agar tidak dobel // 2. Tentukan status & session flash sekaligus agar tidak dobel
if ($request->jenis === 'terima') { if ($request->jenis === 'terima') {
$status = 'diterima'; $status = 'diterima';
session()->flash('success', "Pesanan #{$pesanan->no_invoice} telah diterima!"); // Alert Hijau session()->flash('success', "Pesanan {$pesanan->no_invoice} telah diterima!"); // Alert Hijau
} elseif ($request->jenis === 'selesai') {
$status = 'selesai';
session()->flash('success', "Pesanan {$pesanan->no_invoice} berhasil diselesaikan!");
} else { } else {
$status = 'ditolak'; $status = 'ditolak';
session()->flash('error', "Pesanan #{$pesanan->no_invoice} telah ditolak!"); // Alert Merah session()->flash('error', "Pesanan {$pesanan->no_invoice} telah ditolak!"); // Alert Merah
} }
// 3. Update database // 3. Update database
@ -51,7 +53,7 @@ public function updateStatus(Request $request, $id)
// 5. Susun Pesan berdasarkan kondisi // 5. Susun Pesan berdasarkan kondisi
if ($status === 'diterima') { if ($status === 'diterima') {
$msg = "Halo Kak *{$nama}*,\n\n" . $msg = "Halo Kak *{$nama}*,\n\n" .
"Pesanan Anda dengan Nomor Invoice: *#{$invoice}* telah kami *TERIMA* dan masuk dalam daftar proses pengerjaan.\n\n" . "Pesanan Anda dengan Nomor Invoice: *{$invoice}* telah kami *TERIMA* dan masuk dalam daftar proses pengerjaan.\n\n" .
"*Rincian Pesanan:*\n" . "*Rincian Pesanan:*\n" .
"- *Produk:* {$produk}\n" . "- *Produk:* {$produk}\n" .
"- *Total Bayar:* Rp {$total}\n" . "- *Total Bayar:* Rp {$total}\n" .
@ -61,7 +63,7 @@ public function updateStatus(Request $request, $id)
"Mohon simpan rincian ini dan ditunggu info selanjutnya ya Kak. Terima kasih! ✨"; "Mohon simpan rincian ini dan ditunggu info selanjutnya ya Kak. Terima kasih! ✨";
} else { } else {
$msg = "Halo Kak *{$nama}*,\n\n" . $msg = "Halo Kak *{$nama}*,\n\n" .
"Mengenai pesanan Anda dengan Nomor Invoice: *#{$invoice}* terpaksa kami *TOLAK* dikarenakan:\n\n" . "Mengenai pesanan Anda dengan Nomor Invoice: *{$invoice}* terpaksa kami *TOLAK* dikarenakan:\n\n" .
"*[TULIS ALASAN DI SINI]*\n\n" . "*[TULIS ALASAN DI SINI]*\n\n" .
"*Rincian Pesanan:*\n" . "*Rincian Pesanan:*\n" .
"- *Produk:* {$produk}\n" . "- *Produk:* {$produk}\n" .

View File

@ -11,11 +11,11 @@ class PesananFotoController extends Controller
public function index() public function index()
{ {
$pesanan = BookingFoto::with([ $pesanan = BookingFoto::with([
'pelanggan', // Untuk ambil Nama & No HP 'pelanggan',
'paketFoto', // Untuk ambil Nama Paket (misal: Paket Wisuda) 'paketFoto',
'detailAdditional.additional' // Lanjut ambil Nama Additional (misal: Background, Orang Tambahan) 'detailAdditional.additional'
]) ])
->where('status_booking', 'menunggu_verifikasi') ->whereIn('status_booking', ['menunggu_verifikasi', 'diterima'])
->latest() ->latest()
->get(); ->get();
@ -31,10 +31,13 @@ public function updateStatus(Request $request, $id)
// 2. Tentukan status & session flash // 2. Tentukan status & session flash
if ($request->jenis === 'terima') { if ($request->jenis === 'terima') {
$status = 'diterima'; $status = 'diterima';
session()->flash('success', "Booking #{$pesanan->no_invoice} telah diterima!"); session()->flash('success', "Booking {$pesanan->no_invoice} telah diterima!");
} elseif ($request->jenis === 'selesai') {
$status = 'selesai';
session()->flash('success', "Pesanan {$pesanan->no_invoice} berhasil diselesaikan!");
} else { } else {
$status = 'ditolak'; $status = 'ditolak';
session()->flash('error', "Booking #{$pesanan->no_invoice} telah ditolak!"); session()->flash('error', "Booking {$pesanan->no_invoice} telah ditolak!");
} }
// 3. Update database (Pastikan nama kolom status_booking sesuai migrasimu) // 3. Update database (Pastikan nama kolom status_booking sesuai migrasimu)
@ -60,16 +63,16 @@ public function updateStatus(Request $request, $id)
$list_additional .= "- " . $item->additional->nama . " (x" . $item->qty . ")\n"; $list_additional .= "- " . $item->additional->nama . " (x" . $item->qty . ")\n";
} }
} else { } else {
$list_additional = "- Tidak ada tambahan\n"; $list_additional = "- Tidak ada additional\n";
} }
// 6. Susun Pesan WA // 6. Susun Pesan WA
if ($status === 'diterima') { if ($status === 'diterima') {
$msg = "Halo Kak *{$nama}* ,\n\n" . $msg = "Halo Kak *{$nama}* ,\n\n" .
"Booking foto Anda dengan Invoice: *#{$invoice}* telah kami *TERIMA*. \n\n" . "Booking foto Anda dengan Invoice: *{$invoice}* telah kami *TERIMA*. \n\n" .
"*Rincian Booking:*\n" . "*Rincian Booking:*\n" .
"- *Paket:* {$paket}\n" . "- *Paket:* {$paket}\n" .
"*Tambahan:*\n{$list_additional}" . "*Additional:*\n{$list_additional}" .
"- *Total Bayar:* Rp {$total}\n\n" . "- *Total Bayar:* Rp {$total}\n\n" .
"*Jadwal Sesi Foto:*\n" . "*Jadwal Sesi Foto:*\n" .
" Tanggal: {$tanggal}\n" . " Tanggal: {$tanggal}\n" .
@ -77,13 +80,15 @@ public function updateStatus(Request $request, $id)
"Mohon datang 15 menit sebelum jadwal dimulai ya Kak. Sampai jumpa di studio! "; "Mohon datang 15 menit sebelum jadwal dimulai ya Kak. Sampai jumpa di studio! ";
} else { } else {
$msg = "Halo Kak *{$nama}*,\n\n" . $msg = "Halo Kak *{$nama}*,\n\n" .
"Mohon maaf, booking foto Anda dengan Invoice *#{$invoice}* terpaksa kami *TOLAK* dikarenakan:\n\n" . "Mohon maaf, booking foto Anda dengan Invoice *{$invoice}* terpaksa kami *TOLAK* dikarenakan:\n\n" .
"*[TULIS ALASAN DI SINI]*\n\n" . "*[TULIS ALASAN DI SINI]*\n\n" .
"*Rincian Booking:*\n" . "*Rincian Booking:*\n" .
"- *Paket:* {$paket}\n" . "- *Paket:* {$paket}\n" .
"*Tambahan:*\n{$list_additional}" . "*Additional:*\n{$list_additional}" .
"- *Total Bayar:* Rp {$total}\n" . "- *Total Bayar:* Rp {$total}\n" .
"- *Jadwal Sesi:* {$tanggal} ({$jam_mulai} - {$jam_selesai} WIB)\n\n" . "*Jadwal Sesi Foto:*\n" .
" Tanggal: {$tanggal}\n" .
" Jam: {$jam_mulai} - {$jam_selesai} WIB\n\n" .
"Admin kami akan segera menghubungi Kakak untuk info pengembalian dana atau penjadwalan ulang. Terima kasih. "; "Admin kami akan segera menghubungi Kakak untuk info pengembalian dana atau penjadwalan ulang. Terima kasih. ";
} }

View File

@ -11,6 +11,9 @@
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
class BookingFotoController extends Controller class BookingFotoController extends Controller
{ {
@ -40,9 +43,6 @@ public function detail($id)
public function loadCalendar(Request $request) public function loadCalendar(Request $request)
{ {
\Carbon\Carbon::setLocale('id'); \Carbon\Carbon::setLocale('id');
// Ambil bulan & tahun dari request AJAX, atau default sekarang
// $month = $request->month ?? date('m');
// $year = $request->year ?? date('Y');
$month = $request->month ?? date('m'); $month = $request->month ?? date('m');
$year = $request->year ?? date('Y'); $year = $request->year ?? date('Y');
$start = \Carbon\Carbon::createFromDate($year, $month, 1); $start = \Carbon\Carbon::createFromDate($year, $month, 1);
@ -50,8 +50,7 @@ public function loadCalendar(Request $request)
// Data Navigasi // Data Navigasi
$prevMonth = $start->copy()->subMonth(); $prevMonth = $start->copy()->subMonth();
$nextMonth = $start->copy()->addMonth(); $nextMonth = $start->copy()->addMonth();
// translatedFormat akan mengikuti locale 'id' di config Anda $currentMonthLabel = $start->isoFormat('MMMM YYYY');
$currentMonthLabel = $start->isoFormat('MMMM YYYY'); // Return hanya potongan HTML (Partial), bukan halaman full
$html = view('user.components.calendar-grid', compact( $html = view('user.components.calendar-grid', compact(
'start', 'start',
'prevMonth', 'prevMonth',
@ -64,8 +63,7 @@ public function loadCalendar(Request $request)
} }
public function cekSlot(Request $request) public function cekSlot(Request $request)
{ {
// Cari booking yang statusnya valid (bukan dibatalkan/ditolak)
// Sesuaikan status dengan logic bisnis kamu
$booked = BookingFoto::where('tgl_booking', $request->tanggal) $booked = BookingFoto::where('tgl_booking', $request->tanggal)
->whereIn('status_booking', ['menunggu_verifikasi', 'diterima', 'selesai']) ->whereIn('status_booking', ['menunggu_verifikasi', 'diterima', 'selesai'])
->get(['jam_mulai']); ->get(['jam_mulai']);
@ -149,8 +147,7 @@ public function cancelBooking()
} }
public function store(Request $request) public function store(Request $request)
{ {
// 1. Validasi Input menggunakan Format Validator $validator = Validator::make($request->all(), [
$validator = \Illuminate\Support\Facades\Validator::make($request->all(), [
'id_paket' => 'required|exists:paket_fotos,id_paket', 'id_paket' => 'required|exists:paket_fotos,id_paket',
'tgl_booking' => 'required|date|after_or_equal:today', 'tgl_booking' => 'required|date|after_or_equal:today',
'jam_mulai' => 'required', 'jam_mulai' => 'required',
@ -171,28 +168,42 @@ public function store(Request $request)
'mimes' => 'Format :attribute harus jpeg, png, atau jpg.', 'mimes' => 'Format :attribute harus jpeg, png, atau jpg.',
'max.file' => 'Ukuran :attribute maksimal adalah 2MB.', 'max.file' => 'Ukuran :attribute maksimal adalah 2MB.',
], [ ], [
// Alias Atribut agar lebih ramah
'id_paket' => 'paket foto',
'nama' => 'nama pemesan', 'nama' => 'nama pemesan',
'no_wa' => 'nomor WhatsApp', 'no_wa' => 'nomor WhatsApp',
'tgl_booking' => 'tanggal booking',
'jam_mulai' => 'jam mulai',
'bukti_bayar' => 'bukti pembayaran', 'bukti_bayar' => 'bukti pembayaran',
]); ]);
if ($validator->fails()) { DB::beginTransaction(); // Mulai Transaksi Database
return back()->withErrors($validator)->withInput();
}
\Illuminate\Support\Facades\DB::beginTransaction(); // Mulai Transaksi Database
try { try {
// 2. Ambil Data Paket & Hitung Waktu (Termasuk Tambahan Menit dari Addons) // 2. Ambil Data Paket & Hitung Waktu
$paket = \App\Models\PaketFoto::findOrFail($request->id_paket); $paket = PaketFoto::findOrFail($request->id_paket);
$totalDurasi = $paket->durasi;
// Asumsi durasi default 20 menit (atau ambil dari database jika ada kolom durasi)
$durasiMenit = $paket->durasi;
$jamMulai = \Carbon\Carbon::createFromFormat('H:i', $request->jam_mulai);
$jamSelesai = $jamMulai->copy()->addMinutes($durasiMenit);
// 3. Cek Slot Sekali Lagi (Mencegah Race Condition)
$isTaken = BookingFoto::where('tgl_booking', $request->tgl_booking)
->where('jam_mulai', $request->jam_mulai)
->whereIn('status_booking', ['menunggu_verifikasi', 'diterima', 'selesai'])
->exists();
if ($isTaken) {
return back()->with('error', 'Mohon maaf, slot waktu ini baru saja diambil orang lain.');
}
// 4. Simpan/Update Data Pelanggan
$pelanggan = Pelanggan::firstOrCreate(
['no_wa' => $request->no_wa],
['nama' => $request->nama]
);
// 6. Hitung Grand Total (Paket + Additional)
// Kita hitung ulang di server agar aman dari manipulasi inspect element
$grandTotal = $paket->harga; $grandTotal = $paket->harga;
$listAdditional = []; $listAdditional = [];
$totalDurasi = $durasiMenit;
if ($request->has('addons')) { if ($request->has('addons')) {
foreach ($request->addons as $idAddon => $qty) { foreach ($request->addons as $idAddon => $qty) {
if ($qty > 0) { if ($qty > 0) {
@ -222,26 +233,25 @@ public function store(Request $request)
// 3. Cek Slot Sekali Lagi (Mencegah Race Condition) // 3. Cek Slot Sekali Lagi (Mencegah Race Condition)
$isTaken = \App\Models\BookingFoto::where('tgl_booking', $request->tgl_booking) $isTaken = \App\Models\BookingFoto::where('tgl_booking', $request->tgl_booking)
->where('jam_mulai', $request->jam_mulai) ->where('jam_mulai', $request->jam_mulai)
->whereIn('status_booking', ['menunggu_verifikasi', 'diterima', 'selesai']) ->whereIn('status_booking', ['menunggu_verifikasi', 'diterima'])
->exists(); ->exists();
if ($isTaken) { if ($isTaken) {
return back()->with('error', 'Mohon maaf, slot waktu ini baru saja diambil orang lain.'); return back()->with('error', 'Mohon maaf, slot waktu ini baru saja diambil orang lain.');
} }
// 4. Simpan/Update Data Pelanggan // 4. Simpan Data Pelanggan
$pelanggan = \App\Models\Pelanggan::firstOrCreate( $pelanggan = \App\Models\Pelanggan::create([
['no_wa' => $request->no_wa], 'nama' => $request->nama,
['nama' => $request->nama] 'no_wa' => $request->no_wa
); ]);
// 5. Upload Bukti Bayar // 5. Upload Bukti Bayar
$pathBukti = null; $pathBukti = null;
if ($request->hasFile('bukti_bayar')) { if ($request->hasFile('bukti_bayar')) {
$file = $request->file('bukti_bayar'); $file = $request->file('bukti_bayar');
$namaFile = 'bukti_' . time() . $file->getClientOriginalExtension(); $namaFile = 'bukti_' . time() . '.' . $file->getClientOriginalExtension();
$file->move(public_path('img/payment'), $namaFile); $pathBukti = $file->storeAs('img/payment/foto', $namaFile, 'public');
$pathBukti = 'img/payment/foto' . $namaFile;
} }
// 6. Simpan Booking Utama // 6. Simpan Booking Utama
@ -278,19 +288,19 @@ public function store(Request $request)
$txtAddons .= "\n"; // Kasih jarak baris $txtAddons .= "\n"; // Kasih jarak baris
} }
// 8. Redirect ke WhatsApp // 8. Redirect ke WhatsApp
$pesan = "Halo Admin Flo.do! Saya sudah melakukan pembayaran untuk invoice {$booking->no_invoice}:" . $pesan = "Halo Admin Flo.do! Saya sudah melakukan pembayaran untuk invoice {$booking->no_invoice}:\n\n" .
"*Data Pemesan:*\n" . "*Data Pemesan:*\n" .
"Nama: {$pelanggan->nama}\n" . "Nama: {$request->nama}\n" .
"WA: {$pelanggan->no_wa}\n\n" . "WA: {$request->no_wa}\n\n" .
"*Detail Booking:*\n" . "*Detail Booking:*\n" .
"Nama Paket: {$request->nama}\n" . "Nama Paket: {$paket->nama}\n" .
$txtAddons . $txtAddons .
"Tanggal: " . \Carbon\Carbon::parse($request->tgl_booking)->translatedFormat('l, d F Y') . "\n" . "Tanggal: " . \Carbon\Carbon::parse($request->tgl_booking)->translatedFormat('l, d F Y') . "\n" .
"Jam: {$request->jam_mulai} - {$jamSelesai->format('H:i')} WIB\n" . "Jam: {$request->jam_mulai} - {$jamSelesai->format('H:i')} WIB\n" .
"Total: Rp " . number_format($grandTotal, 0, ',', '.') . "\n" . "Total: Rp " . number_format($grandTotal, 0, ',', '.') . "\n\n" .
"Mohon segera diproses, ya! Terima kasih."; "Mohon segera diproses, ya! Terima kasih.";
$urlWA = "https://wa.me/6289673668516?text=" . urlencode($pesan); $urlWA = "https://wa.me/6282337687878?text=" . urlencode($pesan);
session()->forget('payment_deadline'); session()->forget('payment_deadline');
return redirect()->route('booking.foto')->with([ return redirect()->route('booking.foto')->with([

View File

@ -114,22 +114,20 @@ public function store(Request $request)
$namaFile = null; $namaFile = null;
if ($request->hasFile('bukti_bayar')) { if ($request->hasFile('bukti_bayar')) {
$file = $request->file('bukti_bayar'); $file = $request->file('bukti_bayar');
// Membuat nama file unik berdasarkan waktu agar tidak tertimpa $namaFile = 'bukti_' . time() . '.' . $file->getClientOriginalExtension();
$namaFile = 'bukti_' . time() . $file->getClientOriginalExtension(); $pathBukti = $file->storeAs('img/payment/buket', $namaFile, 'public');
// Pindahkan ke folder public/img/payment
$file->move(public_path('img/payment/buket'), $namaFile);
} }
$transaksi = TransaksiBuket::create([ $transaksi = TransaksiBuket::create([
'id_pelanggan' => $pelanggan->id_pelanggan, 'id_pelanggan' => $pelanggan->id_pelanggan,
'id_buket' => $request->id_buket, 'id_buket' => $request->id_buket,
'tgl_ambil' => $request->tgl_ambil . ' ' . $request->waktu_ambil, 'tgl_ambil' => $request->tgl_ambil . ' ' . $request->waktu_ambil,
'request' => $request->request_khusus, // Ubah dari request_khusus ke request 'request' => $request->request_khusus,
'ucapan' => $request->ucapan, 'ucapan' => $request->ucapan,
'bukti_bayar' => 'img/payment/' . $namaFile, 'bukti_bayar' => $pathBukti,
'status_transaksi' => 'menunggu_verifikasi', // Ubah dari status ke status_transaksi 'status_transaksi' => 'menunggu_verifikasi',
'total_bayar' => $buket->harga, // Tambahkan ini karena total_bayar wajib di fillable 'total_bayar' => $buket->harga,
'no_invoice' => 'INV-BUKET-' . strtoupper(\Illuminate\Support\Str::random(6)), // Tambahkan invoice sederhana 'no_invoice' => 'INV-BUKET-' . strtoupper(\Illuminate\Support\Str::random(6)),
]); ]);
DB::commit(); DB::commit();
@ -144,7 +142,7 @@ public function store(Request $request)
"Total: Rp " . number_format($transaksi->buket->harga, 0, ',', '.') . "\n\n" . "Total: Rp " . number_format($transaksi->buket->harga, 0, ',', '.') . "\n\n" .
"Mohon segera diproses, ya! Terima kasih."; "Mohon segera diproses, ya! Terima kasih.";
$urlWA = "https://wa.me/6289673668516?text=" . urlencode($pesan); $urlWA = "https://wa.me/6282337687878?text=" . urlencode($pesan);
return redirect()->route('pesan.buket')->with([ return redirect()->route('pesan.buket')->with([
'success' => 'Pesanan Berhasil Dibuat!', 'success' => 'Pesanan Berhasil Dibuat!',

View File

@ -7233,6 +7233,22 @@ .login-logo {
margin-right: auto; margin-right: auto;
} }
/* Sembunyikan mata bawaan browser (Edge/IE) */
input[type="password"]::-ms-reveal,
input[type="password"]::-ms-clear {
display: none;
}
/* Sembunyikan mata bawaan browser (Chrome/Opera/Safari) - jarang muncul tapi buat jaga-jaga */
input[type="password"]::-webkit-contacts-auto-fill-button,
input[type="password"]::-webkit-credentials-auto-fill-button {
visibility: hidden;
display: none !important;
pointer-events: none;
position: absolute;
right: 0;
}
.offcanvas, .offcanvas,
.offcanvas-xxl, .offcanvas-xxl,
.offcanvas-xl, .offcanvas-xl,

View File

@ -285,7 +285,7 @@ class="btn icon btn-primary btn-action" data-bs-toggle="modal"
@include('admin.pesanan.partials.modal-buket') @include('admin.pesanan.partials.modal-buket')
@empty @empty
<tr> <tr>
<td colspan="7" class="text-center text-muted">Tidak ada pesanan buket yang <td colspan="8" class="text-center text-muted">Tidak ada pesanan buket yang
pending. pending.
</td> </td>
</tr> </tr>
@ -338,7 +338,7 @@ class="btn icon btn-primary btn-action" data-bs-toggle="modal"
@include('admin.pesanan.partials.modal-foto') @include('admin.pesanan.partials.modal-foto')
@empty @empty
<tr> <tr>
<td colspan="7" class="text-center text-muted">Tidak ada pesanan <td colspan="8" class="text-center text-muted">Tidak ada pesanan
foto yang pending.</td> foto yang pending.</td>
</tr> </tr>
@endforelse @endforelse

View File

@ -74,7 +74,7 @@ class="badge rounded-pill px-3 py-2
@include('admin.kelola-admin.partials.modal-delete') @include('admin.kelola-admin.partials.modal-delete')
@empty @empty
<tr> <tr>
<td colspan="4" class="text-center text-muted">Belum ada data admin.</td> <td colspan="6" class="text-center text-muted">Belum ada data admin.</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>

View File

@ -75,7 +75,7 @@
<td style="width: 12%" class="text-center">Rp <td style="width: 12%" class="text-center">Rp
{{ number_format($f->harga, 0, ',', '.') }}</td> {{ number_format($f->harga, 0, ',', '.') }}</td>
<td style="width:10%" class="text-center"> <td style="width:10%" class="text-center">
<img src="{{ asset($f->foto) }}" alt="Foto Produk" class="rounded" <img src="{{ asset('storage/' . $f->foto) }}" alt="Foto Produk" class="rounded"
style="width: 50px; height: 50px; object-fit: cover;"> style="width: 50px; height: 50px; object-fit: cover;">
</td> </td>
<td class="col-auto text-center"> <td class="col-auto text-center">
@ -100,7 +100,7 @@
@include('admin.paket-foto.partials.modal-delete-foto') @include('admin.paket-foto.partials.modal-delete-foto')
@empty @empty
<tr> <tr>
<td colspan="4" class="text-center text-muted">Belum ada data paket foto.</td> <td colspan="7" class="text-center text-muted">Belum ada data paket foto.</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>

View File

@ -100,8 +100,8 @@ class="text-center text-muted d-none">
sini</p> sini</p>
</div> </div>
<img id="editImgPreview{{ $f->id_paket }}" src="{{ asset($f->foto) }}" <img id="editImgPreview{{ $f->id_paket }}"
class="img-fluid w-100 h-100" src="{{ asset('storage/' . $f->foto) }}" class="img-fluid w-100 h-100"
style="object-fit: cover; position: absolute; top: 0; left: 0;"> style="object-fit: cover; position: absolute; top: 0; left: 0;">
</div> </div>
</div> </div>

View File

@ -12,8 +12,8 @@
<div class="col-12 col-sm-4"> <div class="col-12 col-sm-4">
@if ($f->foto) @if ($f->foto)
{{-- Langsung img tanpa wrapper --}} {{-- Langsung img tanpa wrapper --}}
<img src="{{ asset($f->foto) }}" class="custom-img-box-foto" <img src="{{ asset('storage/' . $f->foto) }}" class="custom-img-box-foto"
onclick="showImage('{{ asset($f->foto) }}')"> onclick="showImage('{{ asset('storage/' . $f->foto) }}')">
@else @else
{{-- Div pengganti kalau tidak ada foto --}} {{-- Div pengganti kalau tidak ada foto --}}
<div <div
@ -70,10 +70,13 @@ class="custom-img-box-foto d-flex align-items-center justify-content-center text
</div> </div>
</div> </div>
<div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true" style="z-index: 1060 !important;">
<div class="modal-dialog modal-dialog-centered modal-lg"> <div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content bg-transparent border-0 shadow-none"> <div class="modal-content bg-transparent border-0 shadow-none">
<div class="text-end mb-2">
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body p-0 text-center"> <div class="modal-body p-0 text-center">
<img id="img-preview-target" src="" class="img-fluid rounded shadow-lg" <img id="img-preview-target" src="" class="img-fluid rounded shadow-lg"
style="max-height: 85vh;"> style="max-height: 85vh;">

View File

@ -61,7 +61,7 @@
@include('admin.pesanan.partials.modal-buket') @include('admin.pesanan.partials.modal-buket')
@empty @empty
<tr> <tr>
<td colspan="4" class="text-center text-muted">Belum ada data pesanan buket.</td> <td colspan="8" class="text-center text-muted">Belum ada data pesanan buket.</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>

View File

@ -62,7 +62,7 @@
@include('admin.pesanan.partials.modal-foto') @include('admin.pesanan.partials.modal-foto')
@empty @empty
<tr> <tr>
<td colspan="4" class="text-center text-muted">Belum ada data pesanan foto.</td> <td colspan="8" class="text-center text-muted">Belum ada data pesanan foto.</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>

View File

@ -95,9 +95,9 @@ class="badge {{ $p->status_label->class }}">
<div class="proof-img-wrapper"> <div class="proof-img-wrapper">
@if ($p->bukti_bayar) @if ($p->bukti_bayar)
{{-- Klik hanya pada gambar --}} {{-- Klik hanya pada gambar --}}
<img src="{{ asset($p->bukti_bayar) }}" class="proof-img" <img src="{{ asset('storage/' . $p->bukti_bayar) }}" class="proof-img"
style="cursor: pointer;" style="cursor: pointer;"
onclick="showImage('{{ asset($p->bukti_bayar) }}')"> onclick="showImage('{{ asset('storage/' . $p->bukti_bayar) }}')">
@else @else
{{-- Div pengganti kalau tidak ada foto --}} {{-- Div pengganti kalau tidak ada foto --}}
<div class="custom-img-box d-flex align-items-center justify-content-center text-muted border rounded" <div class="custom-img-box d-flex align-items-center justify-content-center text-muted border rounded"
@ -130,7 +130,7 @@ class="badge {{ $p->status_label->class }}">
</div> </div>
{{-- MODAL GAMBAR --}} {{-- MODAL GAMBAR --}}
<div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true" style="z-index: 1060 !important;">
<div class="modal-dialog modal-dialog-centered modal-lg"> <div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content bg-transparent border-0 shadow-none"> <div class="modal-content bg-transparent border-0 shadow-none">
{{-- Tombol close putih agar terlihat di background gelap --}} {{-- Tombol close putih agar terlihat di background gelap --}}

View File

@ -90,9 +90,9 @@ class="badge {{ $p->status_label->class }}">
<div class="proof-img-wrapper"> <div class="proof-img-wrapper">
@if ($p->bukti_bayar) @if ($p->bukti_bayar)
{{-- Klik hanya pada gambar --}} {{-- Klik hanya pada gambar --}}
<img src="{{ asset($p->bukti_bayar) }}" class="proof-img" <img src="{{ asset('storage/' . $p->bukti_bayar) }}" class="proof-img"
style="cursor: pointer;" style="cursor: pointer;"
onclick="showImage('{{ asset($p->bukti_bayar) }}')"> onclick="showImageFoto('{{ asset('storage/' . $p->bukti_bayar) }}')">
@else @else
{{-- Div pengganti kalau tidak ada foto --}} {{-- Div pengganti kalau tidak ada foto --}}
<div class="custom-img-box d-flex align-items-center justify-content-center text-muted border rounded" <div class="custom-img-box d-flex align-items-center justify-content-center text-muted border rounded"
@ -125,7 +125,7 @@ class="badge {{ $p->status_label->class }}">
</div> </div>
{{-- MODAL GAMBAR --}} {{-- MODAL GAMBAR --}}
<div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="modalImagePreviewFoto" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg"> <div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content bg-transparent border-0 shadow-none"> <div class="modal-content bg-transparent border-0 shadow-none">
{{-- Tombol close putih agar terlihat di background gelap --}} {{-- Tombol close putih agar terlihat di background gelap --}}
@ -134,7 +134,7 @@ class="badge {{ $p->status_label->class }}">
aria-label="Close"></button> aria-label="Close"></button>
</div> </div>
<div class="modal-body p-0 text-center"> <div class="modal-body p-0 text-center">
<img id="img-preview-target" src="" class="img-fluid rounded shadow-lg" <img id="img-preview-target-foto" src="" class="img-fluid rounded shadow-lg"
style="max-height: 85vh; object-fit: contain;"> style="max-height: 85vh; object-fit: contain;">
</div> </div>
</div> </div>
@ -142,9 +142,9 @@ class="badge {{ $p->status_label->class }}">
</div> </div>
<script> <script>
function showImage(src) { function showImageFoto(src) {
const modalElement = document.getElementById('modalImagePreview'); const modalElement = document.getElementById('modalImagePreviewFoto');
const modalImg = document.getElementById('img-preview-target'); const modalImg = document.getElementById('img-preview-target-foto');
// 1. Set sumber gambar // 1. Set sumber gambar
modalImg.src = src; modalImg.src = src;

View File

@ -94,9 +94,9 @@ class="badge {{ $rb->status_label->class }}">
<div class="proof-img-wrapper"> <div class="proof-img-wrapper">
@if ($rb->bukti_bayar) @if ($rb->bukti_bayar)
{{-- Klik hanya pada gambar --}} {{-- Klik hanya pada gambar --}}
<img src="{{ asset($rb->bukti_bayar) }}" class="proof-img" <img src="{{ asset('storage/' . $rb->bukti_bayar) }}" class="proof-img"
style="cursor: pointer;" style="cursor: pointer;"
onclick="showImage('{{ asset($rb->bukti_bayar) }}')"> onclick="showImageBuket('{{ asset('storage/' . $rb->bukti_bayar) }}')">
@else @else
{{-- Div pengganti kalau tidak ada foto --}} {{-- Div pengganti kalau tidak ada foto --}}
<div class="custom-img-box d-flex align-items-center justify-content-center text-muted border rounded" <div class="custom-img-box d-flex align-items-center justify-content-center text-muted border rounded"
@ -110,13 +110,23 @@ class="badge {{ $rb->status_label->class }}">
</div> </div>
</div> </div>
<div class="modal-footer border-top-0 pt-2 px-2">
<div class="d-flex w-100 gap-2">
@if ($rb->status_transaksi == 'diterima')
<button type="button" class="btn btn-success flex-fill terima" {{-- Parameter: (this, 'selesai', ID, 'buket') --}}
onclick="prosesTanpaDialog(this, 'selesai', '{{ $rb->id_transaksi }}', 'buket')">
Selesaikan Pesanan
</button>
@endif
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{{-- MODAL GAMBAR --}} {{-- MODAL GAMBAR --}}
<div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="modalImagePreviewBuket" tabindex="-1" aria-hidden="true" style="z-index: 1060 !important;">
<div class="modal-dialog modal-dialog-centered modal-lg"> <div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content bg-transparent border-0 shadow-none"> <div class="modal-content bg-transparent border-0 shadow-none">
{{-- Tombol close putih agar terlihat di background gelap --}} {{-- Tombol close putih agar terlihat di background gelap --}}
@ -125,7 +135,7 @@ class="badge {{ $rb->status_label->class }}">
aria-label="Close"></button> aria-label="Close"></button>
</div> </div>
<div class="modal-body p-0 text-center"> <div class="modal-body p-0 text-center">
<img id="img-preview-target" src="" class="img-fluid rounded shadow-lg" <img id="img-preview-target-buket" src="" class="img-fluid rounded shadow-lg"
style="max-height: 85vh; object-fit: contain;"> style="max-height: 85vh; object-fit: contain;">
</div> </div>
</div> </div>
@ -133,9 +143,9 @@ class="badge {{ $rb->status_label->class }}">
</div> </div>
<script> <script>
function showImage(src) { function showImageBuket(src) {
const modalElement = document.getElementById('modalImagePreview'); const modalElement = document.getElementById('modalImagePreviewBuket');
const modalImg = document.getElementById('img-preview-target'); const modalImg = document.getElementById('img-preview-target-buket');
// 1. Set sumber gambar // 1. Set sumber gambar
modalImg.src = src; modalImg.src = src;
@ -145,3 +155,44 @@ function showImage(src) {
myModal.show(); myModal.show();
} }
</script> </script>
<script>
// Tambahkan parameter ke-4: 'kategori'
function prosesTanpaDialog(btn, jenis, id, kategori) {
// 1. Efek Loading
const originalText = btn.innerHTML;
btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span>';
btn.disabled = true;
// 2. Fetch
fetch(`{{ url('/admin/riwayat-pesanan/update-status') }}/${id}`, {
method: 'PUT',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
// Kirim 'jenis' DAN 'kategori'
body: JSON.stringify({
jenis: jenis,
kategori: kategori
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert("Gagal: " + (data.message || "Terjadi kesalahan"));
btn.innerHTML = originalText;
btn.disabled = false;
}
})
.catch(error => {
console.error(error);
alert("Error sistem.");
btn.innerHTML = originalText;
btn.disabled = false;
});
}
</script>

View File

@ -93,9 +93,9 @@ class="badge {{ $rf->status_label->class }}">
<div class="proof-img-wrapper"> <div class="proof-img-wrapper">
@if ($rf->bukti_bayar) @if ($rf->bukti_bayar)
{{-- Klik hanya pada gambar --}} {{-- Klik hanya pada gambar --}}
<img src="{{ asset($rf->bukti_bayar) }}" class="proof-img" <img src="{{ asset('storage/' . $rf->bukti_bayar) }}" class="proof-img"
style="cursor: pointer;" style="cursor: pointer;"
onclick="showImage('{{ asset($rf->bukti_bayar) }}')"> onclick="showImageFoto('{{ asset('storage/' . $rf->bukti_bayar) }}')">
@else @else
{{-- Div pengganti kalau tidak ada foto --}} {{-- Div pengganti kalau tidak ada foto --}}
<div class="custom-img-box d-flex align-items-center justify-content-center text-muted border rounded" <div class="custom-img-box d-flex align-items-center justify-content-center text-muted border rounded"
@ -109,13 +109,23 @@ class="badge {{ $rf->status_label->class }}">
</div> </div>
</div> </div>
<div class="modal-footer border-top-0 pt-2 px-2">
<div class="d-flex w-100 gap-2">
@if ($rf->status_booking == 'diterima')
<button type="button" class="btn btn-success flex-fill terima" {{-- Parameter: (this, 'selesai', ID, 'foto') --}}
onclick="prosesTanpaDialog(this, 'selesai', '{{ $rf->id_booking }}', 'foto')">
Selesaikan Pesanan
</button>
@endif
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{{-- MODAL GAMBAR --}} {{-- MODAL GAMBAR --}}
<div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="modalImagePreviewFoto" tabindex="-1" aria-hidden="true" style="z-index: 1060 !important;">
<div class="modal-dialog modal-dialog-centered modal-lg"> <div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content bg-transparent border-0 shadow-none"> <div class="modal-content bg-transparent border-0 shadow-none">
{{-- Tombol close putih agar terlihat di background gelap --}} {{-- Tombol close putih agar terlihat di background gelap --}}
@ -124,7 +134,7 @@ class="badge {{ $rf->status_label->class }}">
aria-label="Close"></button> aria-label="Close"></button>
</div> </div>
<div class="modal-body p-0 text-center"> <div class="modal-body p-0 text-center">
<img id="img-preview-target" src="" class="img-fluid rounded shadow-lg" <img id="img-preview-target-foto" src="" class="img-fluid rounded shadow-lg"
style="max-height: 85vh; object-fit: contain;"> style="max-height: 85vh; object-fit: contain;">
</div> </div>
</div> </div>
@ -132,9 +142,9 @@ class="badge {{ $rf->status_label->class }}">
</div> </div>
<script> <script>
function showImage(src) { function showImageFoto(src) {
const modalElement = document.getElementById('modalImagePreview'); const modalElement = document.getElementById('modalImagePreviewFoto');
const modalImg = document.getElementById('img-preview-target'); const modalImg = document.getElementById('img-preview-target-foto');
// 1. Set sumber gambar // 1. Set sumber gambar
modalImg.src = src; modalImg.src = src;
@ -144,3 +154,44 @@ function showImage(src) {
myModal.show(); myModal.show();
} }
</script> </script>
<script>
// Tambahkan parameter ke-4: 'kategori'
function prosesTanpaDialog(btn, jenis, id, kategori) {
// 1. Efek Loading
const originalText = btn.innerHTML;
btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span>';
btn.disabled = true;
// 2. Fetch
fetch(`{{ url('/admin/riwayat-pesanan/update-status') }}/${id}`, {
method: 'PUT',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
// Kirim 'jenis' DAN 'kategori'
body: JSON.stringify({
jenis: jenis,
kategori: kategori
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert("Gagal: " + (data.message || "Terjadi kesalahan"));
btn.innerHTML = originalText;
btn.disabled = false;
}
})
.catch(error => {
console.error(error);
alert("Error sistem.");
btn.innerHTML = originalText;
btn.disabled = false;
});
}
</script>

View File

@ -3,13 +3,28 @@
@section('title', 'Riwayat Pesanan') @section('title', 'Riwayat Pesanan')
@section('content') @section('content')
{{-- ALERT SUKSES --}}
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
{{-- ALERT ERROR UMUM (Jika ada error selain validasi modal) --}}
@if (session('error'))
<div class="alert alert-danger alert-dismissible fade show" role="alert">
{{ session('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
<section class="section"> <section class="section">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<div class="nav nav-pills nav-fill mb-4" id="v-pills-tab" role="tablist" aria-orientation="horizontal"> <div class="nav nav-pills nav-fill mb-4" id="v-pills-tab" role="tablist" aria-orientation="horizontal">
<a class="nav-link active" id="v-pills-home-tab" data-bs-toggle="pill" href="#v-pills-home" role="tab" <a class="nav-link active" id="v-pills-home-tab" data-bs-toggle="pill" href="#v-pills-home"
aria-controls="v-pills-home" aria-selected="true"> role="tab" aria-controls="v-pills-home" aria-selected="true">
Buket Buket
</a> </a>
<a class="nav-link" id="v-pills-profile-tab" data-bs-toggle="pill" href="#v-pills-profile" <a class="nav-link" id="v-pills-profile-tab" data-bs-toggle="pill" href="#v-pills-profile"
@ -57,7 +72,7 @@
@include('admin.pesanan.partials.modal-riwayat-buket') @include('admin.pesanan.partials.modal-riwayat-buket')
@empty @empty
<tr> <tr>
<td colspan="4" class="text-center text-muted">Belum ada data riwayat pesanan <td colspan="8" class="text-center text-muted">Belum ada data riwayat pesanan
buket. buket.
</td> </td>
</tr> </tr>
@ -102,7 +117,7 @@
@include('admin.pesanan.partials.modal-riwayat-foto') @include('admin.pesanan.partials.modal-riwayat-foto')
@empty @empty
<tr> <tr>
<td colspan="4" class="text-center text-muted">Belum ada data riwayat pesanan <td colspan="8" class="text-center text-muted">Belum ada data riwayat pesanan
foto.</td> foto.</td>
</tr> </tr>
@endforelse @endforelse

View File

@ -46,7 +46,7 @@
<td style="width: 35%">{{ Str::limit($b->deskripsi, 50) }}</td> <td style="width: 35%">{{ Str::limit($b->deskripsi, 50) }}</td>
<td style="width: 15%">Rp {{ number_format($b->harga, 0, ',', '.') }}</td> <td style="width: 15%">Rp {{ number_format($b->harga, 0, ',', '.') }}</td>
<td style="width:10%"> <td style="width:10%">
<img src="{{ asset($b->foto) }}" alt="Foto Produk" class="rounded" <img src="{{ asset('storage/' . $b->foto) }}" alt="Foto Produk" class="rounded"
style="width: 50px; height: 50px; object-fit: cover;"> style="width: 50px; height: 50px; object-fit: cover;">
</td> </td>
<td class="col-auto text-center" style="width: 15%"> <td class="col-auto text-center" style="width: 15%">
@ -71,7 +71,7 @@
@include('admin.produk-buket.partials.modal-delete') @include('admin.produk-buket.partials.modal-delete')
@empty @empty
<tr> <tr>
<td colspan="4" class="text-center text-muted">Tidak ada data buket.</td> <td colspan="6" class="text-center text-muted">Tidak ada data buket.</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>

View File

@ -123,8 +123,9 @@ class="form-control @error('nama') is-invalid @enderror" style="font-size: 14px;
<p class="mb-0" style="font-size: 12px;">Belum ada foto</p> <p class="mb-0" style="font-size: 12px;">Belum ada foto</p>
</div> </div>
<img id="editImgPreview{{ $b->id_buket }}" src="{{ asset($b->foto) }}" <img id="editImgPreview{{ $b->id_buket }}"
class="w-100 h-100" style="object-fit: contain;"> src="{{ asset('storage/' . $b->foto) }}" class="w-100 h-100"
style="object-fit: contain;">
</div> </div>
</div> </div>
</div> </div>

View File

@ -12,8 +12,8 @@
<div class="col-12 col-sm-4"> <div class="col-12 col-sm-4">
@if ($b->foto) @if ($b->foto)
{{-- Langsung img tanpa wrapper --}} {{-- Langsung img tanpa wrapper --}}
<img src="{{ asset($b->foto) }}" class="custom-img-box" <img src="{{ asset('storage/' . $b->foto) }}" class="custom-img-box"
onclick="showImage('{{ asset($b->foto) }}')"> onclick="showImage('{{ asset('storage/' . $b->foto) }}')">
@else @else
{{-- Div pengganti kalau tidak ada foto --}} {{-- Div pengganti kalau tidak ada foto --}}
<div class="custom-img-box d-flex align-items-center justify-content-center text-muted"> <div class="custom-img-box d-flex align-items-center justify-content-center text-muted">
@ -83,10 +83,13 @@ class="badge bg-success-subtle rounded-pill px-3 py-2 text-success">{{ $b->kateg
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="modalImagePreview" tabindex="-1" aria-hidden="true" style="z-index: 1060 !important;">
<div class="modal-dialog modal-dialog-centered modal-lg"> <div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content bg-transparent border-0 shadow-none"> <div class="modal-content bg-transparent border-0 shadow-none">
<div class="text-end mb-2">
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body p-0 text-center"> <div class="modal-body p-0 text-center">
<img id="img-preview-target" src="" class="img-fluid rounded shadow-lg" <img id="img-preview-target" src="" class="img-fluid rounded shadow-lg"
style="max-height: 85vh;"> style="max-height: 85vh;">

View File

@ -95,8 +95,8 @@ class="form-control @error('email', 'updateProfil') is-invalid @enderror"
<div class="mb-2"> <div class="mb-2">
<label class="form-label">Peran</label> <label class="form-label">Peran</label>
<input type="text" class="form-control bg-light" <input type="text" class="form-control bg-light"
value="{{ ucfirst($user->role ?? 'Admin') }}" style="font-size: 14px;" value="{{ ucwords(str_replace('_', ' ', $user->role ?? 'Admin')) }}"
readonly> style="font-size: 14px;" readonly>
</div> </div>
</div> </div>
</div> </div>

View File

@ -20,7 +20,7 @@
<div class="col"> <div class="col">
<div class="bookingfoto-card position-relative"> <div class="bookingfoto-card position-relative">
<div class="img-wrapper mb-3"> <div class="img-wrapper mb-3">
<img src="{{ asset($f->foto) }}" class="img-fluid rounded-4" <img src="{{ asset('storage/' . $f->foto) }}" class="img-fluid rounded-4"
alt="{{ $f->nama }}"> alt="{{ $f->nama }}">
</div> </div>
<div class="text-left"> <div class="text-left">

View File

@ -4,7 +4,7 @@
<div class="col-6 col-md-4 col-lg-3"> <div class="col-6 col-md-4 col-lg-3">
<div class="katalogbuket-card h-100 position-relative"> <div class="katalogbuket-card h-100 position-relative">
<div class="img-wrapper mb-3"> <div class="img-wrapper mb-3">
<img src="{{ asset($b->foto) }}" class="img-fluid rounded-4" alt="{{ $b->nama }}"> <img src="{{ asset('storage/' . $b->foto) }}" class="img-fluid rounded-4" alt="{{ $b->nama }}">
</div> </div>
<h6 class="katalogbuket-product-title">{{ $b->nama }}</h6> <h6 class="katalogbuket-product-title">{{ $b->nama }}</h6>
<p class="katalogbuket-product-price">Rp {{ number_format($b->harga, 0, ',', '.') }}</p> <p class="katalogbuket-product-price">Rp {{ number_format($b->harga, 0, ',', '.') }}</p>

View File

@ -18,7 +18,7 @@
<div class="col-lg-5 mb-5 mb-lg-0"> <div class="col-lg-5 mb-5 mb-lg-0">
<div class="detailbuket-img-frame"> <div class="detailbuket-img-frame">
<img src="{{ asset($buket->foto) }}" class="img-fluid" alt="{{ $buket->nama }}"> <img src="{{ asset('storage/' . $buket->foto) }}" class="img-fluid" alt="{{ $buket->nama }}">
</div> </div>
</div> </div>
@ -80,7 +80,7 @@ class="btn btn-detailbuket-primary flex-fill">
'* seharga Rp ' . '* seharga Rp ' .
number_format($buket->harga, 0, ',', '.') . number_format($buket->harga, 0, ',', '.') .
'. Bisa diskusi sedikit soal detail dan custom-nya?'; '. Bisa diskusi sedikit soal detail dan custom-nya?';
$waLink = 'https://wa.me/6289673668516?text=' . urlencode($waText); $waLink = 'https://wa.me/6282337687878?text=' . urlencode($waText);
@endphp @endphp
<a href="{{ $waLink }}" target="_blank" class="btn btn-detailbuket-secondary flex-fill"> <a href="{{ $waLink }}" target="_blank" class="btn btn-detailbuket-secondary flex-fill">
Diskusikan di WA Diskusikan di WA

View File

@ -28,7 +28,7 @@
<div class="row gx-3"> <div class="row gx-3">
<div class="col-auto"> <div class="col-auto">
<div class="detailfoto-card p-2"> <div class="detailfoto-card p-2">
<img src="{{ asset($foto->foto) }}" alt="{{ $foto->nama }}" <img src="{{ asset('storage/' . $foto->foto) }}" alt="{{ $foto->nama }}"
class="detailfoto-thumb rounded-4"> class="detailfoto-thumb rounded-4">
</div> </div>
</div> </div>

View File

@ -22,7 +22,8 @@
<h4 class="formulirbuket-section-title mb-3">Rincian Pesanan</h4> <h4 class="formulirbuket-section-title mb-3">Rincian Pesanan</h4>
<div class="formulirbuket-card d-flex flex-column gap-2"> <div class="formulirbuket-card d-flex flex-column gap-2">
<div class="formulirbuket-product-summary d-flex align-items-center gap-3"> <div class="formulirbuket-product-summary d-flex align-items-center gap-3">
<img src="{{ asset($buket->foto) }}" alt="{{ $buket->nama }}" class="rounded-3"> <img src="{{ asset('storage/' . $buket->foto) }}" alt="{{ $buket->nama }}"
class="rounded-3">
<div> <div>
<h6 class=" mb-1">{{ $buket->nama }}</h6> <h6 class=" mb-1">{{ $buket->nama }}</h6>
<p class="text-teal mb-0">Rp {{ number_format($buket->harga, 0, ',', '.') }}</p> <p class="text-teal mb-0">Rp {{ number_format($buket->harga, 0, ',', '.') }}</p>

View File

@ -201,8 +201,6 @@ class="position-absolute w-100 h-100 opacity-0 start-0 top-0 cursor-pointer @err
<div class="d-flex gap-3"> <div class="d-flex gap-3">
<a href="{{ route('booking.cancel') }}" <a href="{{ route('booking.cancel') }}"
class="btn formulirfoto-btn-cancel flex-fill">Batalkan</a> class="btn formulirfoto-btn-cancel flex-fill">Batalkan</a>
{{-- <a href="{{ route('detail.foto', $foto->id_paket) }}"
class="btn formulirfoto-btn-cancel flex-fill">Batalkan</a> --}}
<button type="submit" class="btn formulirfoto-btn-submit flex-fill">Kirim <button type="submit" class="btn formulirfoto-btn-submit flex-fill">Kirim
Pesanan</button> Pesanan</button>
</div> </div>

View File

@ -3,8 +3,6 @@
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Admin as Admin; use App\Http\Controllers\Admin as Admin;
use App\Http\Controllers\User as User; use App\Http\Controllers\User as User;
use App\Http\Controllers\AuthController; // Asumsi controller login dipisah atau di Admin
use App\Http\Controllers\User\TestBookingController;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -31,10 +29,6 @@
Route::post('/simpan-booking-foto', [User\BookingFotoController::class, 'store'])->name('transaksi.foto.store'); Route::post('/simpan-booking-foto', [User\BookingFotoController::class, 'store'])->name('transaksi.foto.store');
Route::get('/cancel-booking', [User\BookingFotoController::class, 'cancelBooking'])->name('booking.cancel'); Route::get('/cancel-booking', [User\BookingFotoController::class, 'cancelBooking'])->name('booking.cancel');
Route::get('/test-flow', [User\TestBookingController::class, 'index']);
Route::get('/cek-slot-foto', [User\TestBookingController::class, 'cekSlot']);
Route::post('/test-flow-simpan', [User\TestBookingController::class, 'store'])->name('test.simpan.foto');
}); });
/* /*
@ -78,6 +72,8 @@
->name('pesanan-foto.update-status'); ->name('pesanan-foto.update-status');
Route::get('/riwayat-pesanan', [Admin\HistoriPesananController::class, 'index'])->name('riwayat'); Route::get('/riwayat-pesanan', [Admin\HistoriPesananController::class, 'index'])->name('riwayat');
Route::put('/riwayat-pesanan/update-status/{id}', [Admin\HistoriPesananController::class, 'updateStatus'])
->name('riwayat-pesanan.update-status');
// Manajemen Produk (Master Data) // Manajemen Produk (Master Data)
Route::resource('produk-buket', Admin\BuketController::class); // Perbaiki namespace jika perlu Route::resource('produk-buket', Admin\BuketController::class); // Perbaiki namespace jika perlu
@ -88,7 +84,7 @@
Route::resource('kelola-admin', Admin\ManajemenAdminController::class); Route::resource('kelola-admin', Admin\ManajemenAdminController::class);
// Profil Diri // Profil Diri
Route::resource('profil', Admin\ProfilController::class); Route::get('/profil', [Admin\ProfilController::class, 'index'])->name('profil.index');
Route::put('/profil/update', [Admin\ProfilController::class, 'update'])->name('profil.simpan'); Route::put('/profil/update', [Admin\ProfilController::class, 'update'])->name('profil.simpan');
Route::put('/profil/password', [Admin\ProfilController::class, 'updatePassword'])->name('profil.password'); Route::put('/profil/password', [Admin\ProfilController::class, 'updatePassword'])->name('profil.password');