feat(home): toolbar filtre/affichage et modale options d'affichage
- Correction du dropdown toolbar : prop align (left/right) pour éviter le débordement hors écran côté droit - Filtre de collection par statut (all/completed/ongoing) persisté dans userPreferencesStore - toolbarConfig rendu réactif (computed) avec isSelected sur Filter, Sort et View - Modale Options d'affichage par vue (Grille, Overview, Table) avec toggles persistés - Composant ToggleRow réutilisable - Normalisation author → authors dans l'entité Manga (l'API renvoie author string)
This commit is contained in:
parent
214f470e77
commit
e525c9b7bd
@@ -3,12 +3,13 @@
|
||||
<Toolbar :config="toolbarConfig" />
|
||||
<div class="overflow-y-auto flex-1">
|
||||
<div class="w-full">
|
||||
<MangaGrid v-if="viewMode === 'grid'" :mangas="pagedItems" />
|
||||
<MangaGrid v-if="viewMode === 'grid'" :mangas="pagedItems" :options="prefs.displayOptions.grid" />
|
||||
<MangaOverview
|
||||
v-else-if="viewMode === 'list'"
|
||||
:mangas="pagedItems"
|
||||
:options="prefs.displayOptions.overview"
|
||||
@manga-click="handleMangaClick" />
|
||||
<MangaTable v-else-if="viewMode === 'table'" :mangas="pagedItems" />
|
||||
<MangaTable v-else-if="viewMode === 'table'" :mangas="pagedItems" :options="prefs.displayOptions.table" />
|
||||
<Pagination
|
||||
v-if="totalPages > 1"
|
||||
:current-page="currentPage"
|
||||
@@ -25,6 +26,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<HomeDisplaySettingsModal
|
||||
:is-open="isDisplaySettingsOpen"
|
||||
:options="prefs.displayOptions"
|
||||
@close="isDisplaySettingsOpen = false"
|
||||
@update="({ view, key, value }) => prefs.setDisplayOption(view, key, value)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -44,6 +51,7 @@ import { useUserPreferencesStore } from '../../../../domain/setting/application/
|
||||
import Pagination from '../../../../shared/components/ui/Pagination.vue';
|
||||
import Toolbar from '../../../../shared/components/ui/Toolbar.vue';
|
||||
import { useMangaStore } from '../../application/store/mangaStore';
|
||||
import HomeDisplaySettingsModal from '../components/HomeDisplaySettingsModal.vue';
|
||||
import MangaGrid from '../components/MangaGrid.vue';
|
||||
import MangaOverview from '../components/MangaOverview.vue';
|
||||
import MangaTable from '../components/MangaTable.vue';
|
||||
@@ -61,6 +69,7 @@ import MangaTable from '../components/MangaTable.vue';
|
||||
|
||||
const viewMode = ref(prefs.defaultView);
|
||||
const currentPage = ref(1);
|
||||
const isDisplaySettingsOpen = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
mangaStore.loadCollection();
|
||||
@@ -71,7 +80,12 @@ import MangaTable from '../components/MangaTable.vue';
|
||||
};
|
||||
|
||||
const sortedCollection = computed(() => {
|
||||
const items = [...(collection.value?.items || [])];
|
||||
let items = [...(collection.value?.items || [])];
|
||||
if (prefs.filterBy === 'completed') {
|
||||
items = items.filter(m => m.status?.toLowerCase() === 'completed');
|
||||
} else if (prefs.filterBy === 'ongoing') {
|
||||
items = items.filter(m => m.status?.toLowerCase() === 'ongoing');
|
||||
}
|
||||
if (prefs.sortBy === 'title') {
|
||||
items.sort((a, b) => a.title.localeCompare(b.title));
|
||||
} else if (prefs.sortBy === 'addedAt') {
|
||||
@@ -91,7 +105,7 @@ import MangaTable from '../components/MangaTable.vue';
|
||||
currentPage.value = 1;
|
||||
});
|
||||
|
||||
const toolbarConfig = {
|
||||
const toolbarConfig = computed(() => ({
|
||||
leftSection: [
|
||||
{
|
||||
icon: ArrowPathIcon,
|
||||
@@ -103,15 +117,15 @@ import MangaTable from '../components/MangaTable.vue';
|
||||
{ icon: MagnifyingGlassIcon, label: 'Search', type: 'button', onClick: () => {} }
|
||||
],
|
||||
rightSection: [
|
||||
{ icon: Cog6ToothIcon, type: 'button', onClick: () => {} },
|
||||
{ icon: Cog6ToothIcon, label: 'Options', type: 'button', onClick: () => { isDisplaySettingsOpen.value = true; } },
|
||||
{
|
||||
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'); } }
|
||||
{ label: 'Overview', isSelected: prefs.defaultView === 'list', onClick: () => { viewMode.value = 'list'; prefs.setDefaultView('list'); } },
|
||||
{ label: 'Grid', isSelected: prefs.defaultView === 'grid', onClick: () => { viewMode.value = 'grid'; prefs.setDefaultView('grid'); } },
|
||||
{ label: 'Table', isSelected: prefs.defaultView === 'table', onClick: () => { viewMode.value = 'table'; prefs.setDefaultView('table'); } }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -119,9 +133,9 @@ import MangaTable from '../components/MangaTable.vue';
|
||||
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') }
|
||||
{ label: 'Title', isSelected: prefs.sortBy === 'title', onClick: () => prefs.setSortBy('title') },
|
||||
{ label: "Date d'ajout", isSelected: prefs.sortBy === 'addedAt', onClick: () => prefs.setSortBy('addedAt') },
|
||||
{ label: 'Progression', isSelected: prefs.sortBy === 'progress', onClick: () => prefs.setSortBy('progress') }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -129,11 +143,11 @@ import MangaTable from '../components/MangaTable.vue';
|
||||
type: 'dropdown',
|
||||
label: 'Filter',
|
||||
items: [
|
||||
{ label: 'All', onClick: () => {} },
|
||||
{ label: 'Completed', onClick: () => {} },
|
||||
{ label: 'In Progress', onClick: () => {} }
|
||||
{ label: 'All', isSelected: prefs.filterBy === 'all', onClick: () => prefs.setFilterBy('all') },
|
||||
{ label: 'Completed', isSelected: prefs.filterBy === 'completed', onClick: () => prefs.setFilterBy('completed') },
|
||||
{ label: 'In Progress', isSelected: prefs.filterBy === 'ongoing', onClick: () => prefs.setFilterBy('ongoing') }
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}));
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user