9e262cc5f0
Completes FC-6.2 with the UI. - PostSeriesMenu: a "Series ▾" control on each post card — "New series from this post" (promote → navigates to manage) and "Add to existing series…" (dialog with a browsable picker loaded from GET /api/series, client-side filtered — avoids the empty-autocomplete #712 trap). - SeriesView (/series): a top-level Series browse grid — cover, name, artist, chapter/page counts, gap badge; sort recent|name|size; cards → manage/read. meta.title adds it to the nav automatically (peer of Posts). - seriesBrowse store for the list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
32 lines
1016 B
JavaScript
32 lines
1016 B
JavaScript
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 }
|
|
})
|