TKK_E32222868/app/Livewire/BundleTable.php

206 lines
6.7 KiB
PHP

<?php
namespace App\Livewire;
use App\Models\Bundles; // Gunakan singular Bundle
use App\Models\Items; // Gunakan singular Item
use Livewire\Component;
use Livewire\WithPagination;
class BundleTable extends Component
{
use WithPagination;
public $search = '';
public $sortBy = 'name';
public $sortDirection = 'asc';
// Properti untuk form Create/Edit Bundle
public $bundleId;
public $name;
public $description;
public $price;
public $is_active = true;
// Untuk fitur mengelola item dalam bundle (penting untuk Many-to-Many)
public $selectedItems = []; // Array ID item yang dipilih untuk bundle ini
public $allItems = [];// Semua item yang tersedia untuk dipilih di form
public $isModalOpen = false;
public $isDeleteModalOpen = false;
public $bundleToDeleteId;
// Aturan validasi
protected $rules = [
'name' => 'required|string|max:255|unique:bundles,name',
'description' => 'nullable|string',
'price' => 'nullable|numeric|min:0',
'is_active' => 'boolean',
'selectedItems' => 'nullable|array', // selectedItems sekarang adalah array
'selectedItems.*' => 'exists:items,id', // Setiap ID dalam array harus ada di tabel items
];
// Mounted lifecycle hook untuk mengambil data dropdown
public function mount()
{
$this->allItems = Items::all(['id', 'name']); // Ambil semua item untuk pilihan di form
}
// Reset halaman pagination setiap kali properti pencarian berubah
public function updatingSearch()
{
$this->resetPage();
}
// Metode untuk mengubah kolom sorting
public function sortBy($field)
{
if ($this->sortBy === $field) {
$this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
} else {
$this->sortBy = $field;
$this->sortDirection = 'asc';
}
}
// Metode untuk membuka modal Create Bundle
public function create()
{
$this->resetInputFields();
$this->is_active = true;
// Tidak perlu mengambil allItems lagi karena sudah di mount(),
// tapi pastikan selectedItems direset
$this->selectedItems = [];
$this->isModalOpen = true;
}
// Metode untuk mengisi form edit dan membuka modal
public function edit($id)
{
$bundle = Bundles::findOrFail($id); // Gunakan Bundle
$this->bundleId = $bundle->id;
$this->name = $bundle->name;
$this->description = $bundle->description;
$this->price = $bundle->price;
$this->is_active = $bundle->is_active;
// === PENTING: Ambil ID item yang sudah terkait dengan bundle ini ===
$this->selectedItems = $bundle->items->pluck('id')->toArray();
$this->isModalOpen = true;
}
// Metode untuk menyimpan atau memperbarui Bundle
public function store()
{
$rules = $this->rules;
if ($this->bundleId) {
// Untuk update, 'name' harus unique kecuali jika itu adalah nama dari bundle yang sedang diedit
$rules['name'] = 'required|string|max:255|unique:bundles,name,' . $this->bundleId;
}
$this->validate($rules);
$bundleData = [
'name' => $this->name,
'description' => $this->description,
'price' => $this->price,
'is_active' => $this->is_active,
];
$bundle = null; // Inisialisasi variabel $bundle
if ($this->bundleId) {
// Update Bundle
$bundle = Bundles::find($this->bundleId); // Gunakan Bundle
$bundle->update($bundleData);
session()->flash('message', 'Bundle berhasil diperbarui!');
} else {
// Create Bundle
$bundle = Bundles::create($bundleData); // Gunakan Bundle
session()->flash('message', 'Bundle berhasil ditambahkan!');
}
// === PENTING: Sinkronkan relasi many-to-many setelah bundle dibuat/diperbarui ===
if ($bundle && !empty($this->selectedItems)) {
$bundle->items()->sync($this->selectedItems);
} elseif ($bundle) {
// Jika tidak ada item yang dipilih, detach semua relasi item yang ada
$bundle->items()->detach();
}
$this->closeModal();
$this->resetInputFields();
}
// Metode untuk membuka modal konfirmasi hapus
public function confirmDelete($id)
{
$this->bundleToDeleteId = $id;
$this->isDeleteModalOpen = true;
}
// Metode untuk menghapus Bundle
public function delete()
{
if ($this->bundleToDeleteId) {
$bundle = Bundles::find($this->bundleToDeleteId); // Gunakan Bundle
if ($bundle) {
// Relasi many-to-many secara otomatis akan di-cascade oleh foreign key ON DELETE CASCADE
// di tabel pivot (bundle_item) ketika bundle dihapus.
// Oleh karena itu, $bundle->items()->detach(); sebenarnya tidak mutlak diperlukan di sini
// jika DB constraint sudah diatur dengan benar.
// Namun, secara eksplisit detach juga aman dilakukan.
// $bundle->items()->detach();
$bundle->delete();
session()->flash('message', 'Bundle berhasil dihapus!');
}
}
$this->closeDeleteModal();
}
// Tutup modal create/edit
public function closeModal()
{
$this->isModalOpen = false;
$this->resetValidation();
}
// Tutup modal konfirmasi hapus
public function closeDeleteModal()
{
$this->isDeleteModalOpen = false;
$this->bundleToDeleteId = null;
}
// Reset semua input form
private function resetInputFields()
{
$this->bundleId = null;
$this->name = '';
$this->description = '';
$this->price = '';
$this->is_active = true;
$this->selectedItems = []; // Reset selectedItems ke array kosong
}
// Metode render komponen Livewire
public function render()
{
$bundles = Bundles::query() // Gunakan Bundle
->when($this->search, function ($query) {
$query->where('name', 'like', '%' . $this->search . '%')
->orWhere('description', 'like', '%' . $this->search . '%');
})
->orderBy($this->sortBy, $this->sortDirection)
// === EAGER LOAD RELASI ITEMS UNTUK MENAMPILKANNYA DI VIEW ===
->with('items') // Eager load relasi items untuk menampilkan di tabel
->paginate(10);
return view('livewire.bundle-table', [
'bundles' => $bundles,
// allItems akan tersedia secara otomatis karena public property
]);
}
}