Explorar el Código

feat: master customer

Muhammad Iqbal Afandi hace 4 años
padre
commit
0089c78e35

+ 29
- 11
app/Http/Controllers/CustomerController.php Ver fichero

2
 
2
 
3
 namespace App\Http\Controllers;
3
 namespace App\Http\Controllers;
4
 
4
 
5
+use App\Http\Requests\Customer\StoreCustomerRequest;
6
+use App\Http\Requests\Customer\UpdateCustomerRequest;
5
 use App\Models\Customer;
7
 use App\Models\Customer;
6
-use Illuminate\Http\Request;
7
 
8
 
8
 class CustomerController extends Controller
9
 class CustomerController extends Controller
9
 {
10
 {
19
      */
20
      */
20
     public function index()
21
     public function index()
21
     {
22
     {
22
-        return inertia('Customers/Index.vue');
23
+        return inertia('Customers/Index.vue', [
24
+            'initialSearch' => request('search'),
25
+            'customers' => Customer::filter(request()->only('search'))
26
+                ->latest()
27
+                ->paginate(10)
28
+                ->withQueryString()
29
+                ->through(fn($customer) => [
30
+                    'id' => $customer->id,
31
+                    'name' => $customer->name,
32
+                    'address' => $customer->address,
33
+                    'phone' => $customer->phone,
34
+                    'npwp' => $customer->npwp
35
+                ])
36
+        ]);
23
     }
37
     }
24
 
38
 
25
     /**
39
     /**
29
      */
43
      */
30
     public function create()
44
     public function create()
31
     {
45
     {
32
-        //
46
+        return inertia('Customers/Create');
33
     }
47
     }
34
 
48
 
35
     /**
49
     /**
38
      * @param  \Illuminate\Http\Request  $request
52
      * @param  \Illuminate\Http\Request  $request
39
      * @return \Illuminate\Http\Response
53
      * @return \Illuminate\Http\Response
40
      */
54
      */
41
-    public function store(Request $request)
55
+    public function store(StoreCustomerRequest $request)
42
     {
56
     {
43
-        //
57
+        Customer::create($request->validated());
58
+
59
+        return back()->with('success', __('messages.success.store.customer'));
44
     }
60
     }
45
 
61
 
46
     /**
62
     /**
57
     /**
73
     /**
58
      * Show the form for editing the specified resource.
74
      * Show the form for editing the specified resource.
59
      *
75
      *
60
-     * @param  int  $id
76
+     * @param  Customer  $customer
61
      * @return \Illuminate\Http\Response
77
      * @return \Illuminate\Http\Response
62
      */
78
      */
63
-    public function edit($id)
79
+    public function edit(Customer $customer)
64
     {
80
     {
65
-        //
81
+        return inertia('Customers/Edit.vue', compact('customer'));
66
     }
82
     }
67
 
83
 
68
     /**
84
     /**
69
      * Update the specified resource in storage.
85
      * Update the specified resource in storage.
70
      *
86
      *
71
      * @param  \Illuminate\Http\Request  $request
87
      * @param  \Illuminate\Http\Request  $request
72
-     * @param  int  $id
88
+     * @param  Customer  $customer
73
      * @return \Illuminate\Http\Response
89
      * @return \Illuminate\Http\Response
74
      */
90
      */
75
-    public function update(Request $request, $id)
91
+    public function update(UpdateCustomerRequest $request, Customer $customer)
76
     {
92
     {
77
-        //
93
+        $customer->update($request->validated());
94
+
95
+        return back()->with('success', __('messages.success.update.customer'));
78
     }
96
     }
79
 
97
 
80
     /**
98
     /**

+ 33
- 0
app/Http/Requests/Customer/StoreCustomerRequest.php Ver fichero

1
+<?php
2
+
3
+namespace App\Http\Requests\Customer;
4
+
5
+use Illuminate\Foundation\Http\FormRequest;
6
+
7
+class StoreCustomerRequest extends FormRequest
8
+{
9
+    /**
10
+     * Determine if the user is authorized to make this request.
11
+     *
12
+     * @return bool
13
+     */
14
+    public function authorize()
15
+    {
16
+        return true;
17
+    }
18
+
19
+    /**
20
+     * Get the validation rules that apply to the request.
21
+     *
22
+     * @return array<string, mixed>
23
+     */
24
+    public function rules()
25
+    {
26
+        return [
27
+            'name' => 'required|string|max:50',
28
+            'address' => 'required|string',
29
+            'phone' => 'required|numeric|digits_between:12,15|unique:customers,phone',
30
+            'npwp' => 'required|numeric|digits_between:15,20|unique:customers,npwp'
31
+        ];
32
+    }
33
+}

+ 33
- 0
app/Http/Requests/Customer/UpdateCustomerRequest.php Ver fichero

1
+<?php
2
+
3
+namespace App\Http\Requests\Customer;
4
+
5
+use Illuminate\Foundation\Http\FormRequest;
6
+
7
+class UpdateCustomerRequest extends FormRequest
8
+{
9
+    /**
10
+     * Determine if the user is authorized to make this request.
11
+     *
12
+     * @return bool
13
+     */
14
+    public function authorize()
15
+    {
16
+        return true;
17
+    }
18
+
19
+    /**
20
+     * Get the validation rules that apply to the request.
21
+     *
22
+     * @return array<string, mixed>
23
+     */
24
+    public function rules()
25
+    {
26
+        return [
27
+            'name' => 'required|string|max:50',
28
+            'address' => 'required|string',
29
+            'phone' => 'required|numeric|digits_between:12,15|unique:customers,phone,' . $this->customer->id,
30
+            'npwp' => 'required|numeric|digits_between:15,20|unique:customers,npwp,' . $this->customer->id
31
+        ];
32
+    }
33
+}

+ 13
- 0
app/Models/Customer.php Ver fichero

15
         'phone',
15
         'phone',
16
         'npwp'
16
         'npwp'
17
     ];
17
     ];
18
+
19
+    protected $hidden = ['created_at', 'updated_at'];
20
+
21
+    public function scopeFilter($query, array $filters)
22
+    {
23
+        $query->when($filters['search'] ?? null, function ($query, $search) {
24
+            $query->where(function ($query) use ($search) {
25
+                $query->where('name', 'like', '%' . $search . '%')
26
+                    ->orWhere('phone', 'like', '%' . $search . '%')
27
+                    ->orWhere('npwp', 'like', '%' . $search . '%');
28
+            });
29
+        });
30
+    }
18
 }
31
 }

+ 4
- 2
lang/en/messages.php Ver fichero

31
             'expense' => 'Expense successfully added',
31
             'expense' => 'Expense successfully added',
32
             'transaction' => 'Transaction successfully added',
32
             'transaction' => 'Transaction successfully added',
33
             'user' => 'User Account successfully added',
33
             'user' => 'User Account successfully added',
34
-            'reset_password' => 'Password successfully reset'
34
+            'reset_password' => 'Password successfully reset',
35
+            'customer' => 'Customer successfully addedd'
35
         ],
36
         ],
36
         'update' => [
37
         'update' => [
37
             'type_vehicle' => 'Type vehicle successfully changed',
38
             'type_vehicle' => 'Type vehicle successfully changed',
40
             'type_member' => 'Jenis member successfully changed',
41
             'type_member' => 'Jenis member successfully changed',
41
             'change_password' => 'Password successfully changed',
42
             'change_password' => 'Password successfully changed',
42
             'transaction_status' => 'Transaction Status successfully changed',
43
             'transaction_status' => 'Transaction Status successfully changed',
43
-            'user' => 'User Account successfully changed'
44
+            'user' => 'User Account successfully changed',
45
+            'customer' => 'Customer successfully changed'
44
         ],
46
         ],
45
         'destroy' => [
47
         'destroy' => [
46
             'type_member' => 'Jenis member successfully deleted',
48
             'type_member' => 'Jenis member successfully deleted',

+ 4
- 2
lang/id/messages.php Ver fichero

31
             'expense' => 'Pengeluaran berhasil ditambahkan',
31
             'expense' => 'Pengeluaran berhasil ditambahkan',
32
             'transaction' => 'Transaksi berhasil ditambahkan',
32
             'transaction' => 'Transaksi berhasil ditambahkan',
33
             'user' => 'Akun user berhasil ditambahkan',
33
             'user' => 'Akun user berhasil ditambahkan',
34
-            'reset_password' => 'Kata sandi berhasil di reset'
34
+            'reset_password' => 'Kata sandi berhasil di reset',
35
+            'customer' => 'Pelanggan berhasil ditambahkan'
35
         ],
36
         ],
36
         'update' => [
37
         'update' => [
37
             'type_vehicle' => 'Jenis kendaraan berhasil diubah',
38
             'type_vehicle' => 'Jenis kendaraan berhasil diubah',
40
             'type_member' => 'Jenis member berhasil diubah',
41
             'type_member' => 'Jenis member berhasil diubah',
41
             'change_password' => 'Password berhasil diubah',
42
             'change_password' => 'Password berhasil diubah',
42
             'transaction_status' => 'Status transaksi berhasil diubah',
43
             'transaction_status' => 'Status transaksi berhasil diubah',
43
-            'user' => 'Akun user berhasil diubah'
44
+            'user' => 'Akun user berhasil diubah',
45
+            'customer' => 'Pelanggan berhasil diubah'
44
         ],
46
         ],
45
         'destroy' => [
47
         'destroy' => [
46
             'type_member' => 'Jenis member berhasil dihapus',
48
             'type_member' => 'Jenis member berhasil dihapus',

+ 6
- 2
public/js/resources_js_pages_Auth_Login_vue.js Ver fichero

28
       type: String,
28
       type: String,
29
       required: true
29
       required: true
30
     },
30
     },
31
+    type: {
32
+      type: String,
33
+      "default": 'text'
34
+    },
31
     error: {
35
     error: {
32
       type: String,
36
       type: String,
33
       "default": null
37
       "default": null
285
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["w-full", {
289
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["w-full", {
286
       'p-invalid': $setup.isError
290
       'p-invalid': $setup.isError
287
     }]),
291
     }]),
288
-    type: "text",
292
+    type: $props.type,
289
     id: $setup.forLabel,
293
     id: $setup.forLabel,
290
     "aria-describedby": $setup.ariaDescribedbyLabel,
294
     "aria-describedby": $setup.ariaDescribedbyLabel,
291
     "model-value": $props.modelValue,
295
     "model-value": $props.modelValue,
297
     })
301
     })
298
   }, null, 8
302
   }, null, 8
299
   /* PROPS */
303
   /* PROPS */
300
-  , ["class", "id", "aria-describedby", "model-value", "placeholder", "value", "disabled"]), $props.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("small", {
304
+  , ["type", "class", "id", "aria-describedby", "model-value", "placeholder", "value", "disabled"]), $props.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("small", {
301
     key: 0,
305
     key: 0,
302
     id: $setup.ariaDescribedbyLabel,
306
     id: $setup.ariaDescribedbyLabel,
303
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({
307
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({

+ 1896
- 0
public/js/resources_js_pages_Customers_Create_vue.js
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


+ 1897
- 0
public/js/resources_js_pages_Customers_Edit_vue.js
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


+ 17781
- 43
public/js/resources_js_pages_Customers_Index_vue.js
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


+ 30
- 0
public/js/resources_js_pages_Customers_tableHeader_js.js Ver fichero

1
+"use strict";
2
+(self["webpackChunk"] = self["webpackChunk"] || []).push([["resources_js_pages_Customers_tableHeader_js"],{
3
+
4
+/***/ "./resources/js/pages/Customers/tableHeader.js":
5
+/*!*****************************************************!*\
6
+  !*** ./resources/js/pages/Customers/tableHeader.js ***!
7
+  \*****************************************************/
8
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9
+
10
+__webpack_require__.r(__webpack_exports__);
11
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
12
+/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
13
+/* harmony export */ });
14
+/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ([{
15
+  field: 'name',
16
+  header: 'Nama'
17
+}, {
18
+  field: 'address',
19
+  header: 'Alamat'
20
+}, {
21
+  field: 'phone',
22
+  header: 'No HP'
23
+}, {
24
+  field: 'npwp',
25
+  header: 'NPWP'
26
+}]);
27
+
28
+/***/ })
29
+
30
+}]);

+ 6
- 2
public/js/resources_js_pages_Users_Create_vue.js Ver fichero

128
       type: String,
128
       type: String,
129
       required: true
129
       required: true
130
     },
130
     },
131
+    type: {
132
+      type: String,
133
+      "default": 'text'
134
+    },
131
     error: {
135
     error: {
132
       type: String,
136
       type: String,
133
       "default": null
137
       "default": null
606
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["w-full", {
610
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["w-full", {
607
       'p-invalid': $setup.isError
611
       'p-invalid': $setup.isError
608
     }]),
612
     }]),
609
-    type: "text",
613
+    type: $props.type,
610
     id: $setup.forLabel,
614
     id: $setup.forLabel,
611
     "aria-describedby": $setup.ariaDescribedbyLabel,
615
     "aria-describedby": $setup.ariaDescribedbyLabel,
612
     "model-value": $props.modelValue,
616
     "model-value": $props.modelValue,
618
     })
622
     })
619
   }, null, 8
623
   }, null, 8
620
   /* PROPS */
624
   /* PROPS */
621
-  , ["class", "id", "aria-describedby", "model-value", "placeholder", "value", "disabled"]), $props.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("small", {
625
+  , ["type", "class", "id", "aria-describedby", "model-value", "placeholder", "value", "disabled"]), $props.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("small", {
622
     key: 0,
626
     key: 0,
623
     id: $setup.ariaDescribedbyLabel,
627
     id: $setup.ariaDescribedbyLabel,
624
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({
628
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({

+ 6
- 2
public/js/resources_js_pages_Users_Edit_vue.js Ver fichero

167
       type: String,
167
       type: String,
168
       required: true
168
       required: true
169
     },
169
     },
170
+    type: {
171
+      type: String,
172
+      "default": 'text'
173
+    },
170
     error: {
174
     error: {
171
       type: String,
175
       type: String,
172
       "default": null
176
       "default": null
729
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["w-full", {
733
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["w-full", {
730
       'p-invalid': $setup.isError
734
       'p-invalid': $setup.isError
731
     }]),
735
     }]),
732
-    type: "text",
736
+    type: $props.type,
733
     id: $setup.forLabel,
737
     id: $setup.forLabel,
734
     "aria-describedby": $setup.ariaDescribedbyLabel,
738
     "aria-describedby": $setup.ariaDescribedbyLabel,
735
     "model-value": $props.modelValue,
739
     "model-value": $props.modelValue,
741
     })
745
     })
742
   }, null, 8
746
   }, null, 8
743
   /* PROPS */
747
   /* PROPS */
744
-  , ["class", "id", "aria-describedby", "model-value", "placeholder", "value", "disabled"]), $props.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("small", {
748
+  , ["type", "class", "id", "aria-describedby", "model-value", "placeholder", "value", "disabled"]), $props.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("small", {
745
     key: 0,
749
     key: 0,
746
     id: $setup.ariaDescribedbyLabel,
750
     id: $setup.ariaDescribedbyLabel,
747
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({
751
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({

+ 6
- 2
public/js/resources_js_pages_Users_Show_vue.js Ver fichero

28
       type: String,
28
       type: String,
29
       required: true
29
       required: true
30
     },
30
     },
31
+    type: {
32
+      type: String,
33
+      "default": 'text'
34
+    },
31
     error: {
35
     error: {
32
       type: String,
36
       type: String,
33
       "default": null
37
       "default": null
503
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["w-full", {
507
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["w-full", {
504
       'p-invalid': $setup.isError
508
       'p-invalid': $setup.isError
505
     }]),
509
     }]),
506
-    type: "text",
510
+    type: $props.type,
507
     id: $setup.forLabel,
511
     id: $setup.forLabel,
508
     "aria-describedby": $setup.ariaDescribedbyLabel,
512
     "aria-describedby": $setup.ariaDescribedbyLabel,
509
     "model-value": $props.modelValue,
513
     "model-value": $props.modelValue,
515
     })
519
     })
516
   }, null, 8
520
   }, null, 8
517
   /* PROPS */
521
   /* PROPS */
518
-  , ["class", "id", "aria-describedby", "model-value", "placeholder", "value", "disabled"]), $props.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("small", {
522
+  , ["type", "class", "id", "aria-describedby", "model-value", "placeholder", "value", "disabled"]), $props.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("small", {
519
     key: 0,
523
     key: 0,
520
     id: $setup.ariaDescribedbyLabel,
524
     id: $setup.ariaDescribedbyLabel,
521
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({
525
     "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({

+ 25
- 1
public/js/vue.js Ver fichero

58308
 		"./resources/js/pages/Auth/Login.vue",
58308
 		"./resources/js/pages/Auth/Login.vue",
58309
 		"resources_js_pages_Auth_Login_vue"
58309
 		"resources_js_pages_Auth_Login_vue"
58310
 	],
58310
 	],
58311
+	"./Customers/Create": [
58312
+		"./resources/js/pages/Customers/Create.vue",
58313
+		"resources_js_pages_Customers_Create_vue"
58314
+	],
58315
+	"./Customers/Create.vue": [
58316
+		"./resources/js/pages/Customers/Create.vue",
58317
+		"resources_js_pages_Customers_Create_vue"
58318
+	],
58319
+	"./Customers/Edit": [
58320
+		"./resources/js/pages/Customers/Edit.vue",
58321
+		"resources_js_pages_Customers_Edit_vue"
58322
+	],
58323
+	"./Customers/Edit.vue": [
58324
+		"./resources/js/pages/Customers/Edit.vue",
58325
+		"resources_js_pages_Customers_Edit_vue"
58326
+	],
58311
 	"./Customers/Index": [
58327
 	"./Customers/Index": [
58312
 		"./resources/js/pages/Customers/Index.vue",
58328
 		"./resources/js/pages/Customers/Index.vue",
58313
 		"resources_js_pages_Customers_Index_vue"
58329
 		"resources_js_pages_Customers_Index_vue"
58316
 		"./resources/js/pages/Customers/Index.vue",
58332
 		"./resources/js/pages/Customers/Index.vue",
58317
 		"resources_js_pages_Customers_Index_vue"
58333
 		"resources_js_pages_Customers_Index_vue"
58318
 	],
58334
 	],
58335
+	"./Customers/tableHeader": [
58336
+		"./resources/js/pages/Customers/tableHeader.js",
58337
+		"resources_js_pages_Customers_tableHeader_js"
58338
+	],
58339
+	"./Customers/tableHeader.js": [
58340
+		"./resources/js/pages/Customers/tableHeader.js",
58341
+		"resources_js_pages_Customers_tableHeader_js"
58342
+	],
58319
 	"./Dashboards/Index": [
58343
 	"./Dashboards/Index": [
58320
 		"./resources/js/pages/Dashboards/Index.vue",
58344
 		"./resources/js/pages/Dashboards/Index.vue",
58321
 		"resources_js_pages_Dashboards_Index_vue"
58345
 		"resources_js_pages_Dashboards_Index_vue"
58513
 /******/ 		// This function allow to reference async chunks
58537
 /******/ 		// This function allow to reference async chunks
58514
 /******/ 		__webpack_require__.u = (chunkId) => {
58538
 /******/ 		__webpack_require__.u = (chunkId) => {
58515
 /******/ 			// return url for filenames based on template
58539
 /******/ 			// return url for filenames based on template
58516
-/******/ 			return "js/" + chunkId + ".js?id=" + {"node_modules_chart_js_auto_auto_esm_js":"9296b829a7757dee","resources_js_pages_Auth_Login_vue":"cb7d9267c0b9275e","resources_js_pages_Customers_Index_vue":"eb78407dfd08456f","resources_js_pages_Dashboards_Index_vue":"7f4150c836fe81d8","resources_js_pages_Purchases_Index_vue":"41fddd7f79c7a85d","resources_js_pages_Sales_Index_vue":"1da65c4ce926abbc","resources_js_pages_StockProducts_Index_vue":"74a65be5ec079b3f","resources_js_pages_Suppliers_Index_vue":"0f2fb6e79fdbec94","resources_js_pages_Users_Create_vue":"d77599e458334081","resources_js_pages_Users_Edit_vue":"e0eb01c3dc9f721f","resources_js_pages_Users_Index_vue":"575b2403097c7e16","resources_js_pages_Users_Show_vue":"5c32daddba0a1355","resources_js_pages_Users_tableHeader_js":"48f19bd820caf015"}[chunkId] + "";
58540
+/******/ 			return "js/" + chunkId + ".js?id=" + {"node_modules_chart_js_auto_auto_esm_js":"9296b829a7757dee","resources_js_pages_Auth_Login_vue":"8e53429f130c83f5","resources_js_pages_Customers_Create_vue":"1ec93aefdbb7bac8","resources_js_pages_Customers_Edit_vue":"47650583b348b8eb","resources_js_pages_Customers_Index_vue":"527935b3268e6218","resources_js_pages_Customers_tableHeader_js":"7a40a3d5ad60171c","resources_js_pages_Dashboards_Index_vue":"7f4150c836fe81d8","resources_js_pages_Purchases_Index_vue":"41fddd7f79c7a85d","resources_js_pages_Sales_Index_vue":"1da65c4ce926abbc","resources_js_pages_StockProducts_Index_vue":"74a65be5ec079b3f","resources_js_pages_Suppliers_Index_vue":"0f2fb6e79fdbec94","resources_js_pages_Users_Create_vue":"290f8cea7ecbd8da","resources_js_pages_Users_Edit_vue":"4f8b3ff98efb4ef3","resources_js_pages_Users_Index_vue":"575b2403097c7e16","resources_js_pages_Users_Show_vue":"5561027a65c32ca4","resources_js_pages_Users_tableHeader_js":"48f19bd820caf015"}[chunkId] + "";
58517
 /******/ 		};
58541
 /******/ 		};
58518
 /******/ 	})();
58542
 /******/ 	})();
58519
 /******/ 	
58543
 /******/ 	

+ 5
- 1
resources/js/components/AppInputText.vue Ver fichero

14
     type: String,
14
     type: String,
15
     required: true,
15
     required: true,
16
   },
16
   },
17
+  type: {
18
+    type: String,
19
+    default: 'text',
20
+  },
17
   error: {
21
   error: {
18
     type: String,
22
     type: String,
19
     default: null,
23
     default: null,
38
 
42
 
39
     <InputText
43
     <InputText
40
       class="w-full"
44
       class="w-full"
41
-      type="text"
45
+      :type="type"
42
       :class="{ 'p-invalid': isError }"
46
       :class="{ 'p-invalid': isError }"
43
       :id="forLabel"
47
       :id="forLabel"
44
       :aria-describedby="ariaDescribedbyLabel"
48
       :aria-describedby="ariaDescribedbyLabel"

+ 86
- 0
resources/js/pages/Customers/Create.vue Ver fichero

1
+<script setup>
2
+import { useForm, Head } from '@inertiajs/inertia-vue3'
3
+import { useFormErrorReset } from '@/components/useFormErrorReset'
4
+import AppInputText from '@/components/AppInputText.vue'
5
+import DashboardLayout from '@/layouts/DashboardLayout.vue'
6
+
7
+const form = useForm({
8
+  name: null,
9
+  address: null,
10
+  phone: null,
11
+  npwp: null,
12
+})
13
+
14
+useFormErrorReset(form)
15
+
16
+const onSubmit = () => {
17
+  form.post(route('customers.store'), { onSuccess: () => form.reset() })
18
+}
19
+</script>
20
+
21
+<template>
22
+  <Head title="Tambah Pelanggan" />
23
+
24
+  <DashboardLayout>
25
+    <div class="grid">
26
+      <div class="col-12 lg:col-8">
27
+        <Card>
28
+          <template #title> Tambah Pelanggan </template>
29
+          <template #content>
30
+            <div class="grid">
31
+              <div class="col-12 md:col-6">
32
+                <AppInputText
33
+                  label="Nama"
34
+                  placeholder="nama"
35
+                  :error="form.errors.name"
36
+                  v-model="form.name"
37
+                />
38
+              </div>
39
+
40
+              <div class="col-12 md:col-6">
41
+                <AppInputText
42
+                  label="Alamat"
43
+                  placeholder="alamat"
44
+                  :error="form.errors.address"
45
+                  v-model="form.address"
46
+                />
47
+              </div>
48
+
49
+              <div class="col-12 md:col-6">
50
+                <AppInputText
51
+                  label="No HP"
52
+                  placeholder="no hp"
53
+                  type="number"
54
+                  :error="form.errors.phone"
55
+                  v-model="form.phone"
56
+                />
57
+              </div>
58
+
59
+              <div class="col-12 md:col-6">
60
+                <AppInputText
61
+                  label="NPWP"
62
+                  placeholder="npwp"
63
+                  type="number"
64
+                  :error="form.errors.npwp"
65
+                  v-model="form.npwp"
66
+                />
67
+              </div>
68
+            </div>
69
+          </template>
70
+
71
+          <template #footer>
72
+            <div class="flex flex-column md:flex-row justify-content-end">
73
+              <Button
74
+                label="Simpan"
75
+                icon="pi pi-check"
76
+                class="p-button-outlined"
77
+                :disabled="form.processing"
78
+                @click="onSubmit"
79
+              />
80
+            </div>
81
+          </template>
82
+        </Card>
83
+      </div>
84
+    </div>
85
+  </DashboardLayout>
86
+</template>

+ 90
- 0
resources/js/pages/Customers/Edit.vue Ver fichero

1
+<script setup>
2
+import { useForm, Head } from '@inertiajs/inertia-vue3'
3
+import { useFormErrorReset } from '@/components/useFormErrorReset'
4
+import AppInputText from '@/components/AppInputText.vue'
5
+import DashboardLayout from '@/layouts/DashboardLayout.vue'
6
+
7
+const props = defineProps({
8
+  customer: Object,
9
+})
10
+
11
+const form = useForm({
12
+  name: props.customer.name,
13
+  address: props.customer.address,
14
+  phone: props.customer.phone,
15
+  npwp: props.customer.npwp,
16
+})
17
+
18
+useFormErrorReset(form)
19
+
20
+const onSubmit = () => {
21
+  form.put(route('customers.update', props.customer.id))
22
+}
23
+</script>
24
+
25
+<template>
26
+  <Head title="Tambah Pelanggan" />
27
+
28
+  <DashboardLayout>
29
+    <div class="grid">
30
+      <div class="col-12 lg:col-8">
31
+        <Card>
32
+          <template #title> Tambah Pelanggan </template>
33
+          <template #content>
34
+            <div class="grid">
35
+              <div class="col-12 md:col-6">
36
+                <AppInputText
37
+                  label="Nama"
38
+                  placeholder="nama"
39
+                  :error="form.errors.name"
40
+                  v-model="form.name"
41
+                />
42
+              </div>
43
+
44
+              <div class="col-12 md:col-6">
45
+                <AppInputText
46
+                  label="Alamat"
47
+                  placeholder="alamat"
48
+                  :error="form.errors.address"
49
+                  v-model="form.address"
50
+                />
51
+              </div>
52
+
53
+              <div class="col-12 md:col-6">
54
+                <AppInputText
55
+                  label="No HP"
56
+                  placeholder="no hp"
57
+                  type="number"
58
+                  :error="form.errors.phone"
59
+                  v-model="form.phone"
60
+                />
61
+              </div>
62
+
63
+              <div class="col-12 md:col-6">
64
+                <AppInputText
65
+                  label="NPWP"
66
+                  placeholder="npwp"
67
+                  type="number"
68
+                  :error="form.errors.npwp"
69
+                  v-model="form.npwp"
70
+                />
71
+              </div>
72
+            </div>
73
+          </template>
74
+
75
+          <template #footer>
76
+            <div class="flex flex-column md:flex-row justify-content-end">
77
+              <Button
78
+                label="Simpan"
79
+                icon="pi pi-check"
80
+                class="p-button-outlined"
81
+                :disabled="form.processing"
82
+                @click="onSubmit"
83
+              />
84
+            </div>
85
+          </template>
86
+        </Card>
87
+      </div>
88
+    </div>
89
+  </DashboardLayout>
90
+</template>

+ 77
- 2
resources/js/pages/Customers/Index.vue Ver fichero

1
 <script setup>
1
 <script setup>
2
+import { watch } from 'vue'
3
+import { Inertia } from '@inertiajs/inertia'
2
 import { Head } from '@inertiajs/inertia-vue3'
4
 import { Head } from '@inertiajs/inertia-vue3'
5
+import { pickBy } from 'lodash'
6
+import tableHeader from './tableHeader'
7
+import { useSearchText } from '@/components/useSearchText'
3
 import DashboardLayout from '@/layouts/DashboardLayout.vue'
8
 import DashboardLayout from '@/layouts/DashboardLayout.vue'
9
+import AppButtonLink from '@/components/AppButtonLink.vue'
10
+import AppPagination from '@/components/AppPagination.vue'
11
+
12
+const props = defineProps({
13
+  customers: Object,
14
+  initialSearch: String,
15
+})
16
+
17
+const { search } = useSearchText(props)
18
+
19
+watch(search, () => {
20
+  Inertia.get('/customers', pickBy({ search: search.value }), {
21
+    preserveState: true,
22
+  })
23
+})
4
 </script>
24
 </script>
5
 
25
 
6
 <template>
26
 <template>
7
-  <Head title="Halaman Pelangan" />
27
+  <Head title="Daftar User" />
28
+
29
+  <DashboardLayout>
30
+    <DataTable
31
+      responsiveLayout="scroll"
32
+      columnResizeMode="expand"
33
+      :value="customers.data"
34
+      :rowHover="true"
35
+      :stripedRows="true"
36
+    >
37
+      <template #header>
38
+        <h1>Pelanggan</h1>
39
+
40
+        <div class="grid">
41
+          <div class="col-12 md:col-8">
42
+            <div class="flex align-items-center">
43
+              <InputText
44
+                class="w-full md:w-27rem"
45
+                placeholder="cari, contoh: tina, 08xx, 0x"
46
+                v-model="search"
47
+              />
48
+            </div>
49
+          </div>
50
+
51
+          <div
52
+            class="col-12 md:col-4 flex flex-column md:flex-row justify-content-end"
53
+          >
54
+            <AppButtonLink
55
+              label="Tambah User"
56
+              icon="pi pi-pencil"
57
+              class="p-button-outlined"
58
+              :href="route('customers.create')"
59
+            />
60
+          </div>
61
+        </div>
62
+      </template>
63
+
64
+      <Column
65
+        v-for="value in tableHeader"
66
+        :field="value.field"
67
+        :header="value.header"
68
+        :key="value.field"
69
+      />
70
+
71
+      <Column>
72
+        <template #body="{ data }">
73
+          <AppButtonLink
74
+            icon="pi pi-pencil"
75
+            class="p-button-icon-only p-button-rounded p-button-text"
76
+            v-tooltip.bottom="'Ubah User'"
77
+            :href="route('customers.edit', data.id)"
78
+          />
79
+        </template>
80
+      </Column>
81
+    </DataTable>
8
 
82
 
9
-  <DashboardLayout> Halaman Pelangan </DashboardLayout>
83
+    <AppPagination :links="customers.links" />
84
+  </DashboardLayout>
10
 </template>
85
 </template>

+ 6
- 0
resources/js/pages/Customers/tableHeader.js Ver fichero

1
+export default [
2
+  { field: 'name', header: 'Nama' },
3
+  { field: 'address', header: 'Alamat' },
4
+  { field: 'phone', header: 'No HP' },
5
+  { field: 'npwp', header: 'NPWP' },
6
+]