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> <template>
<UDashboardPanel id="entrelinea-detail"> <UDashboardPanel id="entrelinea-detail">
<UDashboardNavbar :title="title" :toggle="false"> <UDashboardNavbar :title="document.origin||title" :toggle="false">
<template #leading> <template #leading>
<UButton <UButton
icon="i-lucide-x" icon="i-lucide-x"
@ -108,44 +108,51 @@ function onToggleFavorite() {
</template> </template>
<template #right> <template #right>
<UTooltip :text="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'">
<UButton <UButton
v-if="document.link" :icon="isFav ? 'i-lucide-bookmark-check' : 'i-lucide-bookmark-plus'"
:to="document.link" :color="isFav ? 'primary' : 'neutral'"
target="_blank" variant="ghost"
icon="i-lucide-external-link" :aria-label="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'"
label="Ver en sitio" @click="onToggleFavorite"
color="primary"
variant="solid"
size="sm"
/> />
</UTooltip>
</template> </template>
</UDashboardNavbar> </UDashboardNavbar>
<div class="flex flex-col sm:flex-row justify-between gap-2 p-4 sm:px-6 border-b border-default"> <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"> <div class="min-w-0 flex items-center gap-2 text-xs text-muted">
<UBadge <UBadge
v-if="document.locale" v-if="document.filter"
:label="String(document.locale).toUpperCase()" :label="String(document.filter).toUpperCase()"
color="neutral" color="neutral"
variant="subtle" 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> <span v-if="document.page != null">Página {{ document.page }}</span>
</div> </div>
</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 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 FAB sticky de favorito NUNCA se superponga al contenido: el contenedor
reserva una "zona muerta" en la esquina inferior derecha donde el reserva una "zona muerta" en la esquina inferior derecha donde el
botón puede flotar sin tapar texto ni la imagen. 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 --> <!-- Imagen desde ImageKit -->
<div <div
v-if="imageUrl" 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 <img
:src="imageUrl" :src="imageUrl"
@ -181,22 +188,7 @@ function onToggleFavorite() {
visible mientras el usuario hace scroll. El padding `pe-16/pb-24` visible mientras el usuario hace scroll. El padding `pe-16/pb-24`
del contenedor de contenido garantiza que NUNCA tape texto ni imagen. 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> </div>
</UDashboardPanel> </UDashboardPanel>
</template> </template>

View File

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

View File

@ -42,12 +42,12 @@ async function runSearch(q: string, append = false) {
const timeoutId = setTimeout(() => ac.abort(), REQUEST_TIMEOUT_MS) const timeoutId = setTimeout(() => ac.abort(), REQUEST_TIMEOUT_MS)
try { try {
const res = await meili.index('activities_ES').search(q || '', { const res = await meili.index(`activities_${$i18n.locale.value.toUpperCase()}`).search(q || '', {
attributesToRetrieve: ['*'], attributesToRetrieve: ['*'],
showMatchesPosition: true, showMatchesPosition: true,
limit: PAGE_SIZE, limit: PAGE_SIZE,
offset: append ? hits.value.length : 0, offset: append ? hits.value.length : 0,
sort: q ? undefined : ['date:desc'] sort: q ? undefined : ['isodate:desc']
}, { signal: ac.signal }) }, { signal: ac.signal })
if (seq !== searchSeq) return if (seq !== searchSeq) return

View File

@ -4,6 +4,9 @@ import { breakpointsTailwind, useDebounce } from '@vueuse/core'
import type { SearchHit } from '~/types' import type { SearchHit } from '~/types'
import InboxActivity from '~/components/inbox/InboxActivity.vue' import InboxActivity from '~/components/inbox/InboxActivity.vue'
const { $i18n } = useNuxtApp();
const t = $i18n.t;
const PAGE_SIZE = 15 const PAGE_SIZE = 15
const REQUEST_TIMEOUT_MS = 15000 const REQUEST_TIMEOUT_MS = 15000
@ -36,7 +39,7 @@ async function runSearch(q: string, append = false) {
const timeoutId = setTimeout(() => ac.abort(), REQUEST_TIMEOUT_MS) const timeoutId = setTimeout(() => ac.abort(), REQUEST_TIMEOUT_MS)
try { try {
const res = await meili.index('conferences_ES').search(q || '', { const res = await meili.index(`conferences_${$i18n.locale.value.toUpperCase()}`).search(q || '', {
attributesToRetrieve: ['*'], attributesToRetrieve: ['*'],
showMatchesPosition: true, showMatchesPosition: true,
limit: PAGE_SIZE, 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 * usuario haya puesto en `EXTRA_FILTER_BY`. Es un computed para que se
* reevalúe automáticamente cuando cambia el idioma. */ * reevalúe automáticamente cuando cambia el idioma. */
const filterBy = computed(() => { const filterBy = computed(() => {
const localeFilter = `locale:=${locale.value}` const localeFilter = `locale:=${$i18n.locale.value}`
return EXTRA_FILTER_BY ? `${localeFilter} && ${EXTRA_FILTER_BY}` : localeFilter 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"> <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 <!-- Título pequeño = Origin (cae al id si no hay origin para no
dejar la fila huérfana). --> 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}` }} {{ (hit.document.origin as string) || hit.document.id || `entrelinea_${index}` }}
</div> </div>
</div>
<UTooltip :text="isFav(hit.document) ? 'Quitar de mi lista' : 'Guardar en mi lista'"> <UTooltip :text="isFav(hit.document) ? 'Quitar de mi lista' : 'Guardar en mi lista'">
<UButton <UButton
:icon="isFav(hit.document) ? 'i-lucide-bookmark-check' : 'i-lucide-bookmark-plus'" :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="flex items-start justify-between gap-2 mb-1">
<div class="min-w-0 flex-1"> <div class="min-w-0 flex-1">
<div class="flex gap-2">
<UBadge <UBadge
:label="labelFor(it.collection)" :label="labelFor(it.collection)"
size="xs" size="sm"
variant="subtle" variant="subtle"
color="neutral" color="neutral"
class="mb-1 capitalize" 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"> <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>
</div> </div>
<UButton <UButton