Fixed search locales not working

Fixed between the lines ui for the detail and the list view
Fixed history ui badges
This commit is contained in:
Julio Ruiz 2026-05-12 13:08:15 -05:00
parent b22c58cc5a
commit bbf2465ca2
6 changed files with 99 additions and 64 deletions

View File

@ -96,7 +96,7 @@ function onToggleFavorite() {
<template>
<UDashboardPanel id="entrelinea-detail">
<UDashboardNavbar :title="title" :toggle="false">
<UDashboardNavbar :title="document.origin||title" :toggle="false">
<template #leading>
<UButton
icon="i-lucide-x"
@ -108,44 +108,51 @@ function onToggleFavorite() {
</template>
<template #right>
<UButton
v-if="document.link"
:to="document.link"
target="_blank"
icon="i-lucide-external-link"
label="Ver en sitio"
color="primary"
variant="solid"
size="sm"
/>
<UTooltip :text="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'">
<UButton
:icon="isFav ? 'i-lucide-bookmark-check' : 'i-lucide-bookmark-plus'"
:color="isFav ? 'primary' : 'neutral'"
variant="ghost"
:aria-label="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'"
@click="onToggleFavorite"
/>
</UTooltip>
</template>
</UDashboardNavbar>
<div class="flex flex-col sm:flex-row justify-between gap-2 p-4 sm:px-6 border-b border-default">
<div class="min-w-0 flex items-center gap-2 text-xs text-muted">
<UBadge
v-if="document.locale"
:label="String(document.locale).toUpperCase()"
v-if="document.filter"
:label="String(document.filter).toUpperCase()"
color="neutral"
variant="subtle"
size="xs"
size="sm"
/>
<UBadge
v-if="document.type"
:label="String(document.type).toUpperCase()"
color="neutral"
variant="subtle"
size="sm"
/>
<span v-if="document.page != null">Página {{ document.page }}</span>
</div>
</div>
<div class="flex-1 overflow-y-auto relative">
<div class="flex-1 overflow-y-auto relative bg-gray-100">
<!--
Padding extra a la derecha (pe-16/20) y al fondo (pb-24) para que el
FAB sticky de favorito NUNCA se superponga al contenido: el contenedor
reserva una "zona muerta" en la esquina inferior derecha donde el
botón puede flotar sin tapar texto ni la imagen.
-->
<div class="p-4 sm:p-6 pe-16 sm:pe-20 pb-24 flex flex-col gap-6">
<div class="p-1 sm:p-4 bg-white rounded-lg shadow-md max-w-4xl m-4 sm:mx-auto sm:my-6">
<!-- Imagen desde ImageKit -->
<div
v-if="imageUrl"
class="rounded-lg overflow-hidden border border-default bg-elevated flex items-center justify-center"
class="rounded-lg overflow-hidden border border-default bg-elevated flex items-center justify-center mb-2"
>
<img
:src="imageUrl"
@ -181,22 +188,7 @@ function onToggleFavorite() {
visible mientras el usuario hace scroll. El padding `pe-16/pb-24`
del contenedor de contenido garantiza que NUNCA tape texto ni imagen.
-->
<div
v-if="collection"
class="sticky bottom-0 inset-x-0 h-0 z-20 pointer-events-none"
>
<UTooltip :text="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'">
<UButton
:icon="isFav ? 'i-lucide-bookmark-check' : 'i-lucide-bookmark-plus'"
:color="isFav ? 'primary' : 'neutral'"
variant="solid"
size="xl"
:aria-label="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'"
class="absolute bottom-4 end-4 sm:bottom-6 sm:end-6 rounded-full shadow-lg shadow-black/15 dark:shadow-black/40 ring-1 ring-default pointer-events-auto transition-transform hover:scale-105 active:scale-95"
@click="onToggleFavorite"
/>
</UTooltip>
</div>
</div>
</UDashboardPanel>
</template>

View File

@ -29,27 +29,31 @@ const links = [[{
icon: 'ph:books',
to: '/conferencias',
onSelect: () => { open.value = false }
}, {
label: 'Sermones',
icon: 'ph:books',
to: '/sermones',
onSelect: () => { open.value = false }
}, {
}
// , {
// label: 'Sermones',
// icon: 'ph:books',
// to: '/sermones',
// onSelect: () => { open.value = false }
// }
, {
label: 'Entrelineas',
icon: 'ph:list-magnifying-glass',
to: '/entrelineas',
onSelect: () => { open.value = false }
}, {
label: 'Imprenta',
icon: 'ph:printer',
to: '/imprenta',
onSelect: () => { open.value = false }
}, {
label: 'EBN',
icon: 'ph:chalkboard-teacher',
to: '/ebn',
onSelect: () => { open.value = false }
}, {
}
// , {
// label: 'Imprenta',
// icon: 'ph:printer',
// to: '/imprenta',
// onSelect: () => { open.value = false }
// }, {
// label: 'EBN',
// icon: 'ph:chalkboard-teacher',
// to: '/ebn',
// onSelect: () => { open.value = false }
// }
, {
label: 'Mi lista',
icon: 'i-lucide-bookmark',
to: '/favoritos',

View File

@ -5,7 +5,7 @@ import type { SearchHit } from '~/types'
import InboxActivity from '~/components/inbox/InboxActivity.vue'
const { $i18n } = useNuxtApp();
const t = $i18n.t;
const t = $i18n.t;
const PAGE_SIZE = 15
const REQUEST_TIMEOUT_MS = 15000
@ -42,12 +42,12 @@ async function runSearch(q: string, append = false) {
const timeoutId = setTimeout(() => ac.abort(), REQUEST_TIMEOUT_MS)
try {
const res = await meili.index('activities_ES').search(q || '', {
const res = await meili.index(`activities_${$i18n.locale.value.toUpperCase()}`).search(q || '', {
attributesToRetrieve: ['*'],
showMatchesPosition: true,
limit: PAGE_SIZE,
offset: append ? hits.value.length : 0,
sort: q ? undefined : ['date:desc']
sort: q ? undefined : ['isodate:desc']
}, { signal: ac.signal })
if (seq !== searchSeq) return

View File

@ -4,6 +4,9 @@ import { breakpointsTailwind, useDebounce } from '@vueuse/core'
import type { SearchHit } from '~/types'
import InboxActivity from '~/components/inbox/InboxActivity.vue'
const { $i18n } = useNuxtApp();
const t = $i18n.t;
const PAGE_SIZE = 15
const REQUEST_TIMEOUT_MS = 15000
@ -36,7 +39,7 @@ async function runSearch(q: string, append = false) {
const timeoutId = setTimeout(() => ac.abort(), REQUEST_TIMEOUT_MS)
try {
const res = await meili.index('conferences_ES').search(q || '', {
const res = await meili.index(`conferences_${$i18n.locale.value.toUpperCase()}`).search(q || '', {
attributesToRetrieve: ['*'],
showMatchesPosition: true,
limit: PAGE_SIZE,

View File

@ -50,7 +50,7 @@ const { locale } = useI18n()
* usuario haya puesto en `EXTRA_FILTER_BY`. Es un computed para que se
* reevalúe automáticamente cuando cambia el idioma. */
const filterBy = computed(() => {
const localeFilter = `locale:=${locale.value}`
const localeFilter = `locale:=${$i18n.locale.value}`
return EXTRA_FILTER_BY ? `${localeFilter} && ${EXTRA_FILTER_BY}` : localeFilter
})
@ -366,9 +366,27 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
<div class="flex items-start justify-between gap-2 mb-1">
<!-- Título pequeño = Origin (cae al id si no hay origin para no
dejar la fila huérfana). -->
<div class="text-xs font-semibold uppercase tracking-wide text-muted truncate">
<div class="min-w-0 flex-1 flex gap-2">
<UBadge
v-if="hit.document?.filter"
:label="hit.document?.filter"
size="sm"
variant="subtle"
color="neutral"
class="mb-1 uppercase"
/>
<UBadge
v-if="hit.document?.type"
:label="hit.document?.type"
size="sm"
variant="subtle"
color="neutral"
class="mb-1 uppercase"
/>
<div class="text-sm font-semibold tracking-wide truncate">
{{ (hit.document.origin as string) || hit.document.id || `entrelinea_${index}` }}
</div>
</div>
<UTooltip :text="isFav(hit.document) ? 'Quitar de mi lista' : 'Guardar en mi lista'">
<UButton
:icon="isFav(hit.document) ? 'i-lucide-bookmark-check' : 'i-lucide-bookmark-plus'"

View File

@ -484,15 +484,33 @@ const nearLimit = computed(() => histTotal.value >= Math.floor(HISTORY_LIMIT * 0
>
<div class="flex items-start justify-between gap-2 mb-1">
<div class="min-w-0 flex-1">
<UBadge
:label="labelFor(it.collection)"
size="xs"
variant="subtle"
color="neutral"
class="mb-1 capitalize"
/>
<div class="flex gap-2">
<UBadge
:label="labelFor(it.collection)"
size="sm"
variant="subtle"
color="neutral"
class="mb-1 uppercase"
/>
<UBadge
v-if="it.hit?.filter"
:label="it.hit?.filter"
size="sm"
variant="subtle"
color="neutral"
class="mb-1 uppercase"
/>
<UBadge
v-if="it.hit?.type"
:label="it.hit?.type"
size="sm"
variant="subtle"
color="neutral"
class="mb-1 uppercase"
/>
</div>
<div class="text-sm font-semibold line-clamp-2">
{{ it.hit?.title || 'Sin título' }}
{{ it.hit?.origin || it.hit?.title || 'Sin título' }}
</div>
</div>
<UButton