Files
FabledCurator/frontend/src/stores/seriesBrowse.js
T
bvandeusen e4cebf70d1
CI / lint (push) Successful in 2s
CI / backend-lint-and-test (push) Successful in 26s
CI / frontend-build (push) Successful in 49s
CI / integration (push) Successful in 3m13s
feat(series): browse search + per-card kebab (rename/delete)
The Series browse tab had no way to find a series in a long grid and no
per-series actions. Add a search field (instant client-side name/artist filter
over the already-loaded list) and a kebab on each card with Rename (reuses
TagRenameDialog → PATCH /api/tags/<id>, with its collision-merge flow) and
Delete (confirm dialog → DELETE /api/admin/tags/<id>; series_page/chapter/
suggestion cascade, images kept). Gap badge moved to the cover's top-left so the
kebab can sit top-right. Operator-asked 2026-06-09.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 18:56:45 -04:00

49 lines
1.6 KiB
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()
}
// A series IS a Tag(kind=series); deleting it removes the series structure
// (pages/chapters cascade) via the shared admin tag-delete. Splice the card
// out for instant feedback rather than reloading the whole grid.
async function remove(id) {
await api.delete(`/api/admin/tags/${id}`)
series.value = series.value.filter(s => s.id !== id)
}
// Reflect an in-place rename (PATCH /api/tags/<id>) without a full reload.
function applyRename(id, name) {
const row = series.value.find(s => s.id === id)
if (row) row.name = name
}
return {
series, sort, artistId, loading, error,
load, setSort, remove, applyRename,
}
})