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 @@ + + +