272 lines
9.0 KiB
PHP
272 lines
9.0 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire;
|
|
|
|
use Livewire\Component;
|
|
use App\Models\Items; // --- UBAH: Menggunakan model Items
|
|
use App\Models\TypeItems; // --- BARU: Menambahkan model TypeItems
|
|
use Illuminate\Support\Str;
|
|
use Midtrans\Config;
|
|
use Midtrans\Snap;
|
|
|
|
class FoodOrder extends Component
|
|
{
|
|
public $foodItems = []; // --- UBAH: Menghapus 'array' type hint agar lebih fleksibel
|
|
public array $cart = [];
|
|
public bool $showCart = false;
|
|
public ?int $typeItemId = null; // --- UBAH: Mengganti $foodType menjadi $typeItemId (sesuai ItemTable)
|
|
|
|
// --- BARU: Properties untuk dropdown seperti di ItemTable
|
|
public $allTypeItems;
|
|
|
|
protected $listeners = [
|
|
'paymentSuccess' => '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');
|
|
}
|
|
}
|