diff --git a/app/Livewire/Datatable/Manage/WarehousesTable.php b/app/Livewire/Datatable/Master/WarehousesTable.php similarity index 75% rename from app/Livewire/Datatable/Manage/WarehousesTable.php rename to app/Livewire/Datatable/Master/WarehousesTable.php index 91363d4..beec81f 100644 --- a/app/Livewire/Datatable/Manage/WarehousesTable.php +++ b/app/Livewire/Datatable/Master/WarehousesTable.php @@ -1,6 +1,6 @@ label(function ($row) { $actions = ''; + if (auth()->user()->can('show warehouse')) { + $actions .= view('components.actions.table.show', [ + 'showRoute' => route('studio.master.warehouse.show', $row->hash), + ])->render(); + } + if (auth()->user()->can('update warehouse')) { $actions .= view('components.actions.table.edit-modal', [ 'id' => $row->hash, @@ -42,7 +48,7 @@ public function columns(): array return $actions; }) ->html() - ->hideIf(auth()->user()->cannot('update warehouse') && auth()->user()->cannot('delete warehouse')), + ->hideIf(auth()->user()->cannot('view warehouse') && auth()->user()->cannot('update warehouse') && auth()->user()->cannot('delete warehouse')), ]; } diff --git a/app/Livewire/Studio/Master/Warehouse/Index.php b/app/Livewire/Studio/Master/Warehouse/Index.php new file mode 100644 index 0000000..336aa61 --- /dev/null +++ b/app/Livewire/Studio/Master/Warehouse/Index.php @@ -0,0 +1,89 @@ +canOrAbort('create warehouse'); + + $this->form->store(); + + $this->dispatch('refreshDatatable'); + + $this->toast('Gudang berhasil ditambahkan.'); + + Flux::modals()->close(); + } + + public function update(): void + { + $this->canOrAbort('update warehouse'); + + $this->form->update(); + + $this->dispatch('refreshDatatable'); + + $this->toast('Gudang berhasil diperbarui.'); + + Flux::modals()->close(); + } + + public function delete(WarehouseModel $warehouse): void + { + $this->canOrAbort('delete warehouse'); + + $this->form->warehouse = $warehouse; + + $this->form->delete(); + + $this->dispatch('refreshDatatable'); + + $this->toast('Gudang berhasil dihapus.'); + + Flux::modals()->close(); + } + + #[On('modal:open')] + public function openModal(string $method, string $modalTitle, ?string $id = null): void + { + $this->resetValidation(); + $this->resetErrorBag(); + + $this->method = $method; + $this->modalTitle = $modalTitle; + + $id && $this->form->setWarehouse(WarehouseModel::byHashOrFail($id)); + } + + public function render(): View + { + return view('livewire.studio.master.warehouse.index', [ + 'pageTitle' => 'Gudang', + ]); + } +} diff --git a/app/Livewire/Studio/Master/Warehouse/Show.php b/app/Livewire/Studio/Master/Warehouse/Show.php new file mode 100644 index 0000000..5d9125e --- /dev/null +++ b/app/Livewire/Studio/Master/Warehouse/Show.php @@ -0,0 +1,91 @@ +warehouse = $warehouse; + } + + public function getStatsProperty() + { + $perfumesCount = $this->warehouse->perfumes()->count(); + $productsCount = $this->warehouse->products()->count(); + $bottlesCount = $this->warehouse->bottles()->count(); + $totalItems = $perfumesCount + $productsCount + $bottlesCount; + + return [ + [ + 'title' => 'Total Item', + 'value' => number_format($totalItems, 0, ',', '.'), + ], + [ + 'title' => 'Parfum', + 'value' => number_format($perfumesCount, 0, ',', '.'), + ], + [ + 'title' => 'Produk', + 'value' => number_format($productsCount, 0, ',', '.'), + ], + [ + 'title' => 'Botol', + 'value' => number_format($bottlesCount, 0, ',', '.'), + ], + ]; + } + + public function getItemsProperty() + { + $warehouse = $this->warehouse; + + $perfumes = $warehouse->perfumes()->get()->map(function ($item) { + return [ + 'id' => 'perfume_'.$item->id, + 'type' => 'Parfum', + 'name' => $item->name, + 'stock' => $item->pivot->stock ?? 0, + ]; + }); + + $products = $warehouse->products()->get()->map(function ($item) { + return [ + 'id' => 'product_'.$item->id, + 'type' => 'Produk', + 'name' => $item->name, + 'stock' => $item->pivot->stock ?? 0, + ]; + }); + + $bottles = $warehouse->bottles()->get()->map(function ($item) { + return [ + 'id' => 'bottle_'.$item->id, + 'type' => 'Botol', + 'name' => $item->name, + 'stock' => $item->pivot->stock ?? 0, + ]; + }); + + return $perfumes->concat($products)->concat($bottles); + } + + public function render(): View + { + return view('livewire.studio.master.warehouse.show', [ + 'pageTitle' => 'Detail Gudang', + 'stats' => $this->stats, + ]); + } +} diff --git a/database/migrations/2025_12_27_100001_create_warehouse_perfume_table.php b/database/migrations/2025_12_27_100001_create_warehouse_perfume_table.php new file mode 100644 index 0000000..c4383a7 --- /dev/null +++ b/database/migrations/2025_12_27_100001_create_warehouse_perfume_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignId('warehouse_id')->constrained()->cascadeOnDelete(); + $table->foreignId('perfume_id')->constrained()->cascadeOnDelete(); + $table->unsignedInteger('stock')->default(0); + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('perfume_warehouse'); + } +}; diff --git a/database/migrations/2025_12_27_100002_create_warehouse_product_table.php b/database/migrations/2025_12_27_100002_create_warehouse_product_table.php new file mode 100644 index 0000000..5c1726e --- /dev/null +++ b/database/migrations/2025_12_27_100002_create_warehouse_product_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignId('warehouse_id')->constrained()->cascadeOnDelete(); + $table->foreignId('product_id')->constrained()->cascadeOnDelete(); + $table->unsignedInteger('stock')->default(0); + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('product_warehouse'); + } +}; diff --git a/database/migrations/2025_12_27_100003_create_bottle_warehouse_table.php b/database/migrations/2025_12_27_100003_create_bottle_warehouse_table.php new file mode 100644 index 0000000..3ff2f14 --- /dev/null +++ b/database/migrations/2025_12_27_100003_create_bottle_warehouse_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignId('bottle_id')->constrained()->cascadeOnDelete(); + $table->foreignId('warehouse_id')->constrained()->cascadeOnDelete(); + $table->unsignedInteger('stock')->default(0); + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('bottle_warehouse'); + } +}; diff --git a/resources/views/livewire/studio/master/warehouse.blade.php b/resources/views/livewire/studio/master/warehouse/index.blade.php similarity index 89% rename from resources/views/livewire/studio/master/warehouse.blade.php rename to resources/views/livewire/studio/master/warehouse/index.blade.php index d28767b..547d3e0 100644 --- a/resources/views/livewire/studio/master/warehouse.blade.php +++ b/resources/views/livewire/studio/master/warehouse/index.blade.php @@ -14,7 +14,7 @@