diff --git a/frontend/src/components/modal/FandomPicker.vue b/frontend/src/components/modal/FandomPicker.vue new file mode 100644 index 0000000..31189ab --- /dev/null +++ b/frontend/src/components/modal/FandomPicker.vue @@ -0,0 +1,48 @@ + + + diff --git a/frontend/src/components/modal/TagAutocomplete.vue b/frontend/src/components/modal/TagAutocomplete.vue new file mode 100644 index 0000000..cdc81ce --- /dev/null +++ b/frontend/src/components/modal/TagAutocomplete.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/frontend/src/stores/tags.js b/frontend/src/stores/tags.js new file mode 100644 index 0000000..fbb871a --- /dev/null +++ b/frontend/src/stores/tags.js @@ -0,0 +1,58 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { useApi } from '../composables/useApi.js' + +const KIND_OPTIONS = [ + { value: 'general', label: 'General', icon: 'mdi-tag' }, + { value: 'artist', label: 'Artist', icon: 'mdi-palette' }, + { value: 'character', label: 'Character', icon: 'mdi-account-circle' }, + { value: 'fandom', label: 'Fandom', icon: 'mdi-book-open-page-variant' }, + { value: 'series', label: 'Series', icon: 'mdi-bookshelf' }, + { value: 'meta', label: 'Meta', icon: 'mdi-cog-outline' }, + { value: 'rating', label: 'Rating', icon: 'mdi-shield-check-outline' } +] + +const KIND_COLOR = { + artist: 'accent', + character: 'info', + fandom: 'secondary', + series: 'warning', + general: 'on-surface', + meta: 'on-surface', + rating: 'on-surface', + archive: 'on-surface', + post: 'on-surface' +} + +export const useTagStore = defineStore('tags', () => { + const api = useApi() + const fandomCache = ref([]) + + async function autocomplete(q, kind = null, limit = 20) { + if (!q || !q.trim()) return [] + const params = { q, limit } + if (kind) params.kind = kind + return await api.get('/api/tags/autocomplete', { params }) + } + + async function loadFandoms() { + fandomCache.value = await api.get('/api/tags/autocomplete', { + params: { q: ' ', kind: 'fandom', limit: 200 } + }) + return fandomCache.value + } + + async function createFandom(name) { + const fandom = await api.post('/api/tags', { body: { name, kind: 'fandom' } }) + fandomCache.value = [...fandomCache.value, { + id: fandom.id, name: fandom.name, kind: 'fandom', + fandom_id: null, fandom_name: null, image_count: 0 + }] + return fandom + } + + function kindOptions() { return KIND_OPTIONS } + function colorFor(kind) { return KIND_COLOR[kind] || 'on-surface' } + + return { fandomCache, autocomplete, loadFandoms, createFandom, kindOptions, colorFor } +})