Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Rafael Lopez
/
ppto
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Rafael Lopez
2026-03-12 17:35:46 -0400
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
e6bdfc2d5d0f4a86dd3315d5a54eacfd8dca6ec6
e6bdfc2d
1 parent
ebc2cc7c
nuevo landing
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
195 additions
and
14 deletions
src/routes/+page.svelte
src/routes/test/+page.svelte
src/routes/+page.svelte
View file @
e6bdfc2
This diff could not be displayed because it is too large.
src/routes/test/+page.svelte
View file @
e6bdfc2
<script>
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import {
query,
results,
isLoading,
indexLoaded,
error,
selectedIndex,
showResults,
initIndex,
performSearch,
clearSearch,
navigateResults
} from '$lib/stores/searchStore';
let mounted = false;
let mode = 'archivo';
...
...
@@ -12,8 +26,13 @@
let hWidget = null;
let hGear = false;
let mobileSettingsOpen = false;
let searchInput;
let debounceTimer;
onMount(() => { setTimeout(() => { mounted = true; }, 80); });
onMount(() => {
setTimeout(() => { mounted = true; }, 80);
initIndex();
});
function toggleMobileSettings() {
mobileSettingsOpen = !mobileSettingsOpen;
...
...
@@ -38,8 +57,82 @@
{ label: 'Regalías', bg: 'rgba(160,150,170,0.09)', color: '#aaa0b0' },
];
function switchMode(m) { mode = m; searchVal = ''; }
function handleBlur() { setTimeout(() => { searchFocused = false; }, 200); }
function switchMode(m) {
mode = m;
searchVal = '';
clearSearch();
if (searchInput) searchInput.value = '';
}
function handleBlur() {
setTimeout(() => { searchFocused = false; }, 200);
}
function handleInput(e) {
const value = e.target.value;
searchVal = value;
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
performSearch(value);
}, 250);
}
function handleKeydown(e) {
if (!$showResults) return;
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
navigateResults('down', $results.length);
break;
case 'ArrowUp':
e.preventDefault();
navigateResults('up', $results.length);
break;
case 'Enter':
e.preventDefault();
if ($selectedIndex >= 0 && $results[$selectedIndex]) {
handleSelect($results[$selectedIndex]);
}
break;
case 'Escape':
clearSearch();
searchVal = '';
if (searchInput) searchInput.value = '';
searchInput?.blur();
break;
}
}
function handleSelect(item) {
if (item.tipo === 'entidad') {
goto(`/entidad/${item.codigo}`);
} else if (item.tipo === 'objeto_gasto') {
goto(`/objeto/${item.codigo}`);
} else if (item.tipo === 'rubro') {
goto(`/rubro/${item.codigo}`);
}
clearSearch();
searchVal = '';
if (searchInput) searchInput.value = '';
}
function getTypeLabel(tipo) {
switch (tipo) {
case 'entidad': return 'ENTIDAD';
case 'objeto_gasto': return 'OBJETO';
case 'rubro': return 'RUBRO';
default: return tipo?.toUpperCase() || '';
}
}
function getTypeColor(tipo) {
switch (tipo) {
case 'entidad': return '#4A8B6E';
case 'objeto_gasto': return '#C9A751';
case 'rubro': return '#8B6E9B';
default: return '#6B6860';
}
}
const WIDGETS_INGRESOS = [
{ id: 'rubros', label: 'tipos de ingreso', d: 'Impuestos, regalías, ventas, créditos', t: 'Recursos por rubros', n: '324', href: '/clasificadores/rubros' },
...
...
@@ -155,7 +248,7 @@
<div class="hero-search anim" style="--d:520ms">
<div class="search-wrap">
<!-- Search bar unificado -->
<div class="search-bar" class:search-focused={searchFocused} style="--accent:{accent}">
<div class="search-bar" class:search-focused={searchFocused}
class:search-has-results={searchFocused && ($results.length > 0 || ($query.length >= 2 && $results.length === 0) || $isLoading)}
style="--accent:{accent}">
<!-- Toggle integrado (desktop) -->
<div class="toggle-bar toggle-desktop">
<button class="toggle-btn" class:toggle-active={mode === 'archivo'} on:click={() => switchMode('archivo')}>
...
...
@@ -186,14 +279,28 @@
<circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/>
</svg>
<div class="search-input-wrap">
<input type="text" bind:value={searchVal} on:focus={() => searchFocused = true} on:blur={handleBlur} />
<input
type="text"
bind:this={searchInput}
bind:value={searchVal}
on:input={handleInput}
on:keydown={handleKeydown}
on:focus={() => searchFocused = true}
on:blur={handleBlur}
disabled={!$indexLoaded}
/>
{#if !searchVal && !searchFocused}
<div class="search-placeholder">
<span class="blink-cursor" style="background:{accent}"></span>
<span class="placeholder-text placeholder-desktop">{
placeholder
}</span>
<span class="placeholder-text placeholder-mobile">{
isD ? 'MEFP, Min. Salud, GAM...' : 'BOA, Publicidad, IDH
...'}</span>
<span class="placeholder-text placeholder-desktop">{
$indexLoaded ? placeholder : 'Cargando...'
}</span>
<span class="placeholder-text placeholder-mobile">{
$indexLoaded ? (isD ? 'MEFP, Min. Salud, GAM...' : 'BOA, Publicidad, IDH...') : 'Cargando
...'}</span>
</div>
{/if}
{#if searchVal && !$isLoading}
<button class="search-clear" on:click={() => { clearSearch(); searchVal = ''; if (searchInput) searchInput.value = ''; }}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
{/if}
</div>
{#if !isD}
<div class="gear-btn gear-desktop" class:gear-hover={hGear} on:mouseenter={() => hGear = true} on:mouseleave={() => hGear = false} role="button" tabindex="0">
...
...
@@ -205,6 +312,45 @@
{/if}
</div>
<!-- Search Results Dropdown -->
{#if $isLoading}
<div class="search-results">
<div class="search-loading">Buscando...</div>
</div>
{:else if searchFocused && $results.length > 0}
<div class="search-results">
{#each $results as item, i}
<button
type="button"
class="search-result-item"
class:result-selected={$selectedIndex === i}
on:click={() => handleSelect(item)}
>
<div class="result-main">
<span class="result-name">{item.nombre}</span>
{#if item.sigla}
<span class="result-sigla">({item.sigla})</span>
{/if}
</div>
<div class="result-meta">
{#if item.codigo}
<span class="result-code">{item.codigo}</span>
{/if}
<span class="result-type" style="color:{getTypeColor(item.tipo)}">{getTypeLabel(item.tipo)}</span>
</div>
</button>
{/each}
</div>
{:else if searchFocused && $query.length >= 2 && $results.length === 0}
<div class="search-results">
<div class="search-no-results">Sin resultados para "{$query}"</div>
</div>
{/if}
{#if $error}
<div class="search-error">{$error}</div>
{/if}
<!-- Mobile settings panel -->
<div class="mobile-settings-panel" class:mobile-settings-panel-open={mobileSettingsOpen}>
<div class="mobile-toggle-bar">
...
...
@@ -237,7 +383,7 @@
</div>
<!-- Scroll hint -->
<div class="scroll-hint anim" style="--d:700ms">
<div class="scroll-hint anim" style="--d:700ms"
class:scroll-hint-hidden={searchFocused && $results.length > 0}
>
<svg width="18" height="28" viewBox="0 0 18 28" fill="none" stroke="#B8B5AD" stroke-width="1.2" stroke-linecap="round">
<rect x="1" y="1" width="16" height="26" rx="8"/><line x1="9" y1="7" x2="9" y2="12" opacity="0.7"/>
</svg>
...
...
@@ -659,9 +805,9 @@
.hero{background:#1C1C1A;color:#F5F0E8;flex:1;display:flex;flex-direction:column;justify-content:center;padding:40px 48px 32px;position:relative;overflow:hidden}
.dot-pattern{position:absolute;inset:0;opacity:0.02;background-image:radial-gradient(circle at 1px 1px,#B8B5AD 0.5px,transparent 0);background-size:40px 40px}
.dot-pattern-sm{position:absolute;inset:0;opacity:0.015;background-image:radial-gradient(circle at 1px 1px,#fff 0.5px,transparent 0);background-size:32px 32px}
.hero-inner{max-width:1060px;margin:0 auto;width:100%;position:relative;margin-top:-
24
px;text-align:center}
.hero-identity{margin-bottom:2
8
px}
.hero-search{display:flex;justify-content:center}
.hero-inner{max-width:1060px;margin:0 auto;width:100%;position:relative;margin-top:-
80
px;text-align:center}
.hero-identity{margin-bottom:2
0
px}
.hero-search{display:flex;justify-content:center
;position:relative;z-index:50
}
.hero-tag{font-family:var(--mono);font-size:12px;letter-spacing:0.25em;color:#B8B5AD}
.hero-title{font-size:clamp(44px,5.5vw,72px);font-weight:900;line-height:1.02;letter-spacing:-0.035em;max-width:720px;margin:14px auto 0}
.hero-sub{font-family:var(--sans);font-size:clamp(16px,1.6vw,18px);color:#9B9890;max-width:100%;margin-top:14px;line-height:1.6}
...
...
@@ -670,9 +816,10 @@
.stat-dot{margin:0 10px;opacity:0.3}
/* Search */
.search-wrap{max-width:860px;width:100%;margin:0 auto}
.search-bar{display:flex;align-items:center;background:rgba(255,255,255,0.04);border-radius:16px;padding:8px 14px 8px 8px;transition:all 0.4s cubic-bezier(0.16,1,0.3,1);box-shadow:0 0 0 1px rgba(201,167,81,0.12),0 8px 32px rgba(0,0,0,0.25)}
.search-wrap{max-width:860px;width:100%;margin:0 auto
;position:relative;z-index:9999
}
.search-bar{display:flex;align-items:center;background:rgba(255,255,255,0.04);border-radius:16px;padding:8px 14px 8px 8px;transition:all 0.4s cubic-bezier(0.16,1,0.3,1);box-shadow:0 0 0 1px rgba(201,167,81,0.12),0 8px 32px rgba(0,0,0,0.25)
;position:relative
}
.search-focused{background:rgba(255,255,255,0.07);box-shadow:0 0 0 1.5px rgba(201,167,81,0.35),0 8px 40px rgba(0,0,0,0.3)}
.search-has-results{border-radius:16px 16px 0 0}
.toggle-bar{display:flex;border-radius:10px;padding:2px;background:rgba(0,0,0,0.2);flex-shrink:0}
.toggle-btn{background:transparent;border:none;border-radius:8px;padding:12px 16px;cursor:pointer;display:flex;align-items:center;gap:7px;transition:all 0.3s;font-family:var(--sans);font-size:14px;font-weight:400;color:#9B9890}
.toggle-btn svg{display:block;flex-shrink:0}
...
...
@@ -703,6 +850,27 @@
.mobile-toggle-btn span{font-family:var(--sans);font-size:14px;font-weight:600;color:#F5F0E8}
.mobile-toggle-btn svg{margin-bottom:4px}
.mobile-toggle-sub{font-size:11px!important;font-weight:400!important;color:#9B9890!important;font-family:var(--mono)!important;letter-spacing:0.05em}
/* Search clear button */
.search-clear{background:none;border:none;cursor:pointer;color:#6B6860;padding:4px;display:flex;align-items:center;justify-content:center;transition:color 0.2s;flex-shrink:0}
.search-clear:hover{color:#F5F0E8}
/* Search Results Dropdown */
.search-results{position:absolute;top:100%;left:0;right:0;background:rgba(28,28,26,0.98);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.1);border-top:none;border-radius:0 0 16px 16px;max-height:320px;overflow-y:auto;z-index:9999}
.search-loading,.search-no-results{padding:16px 20px;font-family:var(--sans);font-size:14px;color:#9B9890;text-align:center}
.search-error{margin-top:8px;font-family:var(--sans);font-size:13px;color:#C44B3F;text-align:center}
.search-result-item{width:100%;text-align:left;background:none;border:none;border-top:1px solid rgba(255,255,255,0.06);padding:14px 20px;display:flex;justify-content:space-between;align-items:center;cursor:pointer;transition:background 0.2s}
.search-result-item:first-child{border-top:none}
.search-result-item:hover,.result-selected{background:rgba(255,255,255,0.06)}
.result-main{display:flex;align-items:center;gap:8px;flex:1;min-width:0}
.result-name{font-family:var(--sans);font-size:14px;color:#F5F0E8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.result-sigla{font-family:var(--sans);font-size:12px;color:#9B9890;flex-shrink:0}
.result-meta{display:flex;align-items:center;gap:8px;flex-shrink:0;margin-left:12px}
.result-code{font-family:var(--mono);font-size:10px;color:#9B9890;background:rgba(255,255,255,0.06);padding:2px 6px;border-radius:4px}
.result-type{font-family:var(--mono);font-size:9px;letter-spacing:0.1em;font-weight:600}
.pills{display:flex;gap:8px;margin-top:16px;flex-wrap:wrap;align-items:center;justify-content:center}
.pills-label{font-family:var(--mono);font-size:11px;letter-spacing:0.1em;color:#B8B5AD;margin-right:2px}
.pill{font-family:var(--mono);font-size:12px;font-weight:300;letter-spacing:0.03em;border:none;border-radius:6px;padding:5px 12px;cursor:pointer;transition:all 0.25s;line-height:1.4;position:relative;overflow:hidden}
...
...
@@ -710,7 +878,8 @@
.pill:hover::before{opacity:1}
.pill:hover{transform:translateY(-1px)}
.scroll-hint{position:absolute;bottom:28px;left:0;right:0;margin:0 auto;width:fit-content;display:flex;flex-direction:column;align-items:center;gap:10px;animation:scrollHint 2.5s ease-in-out infinite}
.scroll-hint{position:absolute;bottom:28px;left:0;right:0;margin:0 auto;width:fit-content;display:flex;flex-direction:column;align-items:center;gap:10px;animation:scrollHint 2.5s ease-in-out infinite;z-index:1;transition:opacity 0.3s}
.scroll-hint-hidden{opacity:0;pointer-events:none}
.scroll-hint span{font-family:var(--mono);font-size:10px;letter-spacing:0.2em;color:#B8B5AD;opacity:0.7}
/* ── DIRECTORY ── */
...
...
@@ -917,6 +1086,14 @@
.search-input-wrap input{font-size:15px;padding:10px 8px}
.placeholder-desktop{display:none}
.placeholder-mobile{display:inline;font-size:14px}
/* Search results mobile */
.search-results{max-height:260px;border-radius:0 0 12px 12px}
.search-result-item{padding:12px 16px}
.result-name{font-size:13px}
.result-meta{flex-direction:column;align-items:flex-end;gap:4px}
.result-code{font-size:9px}
.result-type{font-size:8px}
.pills{gap:6px}
.pill{font-size:11px;padding:4px 10px}
.scroll-hint{bottom:20px}
...
...
@@ -1001,6 +1178,10 @@
.mobile-settings-btn{width:36px;height:36px}
.mobile-toggle-btn{padding:14px 10px}
.mobile-toggle-btn span{font-size:13px}
.search-results{max-height:220px}
.search-result-item{padding:10px 14px}
.result-name{font-size:12px}
.result-sigla{font-size:10px}
.pills-label{display:none}
.pill{font-size:10px;padding:4px 8px}
.scroll-hint{display:none}
...
...
Please
register
or
login
to post a comment