From ec1bddbf4e8fc3cd8d902c3d8a1bd60f2457b30f Mon Sep 17 00:00:00 2001 From: mirsydfchrynto Date: Wed, 6 Aug 2025 20:21:14 +0700 Subject: [PATCH] revisi --- .../Admin/AdminBookingController.php | 122 +++++----- app/Models/Booking.php | 5 + ...025_08_01_174811_create_bookings_table.php | 2 +- ..._add_payment_columns_to_bookings_table.php | 29 +++ .../views/admin/bookings/index.blade.php | 81 ++++--- resources/views/admin/bookings/show.blade.php | 221 ++++++++++++------ routes/web.php | 11 +- 7 files changed, 311 insertions(+), 160 deletions(-) create mode 100644 database/migrations/2025_08_06_085405_add_payment_columns_to_bookings_table.php diff --git a/app/Http/Controllers/Admin/AdminBookingController.php b/app/Http/Controllers/Admin/AdminBookingController.php index 1121bdf..321626b 100644 --- a/app/Http/Controllers/Admin/AdminBookingController.php +++ b/app/Http/Controllers/Admin/AdminBookingController.php @@ -1,100 +1,118 @@ paginate(15); - return view('admin.bookings.index', compact('bookings')); } /** - * Show the form for creating a new resource. + * Tampilkan detail pesanan. */ - public function create() + public function show(string $id) { - // + $booking = Booking::findOrFail($id); + return view('admin.bookings.show', compact('booking')); } /** - * Store a newly created resource in storage. + * Konfirmasi pembayaran DP dan arahkan ke WhatsApp. */ - public function store(Request $request) + public function confirmDp(Request $request, $id) { - // - } + $booking = Booking::findOrFail($id); - /** - * Display the specified resource. - */ - public function show(string $id) - { - $booking = Booking::findOrFail($id); // Cari booking secara manual + $request->validate([ + 'dp_amount' => 'required|numeric|min:0', + 'dp_proof' => 'required|image|max:2048', + ]); - return view('admin.bookings.show', compact('booking')); - } + $path = $request->file('dp_proof')->store('bukti_dp', 'public'); - /** - * Show the form for editing the specified resource. - */ - public function edit(string $id) - { - // + $booking->update([ + 'dp_amount' => $request->dp_amount, + 'dp_proof' => $path, + 'status' => 'booked', + ]); + + // Pesan sukses + session()->flash('success', 'DP berhasil dikonfirmasi. Silakan kirim pesan ke pelanggan.'); + + // Pesan WhatsApp + $message = "Halo kak {$booking->contact_name},\n\n" + . "Terima kasih, DP kamu untuk sesi {$booking->session_name} pada tanggal " + . Carbon::parse($booking->booking_date)->format('d F Y') . " pukul {$booking->booking_time} telah kami terima.\n" + . "Pesananmu sudah dikonfirmasi. Sampai jumpa di hari H!"; + + $whatsappNumber = preg_replace('/[^0-9]/', '', $booking->whatsapp_number); + $url = 'https://wa.me/' . $whatsappNumber . '?text=' . urlencode($message); + + return redirect()->away($url); } /** - * Update the specified resource in storage. + * Selesaikan pesanan (pelunasan) dan arahkan ke WhatsApp. */ - public function update(Request $request, $id) + public function completeBooking(Request $request, $id) { $booking = Booking::findOrFail($id); - $validatedData = $request->validate([ - 'status' => ['required', Rule::in(['pending', 'confirmed', 'completed', 'cancelled'])], + $request->validate([ + 'final_payment_amount' => 'required|numeric|min:0', + 'final_payment_proof' => 'required|image|max:2048', ]); - $booking->status = $validatedData['status']; - $booking->save(); - - // Cek apakah status yang baru adalah 'confirmed' - if ($booking->status === 'confirmed') { - // Jika iya, siapkan pesan WhatsApp - $message = "Halo kak " . $booking->contact_name . ",\n\n" - . "Pesanan kamu untuk sesi " . $booking->session_name . " pada tanggal " - . Carbon::parse($booking->booking_date)->format('d F Y') - . " jam " . $booking->booking_time . " sudah berhasil dikonfirmasi.\n\n" - . "Terima kasih sudah memesan di tempat kami!"; - - $whatsappUrl = 'https://wa.me/' . $booking->whatsapp_number . '?text=' . urlencode($message); - - // Redirect ke URL WhatsApp - return redirect()->away($whatsappUrl); - } + $path = $request->file('final_payment_proof')->store('bukti_pelunasan', 'public'); - // Jika status bukan 'confirmed', redirect kembali ke halaman sebelumnya - return redirect()->back()->with('success', 'Status pesanan berhasil diperbarui.'); - } + $booking->update([ + 'final_payment_amount' => $request->final_payment_amount, + 'final_payment_proof' => $path, + 'status' => 'completed', + ]); + // Pesan sukses + session()->flash('success', 'Pelunasan berhasil dikonfirmasi. Silakan kirim konfirmasi ke pelanggan.'); + + // Pesan WhatsApp + $message = "Halo kak {$booking->contact_name},\n\n" + . "Kami telah menerima pelunasan untuk sesi {$booking->session_name} pada tanggal " + . Carbon::parse($booking->booking_date)->format('d F Y') . ".\n" + . "Terima kasih telah mempercayakan layanan kami. See you next time!"; + + $whatsappNumber = preg_replace('/[^0-9]/', '', $booking->whatsapp_number); + $url = 'https://wa.me/' . $whatsappNumber . '?text=' . urlencode($message); + + return redirect()->away($url); + } /** - * Remove the specified resource from storage. + * Hapus pesanan dan hapus file bukti pembayaran. */ - public function destroy(Booking $booking) + public function destroy(Booking $booking) { + // Hapus file bukti jika ada + if ($booking->dp_proof) { + Storage::disk('public')->delete($booking->dp_proof); + } + if ($booking->final_payment_proof) { + Storage::disk('public')->delete($booking->final_payment_proof); + } + $booking->delete(); return redirect()->route('bookings.index')->with('success', 'Pesanan berhasil dihapus.'); } -} +} \ No newline at end of file diff --git a/app/Models/Booking.php b/app/Models/Booking.php index 2e746d4..eb4cb56 100644 --- a/app/Models/Booking.php +++ b/app/Models/Booking.php @@ -18,8 +18,13 @@ class Booking extends Model 'total_price', 'notes', 'status', + 'dp_amount', + 'dp_proof', + 'final_payment_amount', + 'final_payment_proof', ]; + protected $casts = [ 'booking_date' => 'date', 'selected_backgrounds' => 'array', diff --git a/database/migrations/2025_08_01_174811_create_bookings_table.php b/database/migrations/2025_08_01_174811_create_bookings_table.php index c8f519f..9579d9d 100644 --- a/database/migrations/2025_08_01_174811_create_bookings_table.php +++ b/database/migrations/2025_08_01_174811_create_bookings_table.php @@ -23,7 +23,7 @@ public function up(): void $table->json('selected_extra_items'); // Simpan sebagai JSON $table->integer('total_price'); $table->text('notes')->nullable(); - $table->enum('status', ['pending', 'confirmed', 'completed', 'cancelled'])->default('pending'); + $table->enum('status', ['waiting', 'booked', 'completed', 'cancelled'])->default('waiting'); $table->timestamps(); }); } diff --git a/database/migrations/2025_08_06_085405_add_payment_columns_to_bookings_table.php b/database/migrations/2025_08_06_085405_add_payment_columns_to_bookings_table.php new file mode 100644 index 0000000..367fd0e --- /dev/null +++ b/database/migrations/2025_08_06_085405_add_payment_columns_to_bookings_table.php @@ -0,0 +1,29 @@ +integer('dp_amount')->nullable()->after('notes'); + $table->string('dp_proof')->nullable()->after('dp_amount'); + $table->integer('final_payment_amount')->nullable()->after('dp_proof'); + $table->string('final_payment_proof')->nullable()->after('final_payment_amount'); + }); + } + + public function down(): void + { + Schema::table('bookings', function (Blueprint $table) { + $table->dropColumn([ + 'dp_amount', + 'dp_proof', + 'final_payment_amount', + 'final_payment_proof', + ]); + }); + } +}; diff --git a/resources/views/admin/bookings/index.blade.php b/resources/views/admin/bookings/index.blade.php index 83fe604..bdf16c2 100644 --- a/resources/views/admin/bookings/index.blade.php +++ b/resources/views/admin/bookings/index.blade.php @@ -1,15 +1,18 @@ - +
+

Manajemen Pesanan

+ @if (session('success')) - + @endif +
@@ -25,42 +28,54 @@ @forelse ($bookings as $booking) - - - - - - - - + + + + + + + + @empty - - - + + + @endforelse
{{ $booking->id }}{{ $booking->contact_name }}{{ $booking->package_name }} - {{ \Carbon\Carbon::parse($booking->booking_date)->format('d M Y') }} -
- {{ $booking->booking_time }} -
- @php - $badgeColor = [ - 'pending' => 'bg-yellow-100 text-yellow-800', - 'confirmed' => 'bg-green-100 text-green-800', - 'completed' => 'bg-blue-100 text-blue-800', - 'cancelled' => 'bg-red-100 text-red-800' - ][$booking->status] ?? 'bg-gray-100 text-gray-800'; - @endphp - - {{ ucfirst($booking->status) }} - - - Lihat Detail -
+ #{{ $booking->id }} + + {{ $booking->contact_name }} + + {{ $booking->package_name }} + + {{ \Carbon\Carbon::parse($booking->booking_date)->translatedFormat('d F Y') }} +
+ {{ $booking->booking_time }} +
+ @php + $badgeColor = match ($booking->status) { + 'waiting' => 'bg-yellow-100 text-yellow-800 border-yellow-200', + 'booked' => 'bg-green-100 text-green-800 border-green-200', + 'completed' => 'bg-blue-100 text-blue-800 border-blue-200', + default => 'bg-gray-100 text-gray-800 border-gray-200' + }; + @endphp + + {{ ucfirst($booking->status === 'waiting' ? 'Menunggu DP' : ($booking->status === 'booked' ? 'Sudah Dibooking' : 'Selesai')) }} + + + + Lihat Detail + +
Tidak ada pesanan saat ini.
+ Tidak ada pesanan saat ini. +
+
{{ $bookings->links('pagination::tailwind') }}
diff --git a/resources/views/admin/bookings/show.blade.php b/resources/views/admin/bookings/show.blade.php index a0a6f81..f166ab8 100644 --- a/resources/views/admin/bookings/show.blade.php +++ b/resources/views/admin/bookings/show.blade.php @@ -1,101 +1,182 @@ - +
+

Detail Pesanan #{{ $booking->id }}

- Kembali + Kembali
+ @if (session('success')) - +
+ {{ session('success') }} +
@endif -
-
-
-
-

Informasi Pesanan

-
-
-

Nama Kontak: {{ $booking->contact_name }}

-

Nomor WhatsApp: {{ $booking->whatsapp_number }}

-

Tanggal: {{ \Carbon\Carbon::parse($booking->booking_date)->format('d F Y') }}

-

Waktu: {{ $booking->booking_time }}

-

Jenis Sesi: {{ $booking->session_name }}

-

Paket: {{ $booking->package_name }}

-

Total Harga: Rp.{{ number_format($booking->total_price, 0, ',', '.') }}

-

Catatan Tambahan: {{ $booking->notes ?? '-' }}

+ +
+ +
+ +
+

Informasi Pesanan

+
+

Nama: {{ $booking->contact_name }}

+

WhatsApp: {{ $booking->whatsapp_number }}

+

Tanggal: {{ \Carbon\Carbon::parse($booking->booking_date)->translatedFormat('d F Y') }}

+

Jam: {{ $booking->booking_time }}

+

Sesi: {{ $booking->session_name }}

+

Paket: {{ $booking->package_name }}

+

Total: Rp{{ number_format($booking->total_price, 0, ',', '.') }}

+

Catatan: {{ $booking->notes ?? '-' }}

- -
-
-

Pilihan Pengguna

-
-
- @if (!empty($booking->selected_backgrounds)) -

Background yang dipilih:

-
    + +
    +

    Tambahan & Background

    + @if ($booking->selected_backgrounds) +

    Background:

    +
      @foreach ($booking->selected_backgrounds as $bg) -
    • {{ $bg['name'] }}
    • +
    • {{ $bg['name'] }}
    • @endforeach
    - @else - - @endif -
    Extra Items:
    - @if ($booking->selected_extra_items) -
      + @endif + @if ($booking->selected_extra_items) +

      Extra Item:

      +
        @foreach ($booking->selected_extra_items as $extra) -
      • {{ $extra['name'] }} (Rp.{{ number_format($extra['price'], 0, ',', '.') }})
      • +
      • {{ $extra['name'] }} (Rp{{ number_format($extra['price'], 0, ',', '.') }})
      • @endforeach
      - @else + @else

      Tidak ada extra item.

      - @endif -
    + @endif
-
-
-
-

Perbarui Status

+ +
+ +
+

Tindakan Cepat

+ +

Klik untuk memperbarui status terbaru

+
+ + +
+

Status Pesanan

+ @php + $badge = match ($booking->status) { + 'waiting' => 'bg-yellow-200 text-yellow-800', + 'booked' => 'bg-green-200 text-green-800', + 'completed' => 'bg-blue-200 text-blue-800', + default => 'bg-gray-200 text-gray-800' + }; + @endphp + + {{ ucfirst($booking->status === 'waiting' ? 'Menunggu DP' : ($booking->status === 'booked' ? 'Sudah Dibooking' : 'Selesai')) }} + +
+ + + @if ($booking->status === 'waiting') + @php + $dpAmount = number_format($booking->total_price / 2, 0, ',', '.'); + $message = "Halo kak {$booking->contact_name}, pesananmu untuk tanggal {$booking->booking_date->format('d M Y')} jam {$booking->booking_time} telah kami terima. Mohon transfer DP Rp{$dpAmount} untuk mengamankan jadwal. Balas dengan bukti transfer ya. Terima kasih."; + $whatsappLink = "https://wa.me/" . preg_replace('/[^0-9]/', '', $booking->whatsapp_number) . "?text=" . urlencode($message); + @endphp + -
-
+ @endif + + + @if ($booking->status === 'waiting') +
+

Konfirmasi DP

+ @csrf - @method('PUT')
- - + + +
+
+ +
- + -
-
+
+ @endif + + + @if ($booking->status === 'booked') +
+

DP Telah Diterima

+

Nominal: Rp{{ number_format($booking->dp_amount, 0, ',', '.') }}

+

Bukti Transfer:

+ +
+ @endif + + + @if ($booking->status === 'booked') +
+

Pelunasan

+ @csrf - @method('DELETE') - +
+ + +
+
+ + +
+
+ @endif + + + @if ($booking->status === 'completed') +
+

Laporan Pembayaran

+

Nominal DP: Rp{{ number_format($booking->dp_amount, 0, ',', '.') }}

+

Nominal Pelunasan: Rp{{ number_format($booking->final_payment_amount, 0, ',', '.') }}

+
+

Bukti DP:

+ +

Bukti Pelunasan:

+ +
+
+ @endif + + +
+
+ @csrf + @method('DELETE') + +
diff --git a/routes/web.php b/routes/web.php index dab3fc0..5c39dab 100644 --- a/routes/web.php +++ b/routes/web.php @@ -13,8 +13,8 @@ use Livewire\Volt\Volt; // Homepage -Route::get('/', fn () => view('welcome'))->name('home'); -Route::get('/homepage', fn () => view('homepage'))->name('homepage'); +Route::get('/', fn() => view('welcome'))->name('home'); +Route::get('/homepage', fn() => view('homepage'))->name('homepage'); // Kategori: Prewedding Route::get('/kategori/prewed', function () { @@ -48,7 +48,7 @@ })->name('kategori.baby'); // Info & Sosial Media -Route::get('/info-more', fn () => view('info'))->name('info'); +Route::get('/info-more', fn() => view('info'))->name('info'); // Booking Store Route::post('/booking', [BookingController::class, 'store']); @@ -59,10 +59,13 @@ Route::resource('backgrounds', BackgroundController::class); Route::resource('bookings', AdminBookingController::class)->except(['create', 'store', 'edit']); + Route::post('/bookings/{id}/confirm-dp', [AdminBookingController::class, 'confirmDp'])->name('bookings.confirmDp'); + Route::post('/bookings/{id}/complete-booking', [AdminBookingController::class, 'completeBooking'])->name('bookings.completeBooking'); Route::resource('extra-items', ExtraItemsController::class); Route::resource('terms', TermsAndConditionController::class); }); + // Settings via Volt Route::middleware(['auth'])->group(function () { Route::redirect('settings', 'settings/profile'); @@ -73,4 +76,4 @@ }); // Auth Routes (Login, Logout, Register) — note: register dapat dimatikan di file auth.php -require __DIR__.'/auth.php'; +require __DIR__ . '/auth.php';