All checks were successful
Deploy / deploy (push) Successful in 2m50s
Remplace les grandes cartes verbeux par des lignes compactes avec cover, titre (text-2xl), badge statut, résumé tronqué et 3 boutons d'action verticaux (éditer, sources, rafraîchir) — cohérent avec MangaTable. Archivage de la tâche [UI] Améliorer la vue Overview dans TASK.md.
140 lines
5.0 KiB
Vue
140 lines
5.0 KiB
Vue
<template>
|
|
<div class="flex flex-col h-full">
|
|
<Toolbar :config="toolbarConfig" />
|
|
<div class="overflow-y-auto flex-1">
|
|
<div class="w-full">
|
|
<MangaGrid v-if="viewMode === 'grid'" :mangas="pagedItems" />
|
|
<MangaOverview
|
|
v-else-if="viewMode === 'list'"
|
|
:mangas="pagedItems"
|
|
@manga-click="handleMangaClick" />
|
|
<MangaTable v-else-if="viewMode === 'table'" :mangas="pagedItems" />
|
|
<Pagination
|
|
v-if="totalPages > 1"
|
|
:current-page="currentPage"
|
|
:total-pages="totalPages"
|
|
:total="sortedCollection.length"
|
|
:limit="prefs.itemsPerPage"
|
|
:has-next-page="currentPage < totalPages"
|
|
:has-previous-page="currentPage > 1"
|
|
@page-change="currentPage = $event" />
|
|
<div
|
|
v-if="isBackgroundLoading"
|
|
class="fixed bottom-4 right-4 bg-gray-800 text-white px-4 py-2 rounded-lg shadow-lg">
|
|
Mise à jour en cours...
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {
|
|
ArrowPathIcon,
|
|
ArrowsUpDownIcon,
|
|
Cog6ToothIcon,
|
|
EyeIcon,
|
|
FunnelIcon,
|
|
MagnifyingGlassIcon
|
|
} from '@heroicons/vue/24/outline';
|
|
import { storeToRefs } from 'pinia';
|
|
import { computed, onMounted, ref, watch } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
import { useUserPreferencesStore } from '../../../../domain/setting/application/store/userPreferencesStore';
|
|
import Pagination from '../../../../shared/components/ui/Pagination.vue';
|
|
import Toolbar from '../../../../shared/components/ui/Toolbar.vue';
|
|
import { useMangaStore } from '../../application/store/mangaStore';
|
|
import MangaGrid from '../components/MangaGrid.vue';
|
|
import MangaOverview from '../components/MangaOverview.vue';
|
|
import MangaTable from '../components/MangaTable.vue';
|
|
|
|
const router = useRouter();
|
|
const mangaStore = useMangaStore();
|
|
const prefs = useUserPreferencesStore();
|
|
|
|
const {
|
|
collection,
|
|
loadingCollection: loading,
|
|
errorCollection: error,
|
|
isBackgroundLoadingCollection: isBackgroundLoading
|
|
} = storeToRefs(mangaStore);
|
|
|
|
const viewMode = ref(prefs.defaultView);
|
|
const currentPage = ref(1);
|
|
|
|
onMounted(() => {
|
|
mangaStore.loadCollection();
|
|
});
|
|
|
|
const handleMangaClick = manga => {
|
|
router.push({ name: 'manga-details', params: { id: manga.id } });
|
|
};
|
|
|
|
const sortedCollection = computed(() => {
|
|
const items = [...(collection.value?.items || [])];
|
|
if (prefs.sortBy === 'title') {
|
|
items.sort((a, b) => a.title.localeCompare(b.title));
|
|
} else if (prefs.sortBy === 'addedAt') {
|
|
items.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
|
}
|
|
return items;
|
|
});
|
|
|
|
const pagedItems = computed(() => {
|
|
const start = (currentPage.value - 1) * prefs.itemsPerPage;
|
|
return sortedCollection.value.slice(start, start + prefs.itemsPerPage);
|
|
});
|
|
|
|
const totalPages = computed(() => Math.ceil(sortedCollection.value.length / prefs.itemsPerPage));
|
|
|
|
watch(() => prefs.itemsPerPage, () => {
|
|
currentPage.value = 1;
|
|
});
|
|
|
|
const toolbarConfig = {
|
|
leftSection: [
|
|
{
|
|
icon: ArrowPathIcon,
|
|
label: 'Refresh',
|
|
type: 'button',
|
|
onClick: () => mangaStore.refreshCollectionInBackground(),
|
|
active: isBackgroundLoading.value
|
|
},
|
|
{ icon: MagnifyingGlassIcon, label: 'Search', type: 'button', onClick: () => {} }
|
|
],
|
|
rightSection: [
|
|
{ icon: Cog6ToothIcon, type: 'button', onClick: () => {} },
|
|
{
|
|
icon: EyeIcon,
|
|
type: 'dropdown',
|
|
label: 'View',
|
|
items: [
|
|
{ label: 'Overview', onClick: () => { viewMode.value = 'list'; prefs.setDefaultView('list'); } },
|
|
{ label: 'Grid', onClick: () => { viewMode.value = 'grid'; prefs.setDefaultView('grid'); } },
|
|
{ label: 'Table', onClick: () => { viewMode.value = 'table'; prefs.setDefaultView('table'); } }
|
|
]
|
|
},
|
|
{
|
|
icon: ArrowsUpDownIcon,
|
|
type: 'dropdown',
|
|
label: 'Sort',
|
|
items: [
|
|
{ label: 'Title', onClick: () => prefs.setSortBy('title') },
|
|
{ label: "Date d'ajout", onClick: () => prefs.setSortBy('addedAt') },
|
|
{ label: 'Progression', onClick: () => prefs.setSortBy('progress') }
|
|
]
|
|
},
|
|
{
|
|
icon: FunnelIcon,
|
|
type: 'dropdown',
|
|
label: 'Filter',
|
|
items: [
|
|
{ label: 'All', onClick: () => {} },
|
|
{ label: 'Completed', onClick: () => {} },
|
|
{ label: 'In Progress', onClick: () => {} }
|
|
]
|
|
}
|
|
]
|
|
};
|
|
</script>
|