Compare commits

..

No commits in common. "main" and "new-collections" have entirely different histories.

14 changed files with 42 additions and 162 deletions

View File

@ -66,8 +66,6 @@ const props = defineProps<{
selectedHit?: TypesenseParagraphHit | null
selectedMatchingHits?: TypesenseParagraphHit[] | null
accentColor?: 'green' | 'blue'
noTrackVisit?: boolean
author?: string
}>()
const emits = defineEmits(['close'])
@ -105,7 +103,7 @@ watch(
() => [props.collection, props.document?.id] as const,
([collection, id]) => {
if (!collection || !id || !props.document) return
if (!props.noTrackVisit) history.visit(collection, toSearchHit(props.document))
history.visit(collection, toSearchHit(props.document))
},
{ immediate: true }
)
@ -846,7 +844,7 @@ const items = computed(() => {
@click="toggleInternalSearch"
/>
</UTooltip>
<UTooltip text="¿Cómo funciona?">
<UTooltip text="Como funciona?">
<UButton
icon="ph-student"
color="neutral"
@ -886,10 +884,6 @@ const items = computed(() => {
<UIcon name="ph:file-dashed" class="size-4 text-carpared" />
{{ $t('search.draft') }}
</p>
<p v-if="author" class="text-sm text-highlighted flex items-center gap-1.5 shrink-0">
<UIcon name="ph:user-circle" :class="['size-4', iconColor]" />
<span class="italic">{{ author }}</span>
</p>
<p v-if="safeDate()" class="text-sm text-highlighted flex items-center gap-1.5 shrink-0">
<UIcon name="ph:calendar" :class="['size-4', iconColor]" />
{{ safeDate() }}

View File

@ -31,7 +31,6 @@ const props = defineProps<{
document: EntrelineaDoc
collection?: string
highlightedText?: string | null
noTrackVisit?: boolean
}>()
const emits = defineEmits<{ close: [] }>()
@ -105,7 +104,7 @@ watch(
() => [props.collection, props.document?.id] as const,
([collection, id]) => {
if (!collection || !id) return
if (!props.noTrackVisit) history.visit(collection, toSearchHit(props.document))
history.visit(collection, toSearchHit(props.document))
},
{ immediate: true }
)

View File

@ -14,12 +14,10 @@ interface Props {
accentColor: 'green' | 'blue'
emptyDetailText: string
showDraft?: boolean
author?: string
}
const props = withDefaults(defineProps<Props>(), {
showDraft: false,
author: ''
showDraft: false
})
const QUERY_BY = 'text'
@ -142,7 +140,6 @@ const colors = computed(() => {
// ---- State ----------------------------------------------------------------
const exactSearch = ref(false)
const sortMode = ref<'relevance' | 'date'>('relevance')
const groupedHits = ref<SearchGroup[]>([])
const total = ref(0)
@ -257,8 +254,6 @@ async function runSearch(q: string, page = 1, append = false) {
const typePage = isInfinite ? (append ? currentPage.value + 1 : 1) : page
try {
const shouldSortByDate = sortMode.value === 'date' && q.trim()
const multi = await documentsApi.multiSearch({
multiSearchParameters: {},
multiSearchSearchesParameter: {
@ -267,7 +262,6 @@ async function runSearch(q: string, page = 1, append = false) {
q: exactSearch.value && q ? `"${q}"` : q || '*',
queryBy: QUERY_BY,
filterBy: filterBy.value,
...(shouldSortByDate ? { sortBy: `$${props.mainCollection}(timestamp:desc)` } : {}),
perPage: settings.pageSize,
page: typePage,
highlightFullFields: QUERY_BY,
@ -340,7 +334,7 @@ async function runBrowse(page = 1, append = false) {
collection: props.paragraphsCollection,
q: '*',
queryBy: QUERY_BY,
filterBy: `${filterBy.value} && $${props.mainCollection}(locale:=${locale.value})`,
filterBy: filterBy.value,
sortBy: `$${props.mainCollection}(timestamp:desc)`,
groupBy: props.groupByField,
perPage: settings.pageSize,
@ -349,6 +343,7 @@ async function runBrowse(page = 1, append = false) {
}]
}
})
console.log('Browse result', multi)
if (seq !== searchSeq) return
const result = (multi?.results?.[0] as TypesenseSearchResponse | undefined)
const rawGroups = result?.groupedHits ?? []
@ -433,15 +428,6 @@ watch(exactSearch, () => {
if (query.value.trim()) runSearch(query.value, 1, false)
})
watch(sortMode, () => {
if (query.value.trim()) {
groupedHits.value = []
total.value = 0
currentPage.value = 1
runSearch(query.value, 1, false)
}
})
// ---- Selección y carga del detalle ----------------------------------------
const selectedDocId = ref<string | null>(null)
@ -473,8 +459,7 @@ async function fetchDocumentWithParagraphs(docId: string) {
const hit = (res?.results?.[0] as { hits?: Array<{ document: Record<string, unknown> }> })?.hits?.[0]
if (hit) {
const docRaw = { ...hit.document }
const raw = docRaw[props.paragraphsCollection]
const rawParagraphs = Array.isArray(raw) ? raw : (raw ? [raw] : []) as ParagraphDoc[]
const rawParagraphs = (docRaw[props.paragraphsCollection] as ParagraphDoc[] | undefined) ?? []
delete docRaw[props.paragraphsCollection]
selectedDocument.value = docRaw as unknown as DocumentDoc
selectedParagraphs.value = [...rawParagraphs]
@ -597,14 +582,6 @@ function metaLocation(meta: DocMeta | undefined): string {
</template>
</UDashboardNavbar>
<div
v-if="author"
class="px-4 sm:px-6 py-2 border-b border-default flex items-center gap-1.5 text-xs text-muted"
>
<UIcon name="ph:user-circle" :class="['size-3.5 shrink-0', colors.icon]" />
<span class="italic">{{ author }}</span>
</div>
<div class="px-4 sm:px-6 py-3 border-b border-default flex items-center gap-2" id="inputField">
<UInput
v-model="query"
@ -630,18 +607,6 @@ function metaLocation(meta: DocMeta | undefined): string {
>{{ t('search.phrase') }}</button>
</div>
</div>
<div class="px-4 sm:px-6 py-3">
<USelect
v-if="query.trim()"
v-model="sortMode"
:items="[
{ label: t('search.sort.relevance'), value: 'relevance' },
{ label: t('search.sort.date'), value: 'date' }
]"
size="sm"
class="shrink-0 min-w-[130px]"
/>
</div>
<UAlert
v-if="errorMsg"
@ -750,7 +715,6 @@ function metaLocation(meta: DocMeta | undefined): string {
:selected-hit="selectedHit"
:selected-matching-hits="selectedMatchingHits"
:accent-color="accentColor"
:author="author"
@close="isPanelOpen = false"
/>
<div v-else-if="!isMobile" class="hidden lg:flex flex-1 items-center justify-center">
@ -775,7 +739,6 @@ function metaLocation(meta: DocMeta | undefined): string {
:selected-hit="selectedHit"
:selected-matching-hits="selectedMatchingHits"
:accent-color="accentColor"
:author="author"
@close="isPanelOpen = false"
/>
</template>

View File

@ -79,8 +79,7 @@ export function usePublicationFetch() {
const docHit = (res?.results?.[0] as { hits?: Array<{ document: Record<string, unknown> }> })?.hits?.[0]
if (docHit) {
const docRaw = { ...docHit.document }
const raw = docRaw[config.paragraphs]
const rawParagraphs = Array.isArray(raw) ? raw : (raw ? [raw] : []) as ParagraphDoc[]
const rawParagraphs = (docRaw[config.paragraphs] as ParagraphDoc[] | undefined) ?? []
delete docRaw[config.paragraphs]
detailDocument.value = docRaw as unknown as DocumentDoc
detailParagraphs.value = [...rawParagraphs]

View File

@ -22,9 +22,6 @@ const { total: favTotal } = storeToRefs(favorites)
const history = useHistoryStore()
const { total: histTotal } = storeToRefs(history)
const toCarpa = () => {
window.location.href = `https://carpa.com/${$i18n.locale.value}`;
}
const links = computed(() => {
const links = [
@ -121,9 +118,9 @@ const links = computed(() => {
class="bg-elevated/25 bg-gradient-to-tr from-blue-100 to-white" :ui="{ footer: 'lg:border-t lg:border-default' }">
<template #header="{ collapsed }">
<div v-if="!collapsed" class="mt-2 flex justify-center">
<img v-on:click="toCarpa" src="/logo.svg" class="w-full cursor-pointer" alt="Buscador - La Gran Carpa Catedral" />
<img src="/logo.svg" class="w-full" alt="Buscador - La Gran Carpa Catedral" />
</div>
<img v-if="collapsed" v-on:click="toCarpa" src="/logo_round.svg" class="w-full cursor-pointer" alt="Buscador - La Gran Carpa Catedral" />
<img v-if="collapsed" src="/logo_round.svg" class="w-full" alt="Buscador - La Gran Carpa Catedral" />
</template>
<template #default="{ collapsed }">

View File

@ -8,6 +8,5 @@
nav-title-key="nav.conferences_ts"
accent-color="blue"
:empty-detail-text="$t('ui.empty_conferences')"
author="Dr. William Soto Santiago"
/>
</template>

View File

@ -285,11 +285,6 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
<template #leading>
<UDashboardSidebarCollapse />
</template>
<template #trailing>
<UBadge :label="total" variant="subtle" :ui="{
base: 'total-results'
}" />
</template>
</UDashboardNavbar>
<!-- Banner: se muestra cuando NO hay clave de desarrollador -->

View File

@ -9,6 +9,5 @@
accent-color="green"
:empty-detail-text="$t('ui.empty_bible_studies')"
:show-draft="true"
author="Dr. José Benjamín Pérez Matos"
/>
</template>

View File

@ -30,28 +30,14 @@ const toast = useToast()
const ENTRELINEAS_COLLECTION = 'entrelineas'
const { t } = useI18n()
const COLLECTION_LABELS: Record<string, string> = {
activities: 'Actividades',
conferences: 'Conferencias',
entrelineas: 'Entre Líneas'
}
function labelFor(c: string): string {
const labels: Record<string, string> = {
activities: t('nav.bible_studies_ts'),
'bible-studies-ts': t('nav.bible_studies_ts'),
conferences: t('nav.conferences_ts'),
'conferences-ts': t('nav.conferences_ts'),
entrelineas: t('nav.between_the_lines'),
}
return labels[c] || c.charAt(0).toUpperCase() + c.slice(1)
}
const COLLECTION_AUTHORS: Record<string, string> = {
'bible-studies-ts': 'Dr. José Benjamín Pérez Matos',
activities: 'Dr. José Benjamín Pérez Matos',
'conferences-ts': 'Dr. William Soto Santiago',
conferences: 'Dr. William Soto Santiago',
}
function authorFor(c: string): string {
return COLLECTION_AUTHORS[c] || ''
return COLLECTION_LABELS[c] || c.charAt(0).toUpperCase() + c.slice(1)
}
// Filtros: pestaña por colección o "todos".
@ -71,9 +57,9 @@ const tabs = computed(() => {
items.push({
value: c,
label: `${labelFor(c)} (${count})`,
icon: (c === 'activities' || c === 'bible-studies-ts')
icon: c === 'activities'
? 'i-lucide-calendar-days'
: (c === 'conferences' || c === 'conferences-ts')
: c === 'conferences'
? 'i-lucide-mic'
: c === 'entrelineas'
? 'i-lucide-book-open'
@ -106,7 +92,6 @@ const selected = ref<HistoryItem | null>(null)
const selectedHit = computed<SearchHit | null>(() => selected.value?.hit ?? null)
const selectedCollection = computed<string | undefined>(() => selected.value?.collection)
const selectedAuthor = computed(() => authorFor(selectedCollection.value ?? ''))
const isEntrelinea = computed(() => selectedCollection.value === ENTRELINEAS_COLLECTION)
@ -567,13 +552,6 @@ const nearLimit = computed(() => histTotal.value >= Math.floor(HISTORY_LIMIT * 0
<span v-if="hasDate(it.hit)">{{ safeDate(it.hit) }}</span>
<USeparator v-if="formatLocation(it.hit)" orientation="vertical" class="h-3 hidden sm:block" />
<span class="truncate">{{ formatLocation(it.hit) }}</span>
<template v-if="authorFor(it.collection)">
<USeparator orientation="vertical" class="h-3 hidden sm:block" />
<span class="inline-flex items-center gap-1 italic truncate">
<UIcon name="ph:user-circle" class="size-3 shrink-0" />
{{ authorFor(it.collection) }}
</span>
</template>
</p>
</div>
</div>
@ -585,7 +563,6 @@ const nearLimit = computed(() => histTotal.value >= Math.floor(HISTORY_LIMIT * 0
v-if="selected && !isMobile && isEntrelinea"
:document="selectedEntrelineaDoc!"
:collection="selectedCollection"
no-track-visit
@close="selected = null"
/>
<!-- Resto (actividades, conferencias) detalle completo con párrafos. -->
@ -596,8 +573,6 @@ const nearLimit = computed(() => histTotal.value >= Math.floor(HISTORY_LIMIT * 0
:paragraphs="detailParagraphs"
:paragraphs-loading="detailParagraphsLoading"
:collection="selectedCollection!"
:author="selectedAuthor"
no-track-visit
@close="selected = null"
/>
<div v-else-if="!selected" class="hidden lg:flex flex-1 items-center justify-center">
@ -616,7 +591,6 @@ const nearLimit = computed(() => histTotal.value >= Math.floor(HISTORY_LIMIT * 0
v-if="selected && isEntrelinea"
:document="selectedEntrelineaDoc!"
:collection="selectedCollection"
no-track-visit
@close="selected = null"
/>
<PublicationDetail
@ -626,8 +600,6 @@ const nearLimit = computed(() => histTotal.value >= Math.floor(HISTORY_LIMIT * 0
:paragraphs="detailParagraphs"
:paragraphs-loading="detailParagraphsLoading"
:collection="selectedCollection!"
:author="selectedAuthor"
no-track-visit
@close="selected = null"
/>
</template>

View File

@ -19,29 +19,14 @@ export interface Release {
}
export const releases: Release[] = [
{
version: '0.8',
date: '5 de junio, 2026',
title: 'Autoría visible en Estudios Bíblicos, Conferencias e Historial',
changes: [
{ type: 'nuevo', text: 'Nombre del autor visible en el panel lateral de Estudios Bíblicos (Dr. José Benjamín Pérez Matos)' },
{ type: 'nuevo', text: 'Nombre del autor visible en el panel lateral de Conferencias (Dr. William Soto Santiago)' },
{ type: 'nuevo', text: 'Nombre del autor visible en el panel de detalle del documento para ambas secciones' },
{ type: 'nuevo', text: 'El historial muestra el nombre del autor en cada entrada de Estudios Bíblicos y Conferencias' },
{ type: 'nuevo', text: 'Se agregó al momento de hacer una búsqueda un desplegable con los resultados "Más recientes" y "Normal"' },
{ type: 'mejora', text: 'El panel de detalle abierto desde el historial también muestra el autor correspondiente' },
{ type: 'fix', text: 'Las colecciones en el historial ahora muestran "Estudios Bíblicos" y "Conferencias" en lugar de los identificadores internos' },
{ type: 'fix', text: 'Corrección de etiquetas en inglés para las pestañas del historial' }
]
},
{
version: '0.7',
date: '31 de mayo, 2026 11:50PM',
title: 'Tour y optimizaciones',
changes: [
{ type: 'nuevo', text: 'Agregado tour virtual con localización para explicar funcionamiento del buscador.'},
{ type: 'nuevo', text: '_Agregada página de inicio que muestra la versión más reciente del changelog.' },
{ type: 'mejora', text: 'Separación de changelog a un TS aparte, para utilizar en changelog y en el home sin duplicación de código.'},
{ type: 'nuevo', text: 'Agregado tour virtual con localizacion para explicar funcionamiento del buscador'},
{ type: 'nuevo', text: 'Agregada pagina de inicio que muestra la version mas reciente del changelog' },
{ type: 'mejora', text: 'Separacion de changelog a un TS aparte para utilizar en changelog y en el home sin duplicacion de codigo'},
{ type: 'nuevo', text: 'Finalizado flow de automatizacion entre backend y typesense'}
]
},

View File

@ -3,8 +3,8 @@
"nav": {
"home": "Home",
"bible_studies": "Bible Studies",
"bible_studies_ts": "Bible Studies",
"conferences_ts": "Conferences",
"bible_studies_ts": "Bible Studies Typesense",
"conferences_ts": "Conferences Typesense",
"conferences": "Conferences",
"between_the_lines": "Between the Lines",
"my_list": "My List",
@ -12,12 +12,8 @@
"settings": "Settings",
"changelog": "What's New"
},
"search": {
"sort": {
"relevance": "Normal",
"date": "Most recent"
},
"word": "Word",
"search": {
"word": "Word",
"phrase": "Phrase",
"placeholder": "Search for...",
"searching": "Searching...",
@ -87,7 +83,7 @@
"development_subtitle_line2": "Come back soon."
},
"ui": {
"copy": "Copy",
"copy": "Copy",
"draft": "Draft",
"empty_bible_studies": "Choose a Bible Study to see the detail",
"empty_conferences": "Choose a Conference to see the detail"

View File

@ -10,38 +10,32 @@
"history": "Historial",
"settings": "Configuración",
"changelog": "Novedades",
"tour": "Toma el tour",
"localeselector": "Selector de idioma"
"tour": "Toma el tour"
},
"tour": {
"progress": "{current} de {total}",
"next": "Siguiente",
"prev": "Anterior",
"done": "Finalizar",
"bible_studies_description": "Realiza búsquedas en los Estudios Bíblicos predicados por el Dr. José Benjamín Pérez Matos",
"conferences_description": "Realiza búsquedas en las conferencias predicadas por el Dr. William Soto Santiago",
"betweenthelines_description": "Realiza búsquedas en las imágenes de entrelíneas de los estudios del Dr. José Benjamín Pérez Matos",
"favorites_description": "Listado de resultados guardados como favoritos para fácil acceso futuro",
"history_description": "Historial de los resultados de búsqueda que has visto",
"settings_description": "Configuración, cantidad de resultados por página, tipo de paginación, entre otros",
"changelog_description": "Bitácora de cambios realizados al sitio en orden cronológico",
"feedback_description": "¿Tienes alguna sugerencia o queja? Realízala aquí.",
"localeselector_description": "Cambia fácilmente el idioma de la página",
"index_changelog": "Panel de últimos cambios subidos",
"favorites_toggle": "Botón para guardar / quitar este documento de mis favoritos",
"collapse_sidebar_description": "Oculta o muestra la barra de navegación lateral para tener más espacio en pantalla",
"total_results_description": "Muestra la cantidad total de resultados encontrados para tu búsqueda",
"favorites_button": "Botón de favoritos"
"bible_studies_description": "Realiza busquedas en los estudios biblicos predicados por el Dr. José Benjamín Pérez",
"conferences_description": "Realiza busquedas en las conferencias predicadas por el Dr. William Soto Santiago",
"betweenthelines_description": "Realiza busquedas en las imagenes de entrelineas de los estudios del Dr. José Benjamín Perez",
"favorites_description": "Listado de resultados guardados como favoritos para facil acceso futuro",
"history_description": "Historial de los resultados de busqueda que has visto",
"settings_description": "Configuracion, cantidad de resultados por pagina, tipo de paginacion, entre otros",
"changelog_description": "Bitacora de cambios realizados al sitio en orden cronologico",
"feedback_description": "Tienes alguna sugerencia o queja? realizala aqui",
"localeselector_description": "Cambia facilmente el idioma de la pagina",
"index_changelog": "Panel de ultimos cambios subidos",
"favorites_toggle": "Boton para guardar / quitar este documento de mis favoritos"
},
"home": {
"instructions": "Bienvenidos, aquí podrán buscar, entre los Estudios Bíblicos, las conferencias y las entrelíneas que están disponibles en el material de archivo de La Gran Carpa Catedral."
"instructions": "Bienvenidos, aqui podran buscar entre los estudios biblicos, las conferencias y las entrelineas que estan disponibles en el material de archivo de La Gran Carpa Catedral."
},
"search": {
"placeholder": "Buscar...",
"searching": "Buscando...",
"tip": "Consejo: envuelve en \"comillas\" para frase exacta en ese orden.",
"collapse": "Colapsar menú lateral",
"total_results": "Total de resultados",
"publication": "Publicación",
"draft": "Borrador",
"country": "País",
@ -55,17 +49,13 @@
"hits_per_page": "aciertos por página",
"hits_retrieved_in": "aciertos logrados en",
"for": "Buscando",
"sort": {
"relevance": "Normal",
"date": "Más recientes"
},
"word": "Palabra",
"phrase": "Frase",
"words": "palabras",
"phrases": "frases",
"words_tooltip": "Buscar por palabras",
"phrases_tooltip": "Buscar por frases",
"instructions": "Selecciona un resultado de búsqueda...",
"instructions": "Selecciona un resultado de busqueda...",
"tab1": {
"tab_title": "Actividades"
},
@ -78,7 +68,7 @@
"page_size_desc": "Cuántos resultados cargar en cada página o petición.",
"results": "resultados",
"pagination_title": "Tipo de paginación",
"pagination_desc": "¿Cómo quieres navegar entre los resultados?",
"pagination_desc": "Cómo quieres navegar entre los resultados.",
"infinite_scroll": "Scroll infinito",
"infinite_scroll_desc": "Los resultados se cargan automáticamente al llegar al final de la lista.",
"numbered": "Páginas numeradas",
@ -96,7 +86,7 @@
"downloads": {
"audio": "Audio",
"book": "Libro",
"simple": "Sencillo"
"simple": "Sencillo",
},
"feedback": {
"title": "Reportar un error",

View File

@ -13,10 +13,6 @@
"changelog": "Nouveautés"
},
"search": {
"sort": {
"relevance": "Normal",
"date": "Plus récents"
},
"word": "Mot",
"phrase": "Phrase",
"placeholder": "Rechercher des activités",

View File

@ -13,10 +13,6 @@
"changelog": "Novidades"
},
"search": {
"sort": {
"relevance": "Normal",
"date": "Mais recentes"
},
"word": "Palavra",
"phrase": "Frase",
"placeholder": "Digite para pesquisar...",