Skip to content

Commit

Permalink
Fix: AppMenu Search Enhanced for larger amount of Items.
Browse files Browse the repository at this point in the history
Fix: Created dedicated component for dashboard card
  • Loading branch information
mehedijaman committed Nov 2, 2024
1 parent 01edec0 commit 7b3f6fe
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 60 deletions.
44 changes: 32 additions & 12 deletions stubs/resources/js/Components/Menu/AppMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
</template>

<script setup>
import { ref } from 'vue'
import { computed } from 'vue'
import { ref, computed } from 'vue'
const props = defineProps({
items: {
Expand All @@ -49,19 +48,40 @@ const searchTerm = ref('')
// Computed property to filter items based on search term
const filteredItems = computed(() => {
if (!searchTerm.value) return props.items
const searchFilter = (item) => {
// Convert search term to lowercase for case-insensitive matching
const term = searchTerm.value.toLowerCase()
const term = searchTerm.value.toLowerCase()
// Check if the label or any child item contains the search term
const matches = (i) =>
i.label?.toLowerCase().includes(term) ||
(i.children && i.children.some(matches)) // Recursively check children
// Recursive function to filter items and their children
const filterItems = (items) => {
return items.reduce((acc, item) => {
const isParentMatch = item.label.toLowerCase().includes(term)
let filteredChildren = []
return matches(item)
if (item.children) {
if (isParentMatch) {
// If parent matches, include all children
filteredChildren = item.children
} else {
// Else, filter children based on search term
filteredChildren = filterItems(item.children)
}
}
// Include the item if the parent matches or any of its children match
if (
isParentMatch ||
(filteredChildren && filteredChildren.length)
) {
acc.push({
...item,
// If parent matches, include all children; else, include filtered children
children: isParentMatch ? item.children : filteredChildren
})
}
return acc
}, [])
}
// Filter items recursively
return props.items.filter(searchFilter)
return filterItems(props.items)
})
</script>
45 changes: 45 additions & 0 deletions stubs/resources/js/Pages/Dashboard/Components/DashboardCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<div
class="shadow-xs flex items-center rounded-lg border border-skin-neutral-4 bg-skin-neutral-2 p-4 hover:cursor-pointer hover:bg-skin-neutral-1"
@click="$inertia.visit(route(link))"
>
<div
class="mr-4 rounded-full bg-green-100 px-3 py-2 text-green-500 dark:bg-green-500 dark:text-green-100"
>
<i :class="icon" class="text-2xl"></i>
</div>
<div>
<p class="mb-2 text-sm font-medium">
{{ label }}
</p>
<p class="text-lg font-semibold">
{{ count }}
</p>
</div>
</div>
</template>

<script setup>
import useAuthCan from '@/Composables/useAuthCan'
defineProps({
link: {
type: String,
default: null
},
count: {
type: String,
default: null
},
label: {
type: String,
default: null
},
icon: {
type: String,
default: null
}
})
const { can } = useAuthCan()
</script>
67 changes: 19 additions & 48 deletions stubs/resources/js/Pages/Dashboard/DashboardIndex.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,67 +12,38 @@

<div class="my-6 grid grid-cols-1 gap-6 md:grid-cols-3">
<!-- User Count Card -->
<div
class="shadow-xs flex items-center rounded-lg border border-skin-neutral-4 bg-skin-neutral-2 p-4 hover:cursor-pointer hover:bg-skin-neutral-1"
@click="$inertia.visit(route('user.index'))"
<DashboardCard
v-if="can('Acl')"
>
<div
class="mr-4 rounded-full bg-green-100 px-3 py-2 text-green-500 dark:bg-green-500 dark:text-green-100"
>
<i class="ri-user-fill text-2xl"></i>
</div>
<div>
<p class="mb-2 text-sm font-medium">Users</p>
<p class="text-lg font-semibold">
{{ props.count['users'] }}
</p>
</div>
</div>
link="user.index"
label="Users"
:count="props.count['users']"
icon="ri-user-fill"
></DashboardCard>

<!-- Role Count Card -->
<div
class="shadow-xs flex items-center rounded-lg border border-skin-neutral-4 bg-skin-neutral-2 p-4 hover:cursor-pointer hover:bg-skin-neutral-1"
@click="$inertia.visit(route('aclRole.index'))"
<DashboardCard
v-if="can('Acl')"
>
<div
class="mr-4 rounded-full bg-blue-100 px-3 py-2 text-blue-500 dark:bg-blue-500 dark:text-blue-100"
>
<i class="ri-user-settings-line text-2xl"></i>
</div>
<div>
<p class="mb-2 text-sm font-medium">Roles</p>
<p class="text-lg font-semibold">
{{ props.count['roles'] }}
</p>
</div>
</div>
link="aclRole.index"
label="Roles"
:count="props.count['roles']"
icon="ri-user-settings-line"
></DashboardCard>

<!-- Permission Count Card -->
<div
class="shadow-xs flex items-center rounded-lg border border-skin-neutral-4 bg-skin-neutral-2 p-4 hover:cursor-pointer hover:bg-skin-neutral-1"
@click="$inertia.visit(route('aclPermission.index'))"
<DashboardCard
v-if="can('Acl')"
>
<div
class="mr-4 rounded-full bg-orange-100 px-3 py-2 text-orange-500 dark:bg-orange-500 dark:text-orange-100"
>
<i class="ri-key-fill text-2xl"></i>
</div>
<div>
<p class="mb-2 text-sm font-medium">Permissions</p>
<p class="text-lg font-semibold">
{{ props.count['permissions'] }}
</p>
</div>
</div>
link="aclPermission.index"
label="Permissions"
:count="props.count['permissions']"
icon="ri-key-fill"
></DashboardCard>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Head } from '@inertiajs/vue3'
import useAuthCan from '@/Composables/useAuthCan'
import DashboardCard from '@/Pages/Dashboard/Components/DashboardCard.vue'
const { can } = useAuthCan()
Expand Down

0 comments on commit 7b3f6fe

Please sign in to comment.