ソースを参照

feat: outlet master

コミット
bb70c73c60

+ 115
- 0
app/Http/Controllers/OutletController.php ファイルの表示

@@ -0,0 +1,115 @@
1
+<?php
2
+
3
+namespace App\Http\Controllers;
4
+
5
+use App\Http\Controllers\Controller;
6
+use App\Http\Requests\Outlet\StoreOutletRequest;
7
+use App\Http\Requests\Outlet\UpdateOutletRequest;
8
+use App\Models\Outlet;
9
+
10
+class OutletController extends Controller
11
+{
12
+    /**
13
+     * Display a listing of the resource.
14
+     *
15
+     * @return \Inertia\Response
16
+     */
17
+    public function index()
18
+    {
19
+        return inertia('outlet/Index', [
20
+            'outlets' => Outlet::latest()
21
+                ->filter(request()->search)
22
+                ->paginate(10)
23
+                ->withQueryString()
24
+                ->through(fn($outlet) => [
25
+                    'id' => $outlet->id,
26
+                    'outlet_number' => $outlet->outlet_number,
27
+                    'name' => $outlet->name,
28
+                    'phone' => $outlet->phone,
29
+                    'address' => $outlet->address,
30
+                ]),
31
+        ]);
32
+    }
33
+
34
+    /**
35
+     * Show the form for creating a new resource.
36
+     *
37
+     * @return \Inertia\Response
38
+     */
39
+    public function create()
40
+    {
41
+        return inertia('outlet/Create', [
42
+            'outlet_number' => 'OT' . now()->format('YmdHis'),
43
+        ]);
44
+    }
45
+
46
+    /**
47
+     * Store a newly created resource in storage.
48
+     *
49
+     * @param  \Illuminate\Http\Request  $request
50
+     * @return \Illuminate\Http\Response
51
+     */
52
+    public function store(StoreOutletRequest $request)
53
+    {
54
+        Outlet::create($request->validated());
55
+
56
+        return to_route('outlets.index')->with('success', __('messages.success.store.outlet'));
57
+    }
58
+
59
+    /**
60
+     * Display the specified resource.
61
+     *
62
+     * @param  int  $id
63
+     * @return \Inertia\Response
64
+     */
65
+    public function show($id)
66
+    {
67
+        //
68
+    }
69
+
70
+    /**
71
+     * Show the form for editing the specified resource.
72
+     *
73
+     * @param  Outlet  $outlet
74
+     * @return \Inertia\Response
75
+     */
76
+    public function edit(Outlet $outlet)
77
+    {
78
+        return inertia('outlet/Edit', [
79
+            'outlet' => [
80
+                'id' => $outlet->id,
81
+                'outlet_number' => $outlet->outlet_number,
82
+                'name' => $outlet->name,
83
+                'phone' => $outlet->phone,
84
+                'address' => $outlet->address,
85
+            ],
86
+        ]);
87
+    }
88
+
89
+    /**
90
+     * Update the specified resource in storage.
91
+     *
92
+     * @param  \Illuminate\Http\Request  $request
93
+     * @param  Outlet  $outlet
94
+     * @return \Illuminate\Http\Response
95
+     */
96
+    public function update(UpdateOutletRequest $request, Outlet $outlet)
97
+    {
98
+        $outlet->update($request->validated());
99
+
100
+        return back()->with('success', __('messages.success.update.outlet'));
101
+    }
102
+
103
+    /**
104
+     * Remove the specified resource from storage.
105
+     *
106
+     * @param  Outlet  $Outlet
107
+     * @return \Illuminate\Http\Response
108
+     */
109
+    public function destroy(Outlet $outlet)
110
+    {
111
+        $outlet->delete();
112
+
113
+        return to_route('outlets.index')->with('success', __('messages.success.destroy.outlet'));
114
+    }
115
+}

+ 33
- 0
app/Http/Requests/Outlet/StoreOutletRequest.php ファイルの表示

@@ -0,0 +1,33 @@
1
+<?php
2
+
3
+namespace App\Http\Requests\Outlet;
4
+
5
+use Illuminate\Foundation\Http\FormRequest;
6
+
7
+class StoreOutletRequest 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
23
+     */
24
+    public function rules()
25
+    {
26
+        return [
27
+            'outlet_number' => 'required|string',
28
+            'name' => 'required|string|max:50',
29
+            'phone' => 'required|numeric|min:12|unique:users,phone',
30
+            'address' => 'required|string|max:100',
31
+        ];
32
+    }
33
+}

+ 33
- 0
app/Http/Requests/Outlet/UpdateOutletRequest.php ファイルの表示

@@ -0,0 +1,33 @@
1
+<?php
2
+
3
+namespace App\Http\Requests\Outlet;
4
+
5
+use Illuminate\Foundation\Http\FormRequest;
6
+
7
+class UpdateOutletRequest 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
23
+     */
24
+    public function rules()
25
+    {
26
+        return [
27
+            'outlet_number' => 'required|string|unique:outlets,outlet_number,' . $this->outlet->id,
28
+            'name' => 'required|string|max:50',
29
+            'phone' => 'required|numeric|min:12|unique:outlets,phone,' . $this->outlet->id,
30
+            'address' => 'required|string|max:100',
31
+        ];
32
+    }
33
+}

+ 13
- 1
app/Models/Outlet.php ファイルの表示

@@ -12,7 +12,19 @@ class Outlet extends Model
12 12
     protected $fillable = [
13 13
         'outlet_number',
14 14
         'name',
15
-        'address',
16 15
         'phone',
16
+        'address',
17 17
     ];
18
+
19
+    public function scopeFilter($query, $search)
20
+    {
21
+        $query->when($search ?? null, function ($query, $search) {
22
+            $query->where(function ($query) use ($search) {
23
+                $query->where('outlet_number', 'like', '%' . $search . '%')
24
+                    ->orWhere('name', 'like', '%' . $search . '%')
25
+                    ->orWhere('phone', 'like', '%' . $search . '%')
26
+                    ->orWhere('address', 'like', '%' . $search . '%');
27
+            });
28
+        });
29
+    }
18 30
 }

+ 3
- 0
lang/id/messages.php ファイルの表示

@@ -24,14 +24,17 @@ return [
24 24
         'store' => [
25 25
             'user' => 'Akun user berhasil ditambahkan',
26 26
             'customer' => 'Akun customer berhasil ditambahkan',
27
+            'outlet' => 'Data outlet berhasil ditambahkan',
27 28
         ],
28 29
         'update' => [
29 30
             'user' => 'Akun user berhasil diubah',
30 31
             'customer' => 'Akun customer berhasil diubah',
32
+            'outlet' => 'Data outlet berhasil diubah',
31 33
         ],
32 34
         'destroy' => [
33 35
             'user' => 'Akun user berhasil dihapus',
34 36
             'customer' => 'Akun customer berhasil dihapus',
37
+            'outlet' => 'Data outlet berhasil dihapus',
35 38
         ],
36 39
     ],
37 40
 

+ 1934
- 0
public/js/resources_js_pages_outlet_Create_vue.js
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 2344
- 0
public/js/resources_js_pages_outlet_Edit_vue.js
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 2172
- 0
public/js/resources_js_pages_outlet_Index_vue.js
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 25
- 1
public/js/vue.js ファイルの表示

@@ -36083,6 +36083,30 @@ var map = {
36083 36083
 		"./resources/js/pages/customer/Index.vue",
36084 36084
 		"resources_js_pages_customer_Index_vue"
36085 36085
 	],
36086
+	"./outlet/Create": [
36087
+		"./resources/js/pages/outlet/Create.vue",
36088
+		"resources_js_pages_outlet_Create_vue"
36089
+	],
36090
+	"./outlet/Create.vue": [
36091
+		"./resources/js/pages/outlet/Create.vue",
36092
+		"resources_js_pages_outlet_Create_vue"
36093
+	],
36094
+	"./outlet/Edit": [
36095
+		"./resources/js/pages/outlet/Edit.vue",
36096
+		"resources_js_pages_outlet_Edit_vue"
36097
+	],
36098
+	"./outlet/Edit.vue": [
36099
+		"./resources/js/pages/outlet/Edit.vue",
36100
+		"resources_js_pages_outlet_Edit_vue"
36101
+	],
36102
+	"./outlet/Index": [
36103
+		"./resources/js/pages/outlet/Index.vue",
36104
+		"resources_js_pages_outlet_Index_vue"
36105
+	],
36106
+	"./outlet/Index.vue": [
36107
+		"./resources/js/pages/outlet/Index.vue",
36108
+		"resources_js_pages_outlet_Index_vue"
36109
+	],
36086 36110
 	"./user/Create": [
36087 36111
 		"./resources/js/pages/user/Create.vue",
36088 36112
 		"resources_js_pages_user_Create_vue"
@@ -36224,7 +36248,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
36224 36248
 /******/ 		// This function allow to reference async chunks
36225 36249
 /******/ 		__webpack_require__.u = (chunkId) => {
36226 36250
 /******/ 			// return url for filenames based on template
36227
-/******/ 			return "js/" + chunkId + ".js?id=" + {"resources_js_pages_auth_ForgotPassword_vue":"70818f45cbbab151","resources_js_pages_auth_Login_vue":"c4cf6fd873885e8f","resources_js_pages_auth_ResetPassword_vue":"adb7b3ce1defe237","resources_js_pages_auth_VerifyEmail_vue":"766e409b18e8e260","resources_js_pages_customer_Create_vue":"043463d47e5a7d20","resources_js_pages_customer_Edit_vue":"ad87bcdaff2e284c","resources_js_pages_customer_Index_vue":"c9964211a38d2db5","resources_js_pages_user_Create_vue":"c40384f40ba5a089","resources_js_pages_user_Edit_vue":"a880111a8912f84c","resources_js_pages_user_Index_vue":"62f17f79119649c8"}[chunkId] + "";
36251
+/******/ 			return "js/" + chunkId + ".js?id=" + {"resources_js_pages_auth_ForgotPassword_vue":"70818f45cbbab151","resources_js_pages_auth_Login_vue":"c4cf6fd873885e8f","resources_js_pages_auth_ResetPassword_vue":"adb7b3ce1defe237","resources_js_pages_auth_VerifyEmail_vue":"766e409b18e8e260","resources_js_pages_customer_Create_vue":"043463d47e5a7d20","resources_js_pages_customer_Edit_vue":"ad87bcdaff2e284c","resources_js_pages_customer_Index_vue":"c9964211a38d2db5","resources_js_pages_outlet_Create_vue":"610831f5d05c5c2f","resources_js_pages_outlet_Edit_vue":"fb9c21c755b35f2b","resources_js_pages_outlet_Index_vue":"84c5671f63445ef0","resources_js_pages_user_Create_vue":"c40384f40ba5a089","resources_js_pages_user_Edit_vue":"a880111a8912f84c","resources_js_pages_user_Index_vue":"62f17f79119649c8"}[chunkId] + "";
36228 36252
 /******/ 		};
36229 36253
 /******/ 	})();
36230 36254
 /******/ 	

+ 64
- 0
resources/js/pages/outlet/Create.vue ファイルの表示

@@ -0,0 +1,64 @@
1
+<script setup>
2
+import { Head, useForm } from '@inertiajs/inertia-vue3'
3
+
4
+import AppButtonCreate from '@/components/AppButtonCreate.vue'
5
+import AppTextInput from '@/components/AppTextInput.vue'
6
+import DefaultLayout from '@/layouts/DefaultLayout.vue'
7
+
8
+const props = defineProps({
9
+  outlet_number: String,
10
+})
11
+
12
+const form = useForm({
13
+  outlet_number: props.outlet_number,
14
+  name: '',
15
+  phone: '',
16
+  address: '',
17
+})
18
+
19
+const submit = () => {
20
+  form.post(route('outlets.store'))
21
+}
22
+</script>
23
+
24
+<template>
25
+  <Head title="Tambah Outlet" />
26
+
27
+  <DefaultLayout>
28
+    <CRow>
29
+      <CCol md="8">
30
+        <CCard color="light" class="border-light">
31
+          <CForm @submit.prevent="submit">
32
+            <CRow class="p-4">
33
+              <CCol md="6" class="mb-4">
34
+                <CFormLabel>Id Outlet</CFormLabel>
35
+                <CFormInput disabled v-model="form.outlet_number" />
36
+              </CCol>
37
+
38
+              <CCol md="6" class="mb-4">
39
+                <AppTextInput label="Nama" placeholder="nama" :error="form.errors.name" v-model="form.name" />
40
+              </CCol>
41
+
42
+              <CCol md="6" class="mb-4">
43
+                <AppTextInput label="Nomor HP" placeholder="nomor hp" :error="form.errors.phone" v-model="form.phone" />
44
+              </CCol>
45
+
46
+              <CCol md="6" class="mb-4">
47
+                <AppTextInput
48
+                  label="Address"
49
+                  placeholder="address"
50
+                  :error="form.errors.address"
51
+                  v-model="form.address"
52
+                />
53
+              </CCol>
54
+            </CRow>
55
+
56
+            <CCardFooter class="d-flex justify-content-end">
57
+              <AppButtonCreate :disabled="form.processing">Tambah Outlet</AppButtonCreate>
58
+            </CCardFooter>
59
+          </CForm>
60
+        </CCard>
61
+      </CCol>
62
+    </CRow>
63
+  </DefaultLayout>
64
+</template>

+ 77
- 0
resources/js/pages/outlet/Edit.vue ファイルの表示

@@ -0,0 +1,77 @@
1
+<script setup>
2
+import { Head, useForm } from '@inertiajs/inertia-vue3'
3
+
4
+import AppTextInput from '@/components/AppTextInput.vue'
5
+import AppButtonCreate from '@/components/AppButtonCreate.vue'
6
+import AppButtonDelete from '@/components/AppButtonDelete.vue'
7
+import AppButtonAction from '@/components/AppButtonAction.vue'
8
+import AppModalAlert from '@/components/AppModalAlert.vue'
9
+import DefaultLayout from '@/layouts/DefaultLayout.vue'
10
+
11
+const props = defineProps({
12
+  outlet: Object,
13
+})
14
+
15
+const form = useForm({
16
+  outlet_number: props.outlet.outlet_number,
17
+  name: props.outlet.name,
18
+  phone: props.outlet.phone,
19
+  address: props.outlet.address,
20
+})
21
+
22
+const submit = () => {
23
+  form.put(route('outlets.update', props.outlet.id))
24
+}
25
+</script>
26
+
27
+<template>
28
+  <Head title="Ubah Customer" />
29
+
30
+  <DefaultLayout v-slot="{ toggleModalAlert }">
31
+    <CRow>
32
+      <CCol md="8">
33
+        <CCard color="light" class="border-light">
34
+          <CForm @submit.prevent="submit">
35
+            <CRow class="p-4">
36
+              <CCol md="6" class="mb-4">
37
+                <CFormLabel>Id Outlet</CFormLabel>
38
+                <CFormInput disabled v-model="form.outlet_number" />
39
+              </CCol>
40
+
41
+              <CCol md="6" class="mb-4">
42
+                <AppTextInput label="Nama" placeholder="nama" :error="form.errors.name" v-model="form.name" />
43
+              </CCol>
44
+
45
+              <CCol md="6" class="mb-4">
46
+                <AppTextInput label="Nomor HP" placeholder="nomor hp" :error="form.errors.phone" v-model="form.phone" />
47
+              </CCol>
48
+
49
+              <CCol md="6" class="mb-4">
50
+                <AppTextInput
51
+                  label="Address"
52
+                  placeholder="address"
53
+                  :error="form.errors.address"
54
+                  v-model="form.address"
55
+                />
56
+              </CCol>
57
+            </CRow>
58
+
59
+            <CCardFooter class="d-flex justify-content-between">
60
+              <AppButtonAction @click="toggleModalAlert">Hapus Outlet</AppButtonAction>
61
+
62
+              <AppModalAlert>
63
+                Anda yakin ingin mengahapus outlet ini?
64
+
65
+                <template #footer>
66
+                  <AppButtonDelete :href="route('outlets.destroy', outlet.id)">Hapus Outlet</AppButtonDelete>
67
+                </template>
68
+              </AppModalAlert>
69
+
70
+              <AppButtonCreate :disabled="form.processing">Ubah Outlet</AppButtonCreate>
71
+            </CCardFooter>
72
+          </CForm>
73
+        </CCard>
74
+      </CCol>
75
+    </CRow>
76
+  </DefaultLayout>
77
+</template>

+ 57
- 0
resources/js/pages/outlet/Index.vue ファイルの表示

@@ -0,0 +1,57 @@
1
+<script setup>
2
+import { Head } from '@inertiajs/inertia-vue3'
3
+
4
+import AppTable from '@/components/AppTable.vue'
5
+import AppButtonMove from '@/components/AppButtonMove.vue'
6
+import AppButtonDetail from '@/components/AppButtonDetail.vue'
7
+import AppPagination from '@/components/AppPagination.vue'
8
+import DefaultLayout from '@/layouts/DefaultLayout.vue'
9
+
10
+defineProps({
11
+  outlets: Object,
12
+})
13
+</script>
14
+
15
+<template>
16
+  <Head title="Daftar Outlet" />
17
+
18
+  <DefaultLayout>
19
+    <CRow class="mb-4">
20
+      <CCol></CCol>
21
+
22
+      <CCol xs="auto">
23
+        <AppButtonMove :href="route('outlets.create')">Tambah Outlet</AppButtonMove>
24
+      </CCol>
25
+    </CRow>
26
+
27
+    <CRow>
28
+      <CCol>
29
+        <AppTable>
30
+          <template #table-head>
31
+            <CTableRow>
32
+              <CTableHeaderCell>Id Outlet</CTableHeaderCell>
33
+              <CTableHeaderCell>Nama</CTableHeaderCell>
34
+              <CTableHeaderCell>HP</CTableHeaderCell>
35
+              <CTableHeaderCell>Alamat</CTableHeaderCell>
36
+            </CTableRow>
37
+          </template>
38
+          <template #table-body>
39
+            <CTableRow v-for="outlet in outlets.data" :key="outlet.id">
40
+              <CTableDataCell>{{ outlet.outlet_number }}</CTableDataCell>
41
+              <CTableDataCell>{{ outlet.name }}</CTableDataCell>
42
+              <CTableDataCell>{{ outlet.phone }}</CTableDataCell>
43
+              <CTableDataCell>{{ outlet.address }}</CTableDataCell>
44
+              <CTableDataCell>
45
+                <AppButtonDetail :href="route('outlets.edit', outlet.id)" />
46
+              </CTableDataCell>
47
+            </CTableRow>
48
+          </template>
49
+        </AppTable>
50
+      </CCol>
51
+    </CRow>
52
+
53
+    <CRow>
54
+      <AppPagination :links="outlets.links" />
55
+    </CRow>
56
+  </DefaultLayout>
57
+</template>

+ 3
- 0
routes/web.php ファイルの表示

@@ -1,6 +1,7 @@
1 1
 <?php
2 2
 
3 3
 use App\Http\Controllers\CustomerController;
4
+use App\Http\Controllers\OutletController;
4 5
 use App\Http\Controllers\UserController;
5 6
 use Illuminate\Support\Facades\Route;
6 7
 
@@ -24,6 +25,8 @@ Route::middleware(['auth'])->group(function () {
24 25
     Route::resource('/users', UserController::class);
25 26
 
26 27
     Route::resource('/customers', CustomerController::class);
28
+
29
+    Route::resource('/outlets', OutletController::class);
27 30
 });
28 31
 
29 32
 require __DIR__ . '/auth.php';