diff --git a/frontend/src/stores/posts.js b/frontend/src/stores/posts.js new file mode 100644 index 0000000..d5b18c7 --- /dev/null +++ b/frontend/src/stores/posts.js @@ -0,0 +1,64 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { useApi } from '../composables/useApi.js' + +export const usePostsStore = defineStore('posts', () => { + const api = useApi() + + const items = ref([]) + const cursor = ref(null) + const loading = ref(false) + const done = ref(false) + const error = ref(null) + const filters = ref({ artist_id: null, platform: null }) + + function _qs() { + const q = {} + if (cursor.value) q.cursor = cursor.value + if (filters.value.artist_id != null) q.artist_id = filters.value.artist_id + if (filters.value.platform) q.platform = filters.value.platform + return q + } + + function _reset() { + items.value = [] + cursor.value = null + done.value = false + error.value = null + } + + async function loadInitial(newFilters) { + filters.value = { + artist_id: newFilters?.artist_id ?? null, + platform: newFilters?.platform ?? null, + } + _reset() + await loadMore() + } + + async function loadMore() { + if (loading.value || done.value) return + loading.value = true + error.value = null + try { + const body = await api.get('/api/posts', { params: _qs() }) + items.value.push(...body.items) + cursor.value = body.next_cursor + if (body.next_cursor == null) done.value = true + } catch (e) { + error.value = e + } finally { + loading.value = false + } + } + + async function getPostFull(id) { + // Used by PostCard's "Show more" expand to fetch the full description. + return await api.get(`/api/posts/${id}`) + } + + return { + items, cursor, loading, done, error, filters, + loadInitial, loadMore, getPostFull, + } +})