Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | 2x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 18x 12x 12x 12x 12x 12x 12x 6x 1x 5x 12x 12x 12x 12x 1x 1x 1x 7x 6x 3x 2x 2x 2x 2x 2x 1x 1x 3x 3x 3x 3x 1x 1x 1x 2x 2x 2x 1x 1x 18x | import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import api from '@/services/api'
import type { Entity } from '@/stores/entities'
export interface CatalogResponse {
items: Entity[]
nextToken?: string
hasMore: boolean
filteredTotal: number
total: number
}
export const useCatalogStore = defineStore('catalog', () => {
const entities = ref<Entity[]>([])
const loading = ref(false)
const error = ref<string | null>(null)
const nextToken = ref<string | null>(null)
const hasMore = ref(false)
const total = ref(0)
const filteredTotal = ref(0)
const searchQuery = ref('')
let latestFetchRequestId = 0
let latestLoadMoreRequestId = 0
const isEmpty = computed(() => entities.value.length === 0 && !loading.value)
/**
* Fetch public entities catalog (reset pagination)
*/
async function fetchCatalog(search?: string) {
const requestId = ++latestFetchRequestId
loading.value = true
error.value = null
if (search !== undefined) searchQuery.value = search
try {
const response = await api.get<CatalogResponse>('/v1/catalog', {
params: {
limit: 30,
...(searchQuery.value && { search: searchQuery.value })
}
})
// A newer request has started: ignore stale response.
if (requestId !== latestFetchRequestId) {
return
}
entities.value = response.data.items || []
nextToken.value = response.data.nextToken || null
hasMore.value = response.data.hasMore
filteredTotal.value = response.data.filteredTotal ?? entities.value.length
total.value = response.data.total
} catch (err: any) {
Iif (requestId !== latestFetchRequestId) {
return
}
error.value = err.response?.data?.error || 'Failed to load catalog'
console.error('[catalog] Error:', err)
} finally {
if (requestId === latestFetchRequestId) {
loading.value = false
}
}
}
/**
* Load next page of results
*/
async function loadMore() {
if (!hasMore.value || loading.value || !nextToken.value) return
const requestId = ++latestLoadMoreRequestId
loading.value = true
error.value = null
try {
const response = await api.get<CatalogResponse>('/v1/catalog', {
params: {
limit: 30,
nextToken: nextToken.value,
...(searchQuery.value && { search: searchQuery.value })
}
})
// A newer loadMore request has started: ignore stale response.
Iif (requestId !== latestLoadMoreRequestId) {
return
}
entities.value.push(...(response.data.items || []))
nextToken.value = response.data.nextToken || null
hasMore.value = response.data.hasMore
filteredTotal.value = response.data.filteredTotal ?? filteredTotal.value
total.value = response.data.total ?? total.value
} catch (err: any) {
Iif (requestId !== latestLoadMoreRequestId) {
return
}
error.value = err.response?.data?.error || 'Failed to load more results'
console.error('[catalog] Load more error:', err)
} finally {
Eif (requestId === latestLoadMoreRequestId) {
loading.value = false
}
}
}
/**
* Update fork status locally after fork operation
*/
function markAsForked(entityId: string) {
const entity = entities.value.find((e) => e.id === entityId)
Eif (entity) {
entity.forkedByCurrentFlow = true
}
}
function markAsLinked(entityId: string) {
const entity = entities.value.find((e) => e.id === entityId)
if (entity) {
entity.linkedByCurrentFlow = true
}
}
return {
entities,
loading,
error,
hasMore,
filteredTotal,
total,
searchQuery,
isEmpty,
fetchCatalog,
loadMore,
markAsForked,
markAsLinked
}
})
|