Adding visual styling to details component. Adding paragraph indicator.

This commit is contained in:
Julio Ruiz 2026-05-17 10:23:08 -05:00
parent 1eb6d7df59
commit 5e69e45716
1 changed files with 36 additions and 103 deletions

View File

@ -748,13 +748,7 @@ function highlightTextNodes(root: HTMLElement, terms: string[]): number {
<UDashboardPanel id="estudios-ts-detail"> <UDashboardPanel id="estudios-ts-detail">
<UDashboardNavbar :toggle="false"> <UDashboardNavbar :toggle="false">
<template #leading> <template #leading>
<UButton <UButton icon="i-lucide-arrow-left" color="neutral" variant="ghost" class="-ms-1.5" @click="emits('close')" />
icon="i-lucide-arrow-left"
color="neutral"
variant="ghost"
class="-ms-1.5"
@click="emits('close')"
/>
</template> </template>
<template #title> <template #title>
@ -765,14 +759,9 @@ function highlightTextNodes(root: HTMLElement, terms: string[]): number {
<template #right> <template #right>
<UTooltip :text="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'"> <UTooltip :text="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'">
<UButton <UButton :icon="isFav ? 'i-lucide-bookmark-check' : 'i-lucide-bookmark-plus'"
:icon="isFav ? 'i-lucide-bookmark-check' : 'i-lucide-bookmark-plus'" :color="isFav ? 'primary' : 'neutral'" variant="ghost" :disabled="!document"
:color="isFav ? 'primary' : 'neutral'" :aria-label="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'" @click="onToggleFavorite" />
variant="ghost"
:disabled="!document"
:aria-label="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'"
@click="onToggleFavorite"
/>
</UTooltip> </UTooltip>
</template> </template>
</UDashboardNavbar> </UDashboardNavbar>
@ -790,75 +779,39 @@ function highlightTextNodes(root: HTMLElement, terms: string[]): number {
<span class="truncate max-w-55">{{ safeLocation() }}</span> <span class="truncate max-w-55">{{ safeLocation() }}</span>
</p> </p>
</div> </div>
<UButton <UButton v-if="matchUrl" :to="matchUrl" target="_blank" icon="i-lucide-external-link" label="Ver en sitio"
v-if="matchUrl" color="primary" variant="soft" size="xs" class="shrink-0" />
:to="matchUrl"
target="_blank"
icon="i-lucide-external-link"
label="Ver en sitio"
color="primary"
variant="soft"
size="xs"
class="shrink-0"
/>
</div> </div>
<div v-if="fileLinks.length" class="flex flex-wrap gap-2"> <div v-if="fileLinks.length" class="flex flex-wrap gap-2">
<UButton <UButton v-for="(f, idx) in fileLinks" :key="idx" :to="f.to" :target="f.target" :icon="f.icon!" :label="f.label"
v-for="(f, idx) in fileLinks" color="neutral" variant="subtle" size="xs" external />
:key="idx"
:to="f.to"
:target="f.target"
:icon="f.icon!"
:label="f.label"
color="neutral"
variant="subtle"
size="xs"
external
/>
</div> </div>
<!-- Buscador interno del documento --> <!-- Buscador interno del documento -->
<div v-if="paragraphs.length" class="flex items-center gap-2"> <div v-if="paragraphs.length" class="flex items-center gap-2">
<UInput <UInput v-model="localQuery" icon="i-lucide-search" :placeholder="props.query || 'Buscar en este documento...'"
v-model="localQuery" class="flex-1 min-w-0" :ui="{ trailing: 'pe-1' }" @keydown="onInputKey">
icon="i-lucide-search"
:placeholder="props.query || 'Buscar en este documento...'"
class="flex-1 min-w-0"
:ui="{ trailing: 'pe-1' }"
@keydown="onInputKey"
>
<template #trailing> <template #trailing>
<UButton <UButton v-if="localQuery" icon="i-lucide-x" variant="link" aria-label="Limpiar" @click="clearLocalQuery" />
v-if="localQuery"
icon="i-lucide-x"
variant="link"
aria-label="Limpiar"
@click="clearLocalQuery"
/>
</template> </template>
</UInput> </UInput>
<template v-if="matchElements.length || searchMode === 'local'"> <template v-if="matchElements.length || searchMode === 'local'">
<UBadge <UBadge v-if="searchMode === 'typesense' && matchElements.length" label="Typesense" size="xs" variant="subtle"
v-if="searchMode === 'typesense' && matchElements.length" color="warning" class="shrink-0" />
label="Typesense"
size="xs"
variant="subtle"
color="warning"
class="shrink-0"
/>
<span <span
class="text-xs tabular-nums whitespace-nowrap shrink-0 px-2 py-1 rounded-md bg-elevated border border-default" class="text-xs tabular-nums whitespace-nowrap shrink-0 px-2 py-1 rounded-md bg-elevated border border-default"
:class="matchElements.length ? 'text-toned font-medium' : 'text-dimmed'" :class="matchElements.length ? 'text-toned font-medium' : 'text-dimmed'">
>
{{ matchElements.length ? `${currentMatchIdx + 1} / ${matchElements.length}` : '0 / 0' }} {{ matchElements.length ? `${currentMatchIdx + 1} / ${matchElements.length}` : '0 / 0' }}
</span> </span>
<div class="flex items-center gap-1 shrink-0"> <div class="flex items-center gap-1 shrink-0">
<UTooltip text="Anterior (Shift+Enter)"> <UTooltip text="Anterior (Shift+Enter)">
<UButton icon="i-lucide-chevron-up" :disabled="!matchElements.length" aria-label="Anterior" color="neutral" variant="ghost" size="sm" @click="prevMatch" /> <UButton icon="i-lucide-chevron-up" :disabled="!matchElements.length" aria-label="Anterior"
color="neutral" variant="ghost" size="sm" @click="prevMatch" />
</UTooltip> </UTooltip>
<UTooltip text="Siguiente (Enter)"> <UTooltip text="Siguiente (Enter)">
<UButton icon="i-lucide-chevron-down" :disabled="!matchElements.length" aria-label="Siguiente" color="neutral" variant="ghost" size="sm" @click="nextMatch" /> <UButton icon="i-lucide-chevron-down" :disabled="!matchElements.length" aria-label="Siguiente"
color="neutral" variant="ghost" size="sm" @click="nextMatch" />
</UTooltip> </UTooltip>
</div> </div>
</template> </template>
@ -867,54 +820,33 @@ function highlightTextNodes(root: HTMLElement, terms: string[]): number {
<div ref="scrollContainer" class="flex-1 overflow-y-auto relative bg-gray-100"> <div ref="scrollContainer" class="flex-1 overflow-y-auto relative bg-gray-100">
<!-- Cargando párrafos --> <!-- Cargando párrafos -->
<div <div v-if="paragraphsLoading" class="flex items-center justify-center gap-2 py-16 text-sm text-muted">
v-if="paragraphsLoading"
class="flex items-center justify-center gap-2 py-16 text-sm text-muted"
>
<UIcon name="i-lucide-loader-circle" class="size-5 animate-spin" /> <UIcon name="i-lucide-loader-circle" class="size-5 animate-spin" />
Cargando párrafos... Cargando párrafos...
</div> </div>
<!-- Todos los párrafos --> <!-- Todos los párrafos -->
<div <div v-else-if="paragraphs.length" ref="paragraphsContainer" class="p-1 sm:p-4 max-w-4xl m-4 sm:mx-auto sm:my-6">
v-else-if="paragraphs.length" <div class="bg-white rounded-lg shadow-md p-4 mb-4 last:mb-0">
ref="paragraphsContainer" <div v-for="(hit, idx) in paragraphs" :key="idx" :data-paragraph-number="hit.document.number">
class="p-1 sm:p-4 max-w-4xl m-4 sm:mx-auto sm:my-6" <div class="flex items-start gap-2 mb-2">
> <div class="w-1/12">
<div <UBadge v-if="hit.document.number" :label="`#${hit.document.number}`" size="xs" variant="outline"
v-for="(hit, idx) in paragraphs" color="info" />
:key="idx" </div>
:data-paragraph-number="hit.document.number" <div class="w-11/12">
class="bg-white rounded-lg shadow-md p-4 mb-4 last:mb-0" <div
> class="paragraph-html text-sm leading-relaxed text-gray-800 dark:text-gray-200"
<div class="flex items-center gap-2 mb-2"> v-html="hit.document.text"
<UBadge />
v-if="hit.document.number" </div>
:label="`#${hit.document.number}`" </div>
size="xs"
variant="subtle"
color="info"
/>
<UBadge
v-if="hit.document.type"
:label="hit.document.type"
size="xs"
variant="subtle"
color="neutral"
/>
</div> </div>
<div
class="paragraph-html text-sm leading-relaxed text-gray-800 dark:text-gray-200"
v-html="hit.document.text"
/>
</div> </div>
</div> </div>
<!-- Sin contenido --> <!-- Sin contenido -->
<div <div v-else class="flex flex-col items-center justify-center gap-2 py-16 text-dimmed text-sm">
v-else
class="flex flex-col items-center justify-center gap-2 py-16 text-dimmed text-sm"
>
<UIcon name="i-lucide-file-x" class="size-10" /> <UIcon name="i-lucide-file-x" class="size-10" />
<p>No hay contenido disponible para este documento.</p> <p>No hay contenido disponible para este documento.</p>
<p v-if="matchUrl"> <p v-if="matchUrl">
@ -930,6 +862,7 @@ function highlightTextNodes(root: HTMLElement, terms: string[]): number {
.paragraph-html :deep(p) { .paragraph-html :deep(p) {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.paragraph-html :deep(p:last-child) { .paragraph-html :deep(p:last-child) {
margin-bottom: 0; margin-bottom: 0;
} }