diff --git a/app/Livewire/Datatable/VouchersTable.php b/app/Livewire/Datatable/VouchersTable.php index 643d132..3e66f38 100644 --- a/app/Livewire/Datatable/VouchersTable.php +++ b/app/Livewire/Datatable/VouchersTable.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Blade; use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\Views\Column; +use Rappasoft\LaravelLivewireTables\Views\Columns\ArrayColumn; class VouchersTable extends DataTableComponent { @@ -54,6 +55,11 @@ public function columns(): array Column::make('Batas Per Pembali', 'limit_per_user')->searchable()->sortable(), + ArrayColumn::make('Outlet') + ->data(fn ($value, $row) => $row->outlets->pluck('name')->toArray()) + ->outputFormat(fn ($index, $value) => Blade::render(''.$value.'')) + ->flexRow(['class' => 'gap-2 flex-wrap']), + Column::make('Tanggal') ->label(function ($row) { $startDate = formatDate($row->start_date); @@ -105,6 +111,6 @@ public function columns(): array public function builder(): Builder { - return Voucher::select('id', 'name', 'code', 'min_purchase', 'discount_amount', 'max_discount', 'quota', 'limit_per_user', 'start_date', 'end_date', 'is_active', 'type'); + return Voucher::select('id', 'name', 'code', 'min_purchase', 'discount_amount', 'max_discount', 'quota', 'limit_per_user', 'start_date', 'end_date', 'is_active', 'type')->with('outlets'); } } diff --git a/app/Livewire/Forms/VoucherForm.php b/app/Livewire/Forms/VoucherForm.php index 23f3bc7..2fb2ea5 100644 --- a/app/Livewire/Forms/VoucherForm.php +++ b/app/Livewire/Forms/VoucherForm.php @@ -6,6 +6,7 @@ use App\Enums\VoucherType; use App\Models\Voucher; use App\Rules\UnsignedInteger; +use Illuminate\Support\Facades\DB; use Illuminate\Validation\Rule; use Livewire\Form; @@ -37,6 +38,8 @@ class VoucherForm extends Form public string $is_active = '1'; + public array $outlet_ids = []; + public function rules(): array { return [ @@ -71,6 +74,8 @@ public function rules(): array 'end_date' => ['nullable', 'date', 'after_or_equal:start_date'], 'terms_conditions' => ['nullable', 'string'], 'is_active' => ['required', Rule::in(IsActive::values())], + 'outlet_ids' => ['required', 'array', 'min:1'], + 'outlet_ids.*' => Rule::exists('outlets', 'id'), ]; } @@ -94,6 +99,8 @@ public function validationAttributes(): array public function setVoucher(Voucher $voucher) { + $voucher->load('outlets'); + $this->voucher = $voucher; $this->name = $this->voucher->name; @@ -108,6 +115,8 @@ public function setVoucher(Voucher $voucher) $this->start_date = $this->voucher->start_date; $this->end_date = $this->voucher->end_date; $this->is_active = $this->voucher->is_active->value; + + $this->outlet_ids = $this->voucher->outlets->pluck('id')->toArray(); } public function store() @@ -116,7 +125,11 @@ public function store() $data = $this->prepareSavedData(); - Voucher::create($data); + DB::transaction(function () use ($data) { + $voucher = Voucher::create($data); + + $voucher->outlets()->attach($this->outlet_ids); + }); } public function update() @@ -124,8 +137,11 @@ public function update() $this->validate(); $data = $this->prepareSavedData(); + DB::transaction(function () use ($data) { + $this->voucher->update($data); - $this->voucher->update($data); + $this->voucher->outlets()->sync($this->outlet_ids); + }); } private function prepareSavedData() diff --git a/app/Livewire/Studio/Loyalty/Voucher/Create.php b/app/Livewire/Studio/Loyalty/Voucher/Create.php index 1693f45..2c32f24 100644 --- a/app/Livewire/Studio/Loyalty/Voucher/Create.php +++ b/app/Livewire/Studio/Loyalty/Voucher/Create.php @@ -3,6 +3,8 @@ namespace App\Livewire\Studio\Loyalty\Voucher; use App\Livewire\Forms\VoucherForm; +use App\Models\Outlet; +use App\Traits\Voucher\WithOutletSelector; use App\Traits\WithUpdatedData; use Flux\Flux; use Livewire\Attributes\Title; @@ -11,10 +13,17 @@ #[Title('Tambah Voucher')] class Create extends Component { - use WithUpdatedData; + use WithOutletSelector, WithUpdatedData; public VoucherForm $form; + public array $outlets; + + public function mount() + { + $this->outlets = Outlet::pluck('name', 'id')->toArray(); + } + public function save() { $this->form->store(); diff --git a/app/Livewire/Studio/Loyalty/Voucher/Edit.php b/app/Livewire/Studio/Loyalty/Voucher/Edit.php index f47c82e..2597d88 100644 --- a/app/Livewire/Studio/Loyalty/Voucher/Edit.php +++ b/app/Livewire/Studio/Loyalty/Voucher/Edit.php @@ -3,7 +3,9 @@ namespace App\Livewire\Studio\Loyalty\Voucher; use App\Livewire\Forms\VoucherForm; +use App\Models\Outlet; use App\Models\Voucher; +use App\Traits\Voucher\WithOutletSelector; use App\Traits\WithUpdatedData; use Flux\Flux; use Livewire\Attributes\Title; @@ -12,13 +14,17 @@ #[Title('Ubah Voucher')] class Edit extends Component { - use WithUpdatedData; + use WithOutletSelector, WithUpdatedData; public VoucherForm $form; + public array $outlets; + public function mount(Voucher $voucher) { $this->form->setVoucher($voucher); + + $this->outlets = Outlet::pluck('name', 'id')->toArray(); } public function save() diff --git a/app/Models/Outlet.php b/app/Models/Outlet.php index a2a4a83..e29551d 100644 --- a/app/Models/Outlet.php +++ b/app/Models/Outlet.php @@ -47,4 +47,9 @@ public function facilities(): HasMany { return $this->hasMany(Facility::class); } + + public function vouchers(): BelongsToMany + { + return $this->belongsToMany(Voucher::class); + } } diff --git a/app/Models/OutletVoucher.php b/app/Models/OutletVoucher.php new file mode 100644 index 0000000..8bbbe55 --- /dev/null +++ b/app/Models/OutletVoucher.php @@ -0,0 +1,12 @@ + IsActive::class, ]; } + + public function outlets(): BelongsToMany + { + return $this->belongsToMany(Outlet::class); + } } diff --git a/app/Traits/Voucher/WithOutletSelector.php b/app/Traits/Voucher/WithOutletSelector.php new file mode 100644 index 0000000..3f09248 --- /dev/null +++ b/app/Traits/Voucher/WithOutletSelector.php @@ -0,0 +1,16 @@ +form->outlet_ids = array_keys($this->outlets); + } + + public function deselectAll() + { + $this->form->outlet_ids = []; + } +} diff --git a/database/migrations/2025_09_30_015446_create_outlet_voucher_table.php b/database/migrations/2025_09_30_015446_create_outlet_voucher_table.php new file mode 100644 index 0000000..2a8b651 --- /dev/null +++ b/database/migrations/2025_09_30_015446_create_outlet_voucher_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('outlet_id')->constrained()->cascadeOnDelete(); + $table->foreignId('voucher_id')->constrained()->cascadeOnDelete(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('outlet_voucher'); + } +}; diff --git a/database/seeders/VoucherSeeder.php b/database/seeders/VoucherSeeder.php index 9aa42a9..0d5b9a9 100644 --- a/database/seeders/VoucherSeeder.php +++ b/database/seeders/VoucherSeeder.php @@ -4,6 +4,7 @@ use App\Enums\IsActive; use App\Enums\VoucherType; +use App\Models\Outlet; use App\Models\Voucher; use Illuminate\Database\Seeder; @@ -11,7 +12,7 @@ class VoucherSeeder extends Seeder { public function run(): void { - Voucher::insert([ + $vouchers = [ [ 'name' => 'Diskon 10%', 'code' => 'DISC10', @@ -103,6 +104,12 @@ public function run(): void 'end_date' => null, 'is_active' => IsActive::ACTIVE, ], - ]); + ]; + + foreach ($vouchers as $voucher) { + $newVoucher = Voucher::create($voucher); + + $newVoucher->outlets()->attach(Outlet::inRandomOrder()->first()->id); + } } } diff --git a/resources/views/livewire/studio/loyalty/voucher/form.blade.php b/resources/views/livewire/studio/loyalty/voucher/form.blade.php index 03a59f3..165b681 100644 --- a/resources/views/livewire/studio/loyalty/voucher/form.blade.php +++ b/resources/views/livewire/studio/loyalty/voucher/form.blade.php @@ -125,6 +125,20 @@ class="**:data-[slot=content]:min-h-[100px]!" /> @endforeach + + + + Pilih Semua + + Hapus Semua + + @foreach ($outlets as $key => $value) + {{ $value }} + + @endforeach + +