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:
parent
fcfbf140a3
commit
68fed587be
@@ -4,6 +4,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="currentManga" class="relative">
|
<div v-else-if="currentManga" class="relative">
|
||||||
|
<Toolbar :config="toolbarConfig" />
|
||||||
|
|
||||||
<div v-if="isRefreshingDetails" class="absolute top-2 right-2 text-gray-500">
|
<div v-if="isRefreshingDetails" class="absolute top-2 right-2 text-gray-500">
|
||||||
<ArrowPathIcon class="h-5 w-5 animate-spin" />
|
<ArrowPathIcon class="h-5 w-5 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
@@ -31,7 +33,16 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onUnmounted, watch } from 'vue';
|
import { computed, onUnmounted, watch } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
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 { useMangaDetails } from '../composables/useMangaDetails';
|
||||||
import { useMangaVolumes } from '../composables/useMangaVolumes';
|
import { useMangaVolumes } from '../composables/useMangaVolumes';
|
||||||
@@ -40,6 +51,7 @@
|
|||||||
import MangaVolumeList from '../components/MangaVolumeList.vue';
|
import MangaVolumeList from '../components/MangaVolumeList.vue';
|
||||||
|
|
||||||
import { useMangaStore } from '../../application/store/mangaStore';
|
import { useMangaStore } from '../../application/store/mangaStore';
|
||||||
|
import Toolbar from '../../../../shared/components/ui/Toolbar.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const mangaStore = useMangaStore();
|
const mangaStore = useMangaStore();
|
||||||
@@ -60,6 +72,61 @@
|
|||||||
error: errorVolumes
|
error: errorVolumes
|
||||||
} = useMangaVolumes(mangaId);
|
} = 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 loading = computed(() => isLoadingDetails.value || isLoadingVolumes.value);
|
||||||
const isRefreshing = computed(() => isRefreshingDetails.value || isRefreshingVolumes.value);
|
const isRefreshing = computed(() => isRefreshingDetails.value || isRefreshingVolumes.value);
|
||||||
const error = computed(() => errorDetails.value || errorVolumes.value);
|
const error = computed(() => errorDetails.value || errorVolumes.value);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<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>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="['bg-gray-800 p-3 min-h-14', $attrs.class]">
|
<div :class="['bg-gray-800 h-[4.5rem] p-3', $attrs.class]">
|
||||||
<div class="flex flex-row items-center justify-between">
|
<div class="flex flex-row items-center justify-between h-full">
|
||||||
<!-- Left section -->
|
<!-- Left section -->
|
||||||
<ToolbarSection :items="config.leftSection" />
|
<ToolbarSection :items="config.leftSection" />
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,20 @@
|
|||||||
<button
|
<button
|
||||||
@click="$emit('click')"
|
@click="$emit('click')"
|
||||||
:class="[
|
: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
|
active
|
||||||
? 'text-green-500' // Style actif
|
? 'text-green-500' // Style actif
|
||||||
: 'hover:text-green-500' // Effet de survol
|
: 'hover:text-green-500' // Effet de survol
|
||||||
]"
|
]"
|
||||||
:aria-label="label || 'Toolbar button'">
|
:aria-label="label || 'Toolbar button'">
|
||||||
<component v-if="icon" :is="icon" class="h-6 w-6 mb-1" />
|
<component v-if="icon" :is="icon" class="h-6 w-6" />
|
||||||
<span v-if="label" class="text-xs">{{ label }}</span>
|
<ToolbarLabel :label="label" />
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import ToolbarLabel from './ToolbarLabel.vue';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
icon: {
|
icon: {
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<Menu as="div" class="relative inline-block">
|
<Menu as="div" class="relative inline-block h-full">
|
||||||
<div>
|
<div class="h-full">
|
||||||
<MenuButton
|
<MenuButton
|
||||||
:class="[
|
: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' : ''
|
active ? 'text-green-500' : ''
|
||||||
]"
|
]"
|
||||||
:aria-label="label || 'Options'">
|
:aria-label="label || 'Options'">
|
||||||
<component v-if="icon" :is="icon" class="h-6 w-6 mb-1" aria-hidden="true" />
|
<component v-if="icon" :is="icon" class="h-6 w-6" aria-hidden="true" />
|
||||||
<span v-if="label" class="text-xs truncate w-full px-1">{{ label }}</span>
|
<ToolbarLabel :label="label" />
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue';
|
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue';
|
||||||
|
import ToolbarLabel from './ToolbarLabel.vue';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
icon: {
|
icon: {
|
||||||
|
|||||||
13
assets/vue/app/shared/components/ui/ToolbarLabel.vue
Normal file
13
assets/vue/app/shared/components/ui/ToolbarLabel.vue
Normal 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>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<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">
|
<template v-for="(item, index) in items" :key="index">
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
v-if="item.type === 'button'"
|
v-if="item.type === 'button'"
|
||||||
|
|||||||
Reference in New Issue
Block a user