From 426d7ed61c1a47def800de0ef4b27c049b045a49 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 10 Jun 2026 15:49:03 +0700 Subject: [PATCH] Add customer management features including Customer model, CustomerController for CRUD operations, and CustomerRequest for validation. Integrate permissions in the Permission and Role enums, and update routes for customer management. Enhance UI components for customer listing and management, including a data table and form modal. Update sidebar for customer navigation. --- app/Enums/Permission.php | 12 ++ app/Enums/Role.php | 12 ++ .../Admin/Master/CustomerController.php | 59 ++++++++ .../Requests/Admin/Master/CustomerRequest.php | 30 ++++ app/Models/Customer.php | 13 ++ app/Services/Master/CustomerService.php | 67 +++++++++ ...26_06_10_083738_create_customers_table.php | 34 +++++ resources/js/components/AppSidebar.vue | 14 +- .../master/customers/CustomerFormModal.vue | 134 ++++++++++++++++++ .../admin/master/customers/columns.ts | 34 +++++ .../master/customers/data-table-actions.vue | 70 +++++++++ .../js/pages/admin/master/customers/Index.vue | 108 ++++++++++++++ resources/js/types/customers.ts | 31 ++++ routes/web.php | 19 +++ 14 files changed, 635 insertions(+), 2 deletions(-) create mode 100644 app/Http/Controllers/Admin/Master/CustomerController.php create mode 100644 app/Http/Requests/Admin/Master/CustomerRequest.php create mode 100644 app/Models/Customer.php create mode 100644 app/Services/Master/CustomerService.php create mode 100644 database/migrations/2026_06_10_083738_create_customers_table.php create mode 100644 resources/js/components/admin/master/customers/CustomerFormModal.vue create mode 100644 resources/js/components/admin/master/customers/columns.ts create mode 100644 resources/js/components/admin/master/customers/data-table-actions.vue create mode 100644 resources/js/pages/admin/master/customers/Index.vue create mode 100644 resources/js/types/customers.ts diff --git a/app/Enums/Permission.php b/app/Enums/Permission.php index a37c8cc..6616f28 100644 --- a/app/Enums/Permission.php +++ b/app/Enums/Permission.php @@ -27,6 +27,11 @@ enum Permission: string case SUPPLIERS_UPDATE = 'suppliers.update'; case SUPPLIERS_DELETE = 'suppliers.delete'; + case CUSTOMERS_VIEW = 'customers.view'; + case CUSTOMERS_CREATE = 'customers.create'; + case CUSTOMERS_UPDATE = 'customers.update'; + case CUSTOMERS_DELETE = 'customers.delete'; + case PRODUCTS_VIEW = 'products.view'; case PRODUCTS_CREATE = 'products.create'; case PRODUCTS_UPDATE = 'products.update'; @@ -61,6 +66,11 @@ public function label(): string self::SUPPLIERS_UPDATE => 'Ubah Supplier', self::SUPPLIERS_DELETE => 'Hapus Supplier', + self::CUSTOMERS_VIEW => 'Lihat Pelanggan', + self::CUSTOMERS_CREATE => 'Tambah Pelanggan', + self::CUSTOMERS_UPDATE => 'Ubah Pelanggan', + self::CUSTOMERS_DELETE => 'Hapus Pelanggan', + self::PRODUCTS_VIEW => 'Lihat Produk', self::PRODUCTS_CREATE => 'Tambah Produk', self::PRODUCTS_UPDATE => 'Ubah Produk', @@ -85,6 +95,8 @@ public function group(): string self::CATEGORIES_DELETE => 'Kategori', self::SUPPLIERS_VIEW, self::SUPPLIERS_CREATE, self::SUPPLIERS_UPDATE, self::SUPPLIERS_DELETE => 'Supplier', + self::CUSTOMERS_VIEW, self::CUSTOMERS_CREATE, self::CUSTOMERS_UPDATE, + self::CUSTOMERS_DELETE => 'Pelanggan', self::PRODUCTS_VIEW, self::PRODUCTS_CREATE, self::PRODUCTS_UPDATE, self::PRODUCTS_DELETE, self::PRODUCTS_TOGGLE_STATUS => 'Produk', self::RAW_MATERIALS_VIEW, self::RAW_MATERIALS_CREATE, self::RAW_MATERIALS_UPDATE, diff --git a/app/Enums/Role.php b/app/Enums/Role.php index c6e530f..ca31ec0 100644 --- a/app/Enums/Role.php +++ b/app/Enums/Role.php @@ -52,6 +52,10 @@ public function permissions(): array Permission::SUPPLIERS_CREATE, Permission::SUPPLIERS_UPDATE, Permission::SUPPLIERS_DELETE, + Permission::CUSTOMERS_VIEW, + Permission::CUSTOMERS_CREATE, + Permission::CUSTOMERS_UPDATE, + Permission::CUSTOMERS_DELETE, Permission::PRODUCTS_VIEW, Permission::PRODUCTS_CREATE, Permission::PRODUCTS_UPDATE, @@ -78,6 +82,10 @@ public function permissions(): array Permission::SUPPLIERS_CREATE, Permission::SUPPLIERS_UPDATE, Permission::SUPPLIERS_DELETE, + Permission::CUSTOMERS_VIEW, + Permission::CUSTOMERS_CREATE, + Permission::CUSTOMERS_UPDATE, + Permission::CUSTOMERS_DELETE, Permission::PRODUCTS_VIEW, Permission::PRODUCTS_CREATE, Permission::PRODUCTS_UPDATE, @@ -112,6 +120,10 @@ public function permissions(): array Permission::SUPPLIERS_CREATE, Permission::SUPPLIERS_UPDATE, Permission::SUPPLIERS_DELETE, + Permission::CUSTOMERS_VIEW, + Permission::CUSTOMERS_CREATE, + Permission::CUSTOMERS_UPDATE, + Permission::CUSTOMERS_DELETE, Permission::PRODUCTS_VIEW, ], self::NON_OPERATOR => [ diff --git a/app/Http/Controllers/Admin/Master/CustomerController.php b/app/Http/Controllers/Admin/Master/CustomerController.php new file mode 100644 index 0000000..20d934d --- /dev/null +++ b/app/Http/Controllers/Admin/Master/CustomerController.php @@ -0,0 +1,59 @@ +parseDataTableQuery($request); + + return Inertia::render('admin/master/customers/Index', [ + 'customers' => $this->customerService->paginateForIndex($tableQuery), + 'filters' => $this->dataTableFilters($tableQuery), + ]); + } + + public function store(CustomerRequest $request): RedirectResponse + { + $this->customerService->create($request->validated()); + + Inertia::flash('success', 'Customer berhasil ditambahkan.'); + + return redirect()->route('admin.master.customers.index'); + } + + public function update(CustomerRequest $request, Customer $customer): RedirectResponse + { + $this->customerService->update($customer, $request->validated()); + + Inertia::flash('success', 'Customer berhasil diperbarui.'); + + return redirect()->route('admin.master.customers.index'); + } + + public function destroy(Customer $customer): RedirectResponse + { + $this->customerService->delete($customer); + + Inertia::flash('success', 'Customer berhasil dihapus.'); + + return redirect()->route('admin.master.customers.index'); + } +} diff --git a/app/Http/Requests/Admin/Master/CustomerRequest.php b/app/Http/Requests/Admin/Master/CustomerRequest.php new file mode 100644 index 0000000..e8e2aae --- /dev/null +++ b/app/Http/Requests/Admin/Master/CustomerRequest.php @@ -0,0 +1,30 @@ +isMethod('POST') + ? Permission::CUSTOMERS_CREATE + : Permission::CUSTOMERS_UPDATE; + + return $this->user()?->can($permission->value) ?? false; + } + + /** + * @return array + */ + public function rules(): array + { + return [ + 'name' => ['required', 'string', 'max:200'], + 'address' => ['required', 'string'], + 'phone_number' => ['required', 'string', 'max:20'], + ]; + } +} diff --git a/app/Models/Customer.php b/app/Models/Customer.php new file mode 100644 index 0000000..f8bd732 --- /dev/null +++ b/app/Models/Customer.php @@ -0,0 +1,13 @@ +when($tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { + $search = $tableQuery['search']; + $query->where(function (Builder $query) use ($search): void { + $query->where('name', 'like', "%{$search}%") + ->orWhere('phone_number', 'like', "%{$search}%") + ->orWhere('address', 'like', "%{$search}%"); + }); + }); + + $this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']); + + return $query + ->paginate(10) + ->withQueryString(); + } + + /** + * @param array $validated + */ + public function create(array $validated): void + { + Customer::create($validated); + } + + /** + * @param array $validated + */ + public function update(Customer $customer, array $validated): void + { + $customer->name = $validated['name']; + $customer->phone_number = $validated['phone_number']; + $customer->address = $validated['address']; + $customer->save(); + } + + public function delete(Customer $customer): void + { + $customer->delete(); + } + + private function applySorting(Builder $query, string $sort, string $direction): void + { + if (in_array($sort, ['name', 'phone_number', 'address'], true)) { + $query->orderBy($sort, $direction); + + return; + } + + $query->latest(); + } +} diff --git a/database/migrations/2026_06_10_083738_create_customers_table.php b/database/migrations/2026_06_10_083738_create_customers_table.php new file mode 100644 index 0000000..df677ab --- /dev/null +++ b/database/migrations/2026_06_10_083738_create_customers_table.php @@ -0,0 +1,34 @@ +id(); + + $table->string('name', 200); + $table->string('phone_number', 20)->nullable(); + $table->text('address')->nullable(); + + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('customers'); + } +}; diff --git a/resources/js/components/AppSidebar.vue b/resources/js/components/AppSidebar.vue index 9318fc6..22bd723 100644 --- a/resources/js/components/AppSidebar.vue +++ b/resources/js/components/AppSidebar.vue @@ -1,6 +1,6 @@ @@ -89,7 +91,7 @@ const showMasterMenu = computed(() => ( - + @@ -97,6 +99,14 @@ const showMasterMenu = computed(() => ( + + + + + Customer + + + diff --git a/resources/js/components/admin/master/customers/CustomerFormModal.vue b/resources/js/components/admin/master/customers/CustomerFormModal.vue new file mode 100644 index 0000000..bde316e --- /dev/null +++ b/resources/js/components/admin/master/customers/CustomerFormModal.vue @@ -0,0 +1,134 @@ + + +