search/app/composables/usePublicationFetch.ts

113 lines
3.2 KiB
TypeScript

import { ref } from 'vue'
import type { SearchHit } from '~/types'
interface ParagraphDoc {
id?: string
document_id: string
text: string
raw?: string
number: number
locale: string
type: string
}
export interface TypesenseParagraphHit {
document: ParagraphDoc
highlights?: unknown[]
highlight?: Record<string, unknown>
}
export interface DocumentDoc {
id?: string
code: string
locale: string
type: string
title: string
timestamp: number
date: string
place?: string
city?: string
state?: string
country?: string
thumbnail?: string
files?: { youtube?: string; video?: string; audio?: string; booklet?: string; simple?: string }
slug?: string
body?: string
draft?: boolean
[key: string]: unknown
}
// Maps the favorites/history collection name → Typesense main + paragraphs collections.
const COLLECTION_CONFIG: Record<string, { main: string; paragraphs: string }> = {
'bible-studies-ts': { main: 'activities', paragraphs: 'activities_paragraphs' },
'conferences-ts': { main: 'conferences', paragraphs: 'conferences_paragraphs' },
}
export function usePublicationFetch() {
const detailDocument = ref<DocumentDoc | null>(null)
const detailDocumentLoading = ref(false)
const detailParagraphs = ref<TypesenseParagraphHit[]>([])
const detailParagraphsLoading = ref(false)
const { documentsApi } = useTypesenseApi()
async function fetchDetail(hit: SearchHit, favoritesCollection: string) {
const config = COLLECTION_CONFIG[favoritesCollection]
const docId = String(hit._id || hit.id || '')
if (!config || !docId) {
detailDocument.value = null
detailParagraphs.value = []
return
}
detailDocumentLoading.value = true
detailParagraphsLoading.value = true
detailDocument.value = null
detailParagraphs.value = []
try {
const res = await documentsApi.multiSearch({
multiSearchParameters: {},
multiSearchSearchesParameter: {
searches: [{
collection: config.main,
q: '*',
queryBy: 'title',
filterBy: `id:=${docId} && $${config.paragraphs}(id: *)`,
includeFields: `*, $${config.paragraphs}(*)`
}]
}
})
const docHit = (res?.results?.[0] as { hits?: Array<{ document: Record<string, unknown> }> })?.hits?.[0]
if (docHit) {
const docRaw = { ...docHit.document }
const rawParagraphs = (docRaw[config.paragraphs] as ParagraphDoc[] | undefined) ?? []
delete docRaw[config.paragraphs]
detailDocument.value = docRaw as unknown as DocumentDoc
detailParagraphs.value = [...rawParagraphs]
.sort((a, b) => (a.number ?? 0) - (b.number ?? 0))
.map(p => ({ document: p }))
}
} catch (err) {
console.error('[usePublicationFetch] Error fetching publication detail', err)
detailDocument.value = null
detailParagraphs.value = []
} finally {
detailDocumentLoading.value = false
detailParagraphsLoading.value = false
}
}
function clearDetail() {
detailDocument.value = null
detailParagraphs.value = []
}
return {
detailDocument,
detailDocumentLoading,
detailParagraphs,
detailParagraphsLoading,
fetchDetail,
clearDetail,
}
}