refactor: amélioration de la Sidebar.vue avec suppression de MenuItem.vue et mise à jour de MenuGroup.vue pour une gestion simplifiée des éléments de menu

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-03-26 20:25:33 +01:00
parent 53365df456
commit eeb8447d7a
3 changed files with 29 additions and 88 deletions

View File

@@ -9,22 +9,12 @@
<nav class="h-full overflow-y-auto"> <nav class="h-full overflow-y-auto">
<ul class="h-full flex flex-col"> <ul class="h-full flex flex-col">
<li v-for="(item, index) in menuItems" :key="index" class="mb-2"> <li v-for="(item, index) in menuItems" :key="index" class="mb-2">
<template v-if="item.id"> <MenuGroup
<MenuGroup :id="item.id"
:id="item.id"
:icon="item.icon"
:text="item.text"
:sub-items="item.subItems"
:is-active="isActive(item)"
:to="item.to" />
</template>
<MenuItem
v-else
:icon="item.icon" :icon="item.icon"
:text="item.text" :text="item.text"
:to="item.to" :sub-items="item.subItems"
:is-active="isActiveRoute(item.to)" :to="item.to" />
:badge="item.badge" />
</li> </li>
</ul> </ul>
</nav> </nav>
@@ -43,8 +33,7 @@
ClockIcon, ClockIcon,
Cog6ToothIcon, Cog6ToothIcon,
ComputerDesktopIcon ComputerDesktopIcon
} from '@heroicons/vue/24/outline'; } from '@heroicons/vue/24/solid';
import MenuItem from './sidebar/MenuItem.vue';
import MenuGroup from './sidebar/MenuGroup.vue'; import MenuGroup from './sidebar/MenuGroup.vue';
const route = useRoute(); const route = useRoute();
@@ -55,22 +44,6 @@
} }
}); });
const isActiveRoute = path => {
return route.path === path;
};
const isActive = item => {
if (!item.to) {
return item.subItems?.some(subItem => route.path === subItem.to) || false;
}
if (item.to === '/') {
return route.path === '/' || ['/add', '/import', '/discover'].includes(route.path);
}
return route.path.startsWith(item.to);
};
const menuItems = [ const menuItems = [
{ {
icon: BookOpenIcon, icon: BookOpenIcon,
@@ -90,17 +63,20 @@
{ {
icon: ArrowsRightLeftIcon, icon: ArrowsRightLeftIcon,
text: 'Convertir CBR en CBZ', text: 'Convertir CBR en CBZ',
to: '/convert' to: '/convert',
id: 'convert'
}, },
{ {
icon: CalendarIcon, icon: CalendarIcon,
text: 'Calendrier', text: 'Calendrier',
to: '/calendar' to: '/calendar',
id: 'calendar'
}, },
{ {
icon: ClockIcon, icon: ClockIcon,
text: 'Activité', text: 'Activité',
to: '/activity', to: '/activity',
id: 'activity',
badge: '3' badge: '3'
}, },
{ {

View File

@@ -14,9 +14,12 @@
}"> }">
<div class="flex items-center flex-grow"> <div class="flex items-center flex-grow">
<component :is="icon" class="w-5 h-5 mr-3" /> <component :is="icon" class="w-5 h-5 mr-3" />
<span>{{ text }}</span> <span class="px-2">{{ text }}</span>
</div> </div>
<component :is="expanded ? ChevronUpIcon : ChevronDownIcon" class="w-4 h-4" /> <component
v-if="subItems.length > 0"
:is="expanded ? ChevronUpIcon : ChevronDownIcon"
class="w-4 h-4" />
</RouterLink> </RouterLink>
</div> </div>
@@ -32,7 +35,7 @@
</template> </template>
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch, computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/vue/24/outline'; import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/vue/24/outline';
import SubMenuItem from './SubMenuItem.vue'; import SubMenuItem from './SubMenuItem.vue';
@@ -58,10 +61,6 @@
subItems: { subItems: {
type: Array, type: Array,
default: () => [] default: () => []
},
isActive: {
type: Boolean,
required: true
} }
}); });
@@ -69,6 +68,19 @@
const expanded = ref(false); const expanded = ref(false);
const route = useRoute(); const route = useRoute();
const isActive = computed(() => {
if (!props.to) {
return props.subItems?.some(subItem => route.path === subItem.to) || false;
}
if (props.to === '/') {
return route.path === props.to || props.subItems.map(item => item.to).includes(route.path);
}
return route.path.startsWith(props.to);
});
const isRouteMatching = path => { const isRouteMatching = path => {
return props.subItems.some(item => path.startsWith(item.to)) || path === props.to; return props.subItems.some(item => path.startsWith(item.to)) || path === props.to;
}; };

View File

@@ -1,47 +0,0 @@
<template>
<RouterLink :to="to" class="block px-4 py-2 hover:bg-gray-700 border-l-4 border-transparent" role="menuitem">
<div class="flex items-center justify-between">
<div class="flex items-center">
<component :is="icon" class="w-5 h-5 mr-3" aria-hidden="true" />
<span>{{ text }}</span>
</div>
<span
v-if="badge"
class="bg-green-500 text-white text-xs px-2 py-1 rounded-full"
aria-label="Nouveaux éléments: {{ badge }}">
{{ badge }}
</span>
</div>
</RouterLink>
</template>
<script setup>
defineProps({
icon: {
type: Function,
required: true
},
text: {
type: String,
required: true
},
to: {
type: String,
required: true
},
isActive: {
type: Boolean,
required: true
},
badge: {
type: String,
default: null
}
});
</script>
<style lang="postcss" scoped>
.router-link-active {
@apply text-green-600 bg-gray-800 border-green-600;
}
</style>