Browse Source

feat: search menu by name

bregsiaju 1 year ago
parent
commit
448b392ea2
3 changed files with 43 additions and 24 deletions
  1. 11
    3
      src/components/MenuContainer.vue
  2. 8
    9
      src/components/NavBar.vue
  3. 24
    12
      src/stores/menus.js

+ 11
- 3
src/components/MenuContainer.vue View File

2
   <div class="pb-4">
2
   <div class="pb-4">
3
     <h5 class="mb-3">Menu</h5>
3
     <h5 class="mb-3">Menu</h5>
4
     <p v-if="loading">Loading menu ...</p>
4
     <p v-if="loading">Loading menu ...</p>
5
-    <p v-if="error">{{ error.message }}</p>
6
-    <div v-if="menus" class="row g-4 row-cols-lg-3">
5
+    <div v-if="menus.length === 0 || filteredMenus.length === 0" class="row g-4 row-cols-lg-3">
6
+      <p class="w-100 text-center">Menu yang dicari tidak ditemukan.</p>
7
+    </div>
8
+    <div v-else-if="isFilter || isSearch" class="row g-4 row-cols-lg-3">
9
+      <div v-for="menu in filteredMenus" :key="menu.id" class="col">
10
+        <CardMenu :data="menu" />
11
+      </div>
12
+    </div>
13
+    <div v-else-if="menus" class="row g-4 row-cols-lg-3">
7
       <div v-for="menu in menus" :key="menu.id" class="col">
14
       <div v-for="menu in menus" :key="menu.id" class="col">
8
         <CardMenu :data="menu" />
15
         <CardMenu :data="menu" />
9
       </div>
16
       </div>
10
     </div>
17
     </div>
18
+
11
   </div>
19
   </div>
12
 </template>
20
 </template>
13
 
21
 
16
 import { storeToRefs } from 'pinia'
24
 import { storeToRefs } from 'pinia'
17
 import { useMenuStore } from '../stores/menus'
25
 import { useMenuStore } from '../stores/menus'
18
 
26
 
19
-const { menus, loading, error } = storeToRefs(useMenuStore())
27
+const { menus, filteredMenus, isFilter, isSearch, loading } = storeToRefs(useMenuStore())
20
 const { fetchMenus } = useMenuStore()
28
 const { fetchMenus } = useMenuStore()
21
 
29
 
22
 fetchMenus()
30
 fetchMenus()

+ 8
- 9
src/components/NavBar.vue View File

6
       </div>
6
       </div>
7
       <div class="header-right container d-flex justify-content-between align-items-center flex-fill">
7
       <div class="header-right container d-flex justify-content-between align-items-center flex-fill">
8
         <!-- search box -->
8
         <!-- search box -->
9
-        <form class="d-flex position-relative" role="search">
10
-          <input class="form-control" type="search" placeholder="Search menu" aria-label="Search" name="search">
9
+        <form class="d-flex position-relative" role="search" @submit.prevent="searchMenu(search)">
10
+          <input class="form-control" type="search" placeholder="Search menu" aria-label="Search" v-model="search"
11
+            required>
11
           <Icon icon="mdi:search" class="text-dark-purple icon-search" height="24"></Icon>
12
           <Icon icon="mdi:search" class="text-dark-purple icon-search" height="24"></Icon>
12
         </form>
13
         </form>
13
         <div class="profil d-flex align-items-center gap-4">
14
         <div class="profil d-flex align-items-center gap-4">
31
   </nav>
32
   </nav>
32
 </template>
33
 </template>
33
 
34
 
34
-<script>
35
+<script setup>
35
 import { Icon } from '@iconify/vue';
36
 import { Icon } from '@iconify/vue';
37
+import { ref } from 'vue';
38
+import { useMenuStore } from '../stores/menus';
36
 
39
 
37
-export default {
38
-  name: 'NavBar',
39
-  components: {
40
-    Icon
41
-  }
42
-}
40
+const search = ref('')
41
+const { searchMenu } = useMenuStore()
43
 </script>
42
 </script>
44
 
43
 
45
 <style>
44
 <style>

+ 24
- 12
src/stores/menus.js View File

3
 export const useMenuStore = defineStore('menus', {
3
 export const useMenuStore = defineStore('menus', {
4
   state: () => ({
4
   state: () => ({
5
     menus: [],
5
     menus: [],
6
+    filteredMenus: [],
7
+    isFilter: false,
8
+    isSearch: false,
6
     loading: false,
9
     loading: false,
7
     error: null
10
     error: null
8
   }),
11
   }),
9
   actions: {
12
   actions: {
10
     async fetchMenus() {
13
     async fetchMenus() {
11
-      this.menus = []
12
-      this.loading = true
13
-      try {
14
-        this.menus = await fetch('menu.json').then((response) => response.json())
15
-      } catch (error) {
16
-        this.error = error
17
-      } finally {
18
-        this.loading = false
14
+      if (this.menus.length === 0) {
15
+        this.loading = true
16
+        try {
17
+          const response = await fetch('menu.json')
18
+          this.menus = await response.json()
19
+        } catch (error) {
20
+          this.error = error
21
+        } finally {
22
+          this.loading = false
23
+        }
19
       }
24
       }
20
     },
25
     },
21
     async getMenuPerCategory(categoryName) {
26
     async getMenuPerCategory(categoryName) {
27
+      this.isFilter = true
22
       await this.fetchMenus()
28
       await this.fetchMenus()
23
       console.log('nama kategori ' + categoryName)
29
       console.log('nama kategori ' + categoryName)
24
 
30
 
25
       if (categoryName !== 'all') {
31
       if (categoryName !== 'all') {
26
-        const filteredCategory = this.menus.filter((item) => item.category === categoryName)
27
-        console.log(filteredCategory)
28
-        this.menus = filteredCategory
32
+        this.filteredMenus = this.menus.filter((item) => item.category === categoryName)
33
+        console.log(this.filteredMenus)
29
       } else {
34
       } else {
30
-        await this.fetchMenus()
35
+        this.filteredMenus = this.menus
31
       }
36
       }
37
+    },
38
+    async searchMenu(keyword) {
39
+      this.isSearch = true
40
+      await this.fetchMenus()
41
+      this.filteredMenus = this.menus.filter((menu) => menu.name.toLowerCase().includes(keyword))
42
+      console.log(keyword)
43
+      console.log(this.filteredMenus)
32
     }
44
     }
33
   }
45
   }
34
 })
46
 })

Loading…
Cancel
Save