113 lines
3.2 KiB
TypeScript
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,
|
|
}
|
|
}
|