feat: ajout d'une barre d'outils dans le composant MangaDetails, intégration de nouveaux boutons avec des actions configurables, et amélioration de la structure des composants de la barre d'outils pour une meilleure expérience utilisateur.

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-04-03 15:15:18 +02:00
parent fcfbf140a3
commit 68fed587be
7 changed files with 95 additions and 13 deletions

View File

@@ -4,6 +4,8 @@
</div>
<div v-else-if="currentManga" class="relative">
<Toolbar :config="toolbarConfig" />
<div v-if="isRefreshingDetails" class="absolute top-2 right-2 text-gray-500">
<ArrowPathIcon class="h-5 w-5 animate-spin" />
</div>
@@ -31,7 +33,16 @@
<script setup>
import { computed, onUnmounted, watch } from 'vue';
import { useRoute } from 'vue-router';
import { ArrowPathIcon } from '@heroicons/vue/24/outline';
import {
ArrowPathIcon,
PencilSquareIcon,
DocumentArrowDownIcon,
Cog6ToothIcon,
BookmarkIcon,
WrenchIcon,
TrashIcon,
ChevronDoubleDownIcon
} from '@heroicons/vue/24/outline';
import { useMangaDetails } from '../composables/useMangaDetails';
import { useMangaVolumes } from '../composables/useMangaVolumes';
@@ -40,6 +51,7 @@
import MangaVolumeList from '../components/MangaVolumeList.vue';
import { useMangaStore } from '../../application/store/mangaStore';
import Toolbar from '../../../../shared/components/ui/Toolbar.vue';
const route = useRoute();
const mangaStore = useMangaStore();
@@ -60,6 +72,61 @@
error: errorVolumes
} = useMangaVolumes(mangaId);
const toolbarConfig = computed(() => ({
leftSection: [
{
icon: ArrowPathIcon,
label: 'Refresh metadata',
type: 'button',
onClick: () => console.log('Refresh metadata')
},
{
icon: PencilSquareIcon,
label: 'Rename chapters',
type: 'button',
onClick: () => console.log('Rename chapters')
},
{
icon: DocumentArrowDownIcon,
label: 'Manage cbz',
type: 'button',
onClick: () => console.log('Manage cbz')
},
{
icon: Cog6ToothIcon,
label: 'Preferred Sources',
type: 'button',
onClick: () => console.log('Preferred Sources')
}
],
rightSection: [
{
icon: BookmarkIcon,
label: 'Monitoring',
type: 'button',
onClick: () => console.log('Monitoring')
},
{
icon: WrenchIcon,
label: 'Edit',
type: 'button',
onClick: () => console.log('Edit')
},
{
icon: TrashIcon,
label: 'Delete',
type: 'button',
onClick: () => console.log('Delete')
},
{
icon: ChevronDoubleDownIcon,
label: 'Expand all',
type: 'button',
onClick: () => console.log('Expand all')
}
]
}));
const loading = computed(() => isLoadingDetails.value || isLoadingVolumes.value);
const isRefreshing = computed(() => isRefreshingDetails.value || isRefreshingVolumes.value);
const error = computed(() => errorDetails.value || errorVolumes.value);

View File

@@ -1,5 +1,5 @@
<template>
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
<div class="h-full mx-4 border-r opacity-50 border-green-500"></div>
</template>
<script setup>

View File

@@ -1,6 +1,6 @@
<template>
<div :class="['bg-gray-800 p-3 min-h-14', $attrs.class]">
<div class="flex flex-row items-center justify-between">
<div :class="['bg-gray-800 h-[4.5rem] p-3', $attrs.class]">
<div class="flex flex-row items-center justify-between h-full">
<!-- Left section -->
<ToolbarSection :items="config.leftSection" />

View File

@@ -2,19 +2,20 @@
<button
@click="$emit('click')"
:class="[
'flex flex-col items-center justify-center p-1 rounded group text-white min-w-[50px]',
'flex flex-col items-center justify-around h-full w-min p-1 rounded group text-white',
active
? 'text-green-500' // Style actif
: 'hover:text-green-500' // Effet de survol
]"
:aria-label="label || 'Toolbar button'">
<component v-if="icon" :is="icon" class="h-6 w-6 mb-1" />
<span v-if="label" class="text-xs">{{ label }}</span>
<component v-if="icon" :is="icon" class="h-6 w-6" />
<ToolbarLabel :label="label" />
</button>
</template>
<script setup>
import { computed } from 'vue';
import ToolbarLabel from './ToolbarLabel.vue';
defineProps({
icon: {

View File

@@ -1,14 +1,14 @@
<template>
<Menu as="div" class="relative inline-block">
<div>
<Menu as="div" class="relative inline-block h-full">
<div class="h-full">
<MenuButton
:class="[
'flex flex-col items-center justify-center p-1 rounded group text-white w-20 hover:text-green-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75',
'flex flex-col items-center justify-around h-full w-min p-1 rounded group text-white hover:text-green-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75',
active ? 'text-green-500' : ''
]"
:aria-label="label || 'Options'">
<component v-if="icon" :is="icon" class="h-6 w-6 mb-1" aria-hidden="true" />
<span v-if="label" class="text-xs truncate w-full px-1">{{ label }}</span>
<component v-if="icon" :is="icon" class="h-6 w-6" aria-hidden="true" />
<ToolbarLabel :label="label" />
</MenuButton>
</div>
@@ -33,6 +33,7 @@
<script setup>
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue';
import ToolbarLabel from './ToolbarLabel.vue';
defineProps({
icon: {

View File

@@ -0,0 +1,13 @@
<template>
<span v-if="label" class="text-xs line-clamp-2 max-w-fit px-1 text-center min-h-[2rem]">{{ label }}</span>
</template>
<script setup>
defineProps({
label: {
type: String,
required: false,
default: ''
}
});
</script>

View File

@@ -1,5 +1,5 @@
<template>
<div class="flex items-center space-x-2">
<div class="flex items-center space-x-2 h-full">
<template v-for="(item, index) in items" :key="index">
<ToolbarButton
v-if="item.type === 'button'"