'handlePaymentSuccess' ]; public function openCart() { $this->showCart = true; } public function closeCart() { $this->showCart = false; } // --- DIHAPUS: getGroupedFoodItemsProperty tidak lagi relevan dengan type_item_id // --- UBAH: Sesuaikan nama properti untuk filter public function getFilteredFoodItemsProperty() { // --- UBAH: Menggunakan model Items $query = Items::query(); if ($this->typeItemId) { // --- UBAH: Menggunakan $this->typeItemId $query->where('type_item_id', $this->typeItemId); } // --- UBAH: Tambahkan kondisi is_available agar hanya menampilkan yang tersedia $query->where('is_available', true); // --- UBAH: eager load relasi typeItem return $query->with('typeItem')->get(); // Menghapus ->toArray() } // --- UBAH: Sesuaikan nama method filter public function filterByType($typeId = null) // --- UBAH: Parameter menjadi $typeId { $this->typeItemId = $typeId; // --- UBAH: Set $this->typeItemId // Data foodItems akan diperbarui otomatis via render() dan getFilteredFoodItemsProperty() // Jadi, tidak perlu secara eksplisit memuat ulang di sini. // Dispatch event untuk update URL (jika diperlukan) if ($typeId) { // Asumsi route Anda mendukung parameter type_item_id $typeItemName = TypeItems::find($typeId)->name ?? 'all'; // Ambil nama untuk URL $this->dispatch('updateUrl', url: route('menu.byType', ['type' => Str::slug($typeItemName)])); } else { $this->dispatch('updateUrl', url: route('menu.all')); } } public function mount($type = null) // --- UBAH: Parameter bisa berupa slug atau ID { // --- UBAH: Ambil semua TypeItems saat mount $this->allTypeItems = TypeItems::all(); if ($type) { // Coba temukan type_item berdasarkan slug atau ID $foundType = TypeItems::where('id', $type) ->orWhere('name', Str::title(str_replace('-', ' ', $type))) // Coba cari berdasarkan nama yang dislug ->first(); $this->typeItemId = $foundType->id ?? null; } // --- UBAH: Awalnya, foodItems diisi oleh getFilteredFoodItemsProperty() di render // Jadi tidak perlu query langsung di mount, cukup set $typeItemId // Namun, jika Anda ingin agar foodItems langsung terisi saat mount, Anda bisa panggil properti $this->foodItems = $this->getFilteredFoodItemsProperty(); $this->cart = session()->get('cart', []); } public function addToCart($id) { logger("Adding to cart: $id"); // --- UBAH: Menggunakan model Items $item = Items::find($id); // Langsung query dari DB untuk memastikan data terkini if ($item) { if (!isset($this->cart[$id])) { $this->cart[$id] = 1; } else { $this->cart[$id]++; } $this->updateCart(); $this->dispatch('notify', message: $item->name . ' ditambahkan ke keranjang'); } else { logger("Item with ID $id not found."); $this->dispatch('notify', message: 'Item tidak ditemukan.'); } } public function removeFromCart($id) { if (isset($this->cart[$id])) { $this->cart[$id]--; if ($this->cart[$id] <= 0) { unset($this->cart[$id]); } $this->updateCart(); } } public function updateCart() { session()->put('cart', $this->cart); } public function updated($name, $value) { if (Str::startsWith($name, 'cart.')) { $foodId = (int)substr($name, 5); if ($value <= 0 || $value === null) { unset($this->cart[$foodId]); } else { $this->cart[$foodId] = (int)$value; } $this->updateCart(); } } public function getCartItemsProperty() { $items = []; // --- UBAH: Query items dari database berdasarkan ID di keranjang // Ini lebih aman daripada mengandalkan $this->foodItems lokal yang mungkin sudah difilter $foodIdsInCart = array_keys($this->cart); $foodModels = Items::whereIn('id', $foodIdsInCart)->get()->keyBy('id'); // Ambil model Item foreach ($this->cart as $foodId => $qty) { $food = $foodModels->get($foodId); // Ambil model langsung dari koleksi if ($food && $qty > 0) { $items[] = [ 'id' => $foodId, 'name' => $food->name, 'price' => $food->price, 'image_url' => $food->image_url ?? null, 'qty' => $qty, 'total_price' => $food->price * $qty, ]; } } return $items; } public function getCartTotalProperty() { return array_sum(array_map(function($item) { return $item['total_price']; }, $this->getCartItemsProperty())); } public function clearCart() { $this->cart = []; $this->updateCart(); $this->closeCart(); } public function handlePaymentSuccess() { $this->clearCart(); $this->dispatch('notify', message: 'Pembayaran berhasil!'); } public function checkout() { logger("Checkout method called"); $cartItems = $this->getCartItemsProperty(); logger("Cart items: " . json_encode($cartItems)); if (empty($cartItems)) { logger("Cart is empty"); $this->dispatch('notify', message: 'Keranjang kosong'); return; } try { logger("Setting up Midtrans config"); \Midtrans\Config::$serverKey = config('services.midtrans.server_key'); \Midtrans\Config::$isProduction = false; \Midtrans\Config::$isSanitized = true; \Midtrans\Config::$is3ds = true; $params = [ 'transaction_details' => [ 'order_id' => 'ORDER-' . time(), 'gross_amount' => $this->getCartTotalProperty(), ], 'customer_details' => [ 'first_name' => auth()->user()->name ?? 'Guest', 'email' => auth()->user()->email ?? 'guest@example.com', ], // --- BARU: Menambahkan item_details untuk Midtrans 'item_details' => array_map(function($item) { return [ 'id' => $item['id'], 'price' => $item['price'], 'quantity' => $item['qty'], 'name' => $item['name'], ]; }, $cartItems), ]; logger("Midtrans params: " . json_encode($params)); $snapToken = \Midtrans\Snap::getSnapToken($params); logger("Snap token generated: " . $snapToken); $this->dispatch('midtransSnapToken', token: $snapToken); } catch (\Exception $e) { logger("Midtrans error: " . $e->getMessage()); logger("Error trace: " . $e->getTraceAsString()); $this->dispatch('notify', message: 'Gagal memproses pembayaran: ' . $e->getMessage()); } } // Method untuk mendapatkan title berdasarkan type_item_id // --- UBAH: Menggunakan type_item_id dan mengambil nama dari TypeItems public function getPageTitleProperty() { if ($this->typeItemId) { $typeItem = TypeItems::find($this->typeItemId); return $typeItem->name ?? 'Semua Menu'; } return 'Semua Menu'; } public function render() { return view('livewire.food-order', [ 'foodItems' => $this->getFilteredFoodItemsProperty(), // --- UBAH: Gunakan properti terkomputasi 'cartItems' => $this->getCartItemsProperty(), 'cartTotal' => $this->getCartTotalProperty(), 'pageTitle' => $this->getPageTitleProperty(), 'typeItemId' => $this->typeItemId, // --- UBAH: Mengganti foodType menjadi typeItemId 'allTypeItems' => $this->allTypeItems, // --- BARU: Lewatkan allTypeItems ke view ])->layout('components.layouts.front'); } }