diff --git a/frontend/src/components/posts/PostCard.vue b/frontend/src/components/posts/PostCard.vue index cd1c2aa..c38c6da 100644 --- a/frontend/src/components/posts/PostCard.vue +++ b/frontend/src/components/posts/PostCard.vue @@ -15,6 +15,7 @@ · {{ totalImages }} image{{ totalImages === 1 ? '' : 's' }} + + + Series + + + + + New series from this post + + + + Add to existing series… + + + + + + + Add to series + +

+ Appends this post as the next chapter of the chosen series. +

+ +
+ + + Cancel + Add + +
+
+
+ + + diff --git a/frontend/src/router.js b/frontend/src/router.js index 9a6a05d..2073c84 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -4,6 +4,7 @@ import GalleryView from './views/GalleryView.vue' import ShowcaseView from './views/ShowcaseView.vue' import TagsView from './views/TagsView.vue' import ArtistView from './views/ArtistView.vue' +import SeriesView from './views/SeriesView.vue' import SeriesManageView from './views/SeriesManageView.vue' import SeriesReaderView from './views/SeriesReaderView.vue' import SubscriptionsView from './views/SubscriptionsView.vue' @@ -25,7 +26,9 @@ const routes = [ { path: '/tags', name: 'tags', component: TagsView, meta: { title: 'Tags' } }, // Artist detail — no meta.title (reached by clicking an artist, not nav). { path: '/artist/:slug', name: 'artist', component: ArtistView }, - // Series management — no meta.title (reached from a series tag card). + // Series browse — a nav entry (meta.title). Peer of Posts. + { path: '/series', name: 'series', component: SeriesView, meta: { title: 'Series' } }, + // Series management — no meta.title (reached from a series card/tag). { path: '/series/:tagId', name: 'series-manage', component: SeriesManageView }, // Series reader — immersive (no top nav, no meta.title). { path: '/series/:tagId/read', name: 'series-read', component: SeriesReaderView, meta: { immersive: true } }, diff --git a/frontend/src/stores/seriesBrowse.js b/frontend/src/stores/seriesBrowse.js new file mode 100644 index 0000000..adb796c --- /dev/null +++ b/frontend/src/stores/seriesBrowse.js @@ -0,0 +1,31 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { useApi } from '../composables/useApi.js' +import { useAsyncAction } from '../composables/useAsyncAction.js' + +// Backs the Series browse view (FC-6.2). list_series returns every series as a +// card; homelab scale is small enough to load the whole list and sort/filter +// server-side. +export const useSeriesBrowseStore = defineStore('seriesBrowse', () => { + const api = useApi() + const series = ref([]) + const sort = ref('recent') + const artistId = ref(null) + const { loading, error, run } = useAsyncAction({ errorAs: 'message' }) + + async function load() { + await run(async () => { + const params = { sort: sort.value } + if (artistId.value != null) params.artist_id = artistId.value + const body = await api.get('/api/series', { params }) + series.value = body.series || [] + }) + } + + function setSort(s) { + sort.value = s + return load() + } + + return { series, sort, artistId, loading, error, load, setSort } +}) diff --git a/frontend/src/views/SeriesView.vue b/frontend/src/views/SeriesView.vue new file mode 100644 index 0000000..c135848 --- /dev/null +++ b/frontend/src/views/SeriesView.vue @@ -0,0 +1,145 @@ + + + + +