1+ ---
2+ // Navbar.astro
3+ const { posts } = Astro .props ;
4+ ---
5+
6+ <nav class =" nav" >
7+ <a href =" /astro-proyect/" ><img src =" /astro-proyect/images/logo_TB_horiz_negativo-01.png" alt =" The_bridge" class =" logo" ></a >
8+
9+ <div class =" search-container" >
10+ <input
11+ type =" text"
12+ id =" search-input"
13+ placeholder =" Buscar..."
14+ aria-label =" Buscar"
15+ class =" search-input"
16+ style =" padding: 0.5rem; border-radius: 0.25rem; border: 1px solid #ccc;"
17+ />
18+ <ul id =" search-results" class =" search-dropdown" ></ul >
19+ </div >
20+
21+ <ul class =" navList" >
22+ <li class =" navItem" ><a href =" /astro-proyect/fundamentals/" >Fundamentals</a ></li >
23+ <li class =" navItem" ><a href =" /astro-proyect/backend/" >BackEnd</a ></li >
24+ <li class =" navItem" ><a href =" /astro-proyect/frontend/" >FrontEnd</a ></li >
25+ </ul >
26+
27+ <button class =" hamburger" aria-label =" Toggle menu" >☰ </button >
28+ </nav >
29+
30+ <script type =" module" >
31+ let posts = [];
32+ const sectionMap = {
33+ html: 'fundamentals',
34+ css: 'fundamentals',
35+ javascript: 'fundamentals',
36+ react: 'frontend',
37+ nodejs: 'backend',
38+ bases_de_datos: 'backend',
39+ };
40+
41+ async function loadSearchData() {
42+ if (posts.length > 0) return; // Evita recargar si ya están
43+ const res = await fetch('/astro-proyect/search-index.json');
44+ const data = await res.json();
45+
46+ const sectionPosts = Object.entries(sectionMap).map(([category, section]) => ({
47+ title: category,
48+ description: `Ver todos los artículos de ${category}`,
49+ url: `/astro-proyect/${section}/${category}/`
50+ }));
51+
52+ const contentPosts = data.map(post => ({
53+ title: post.title,
54+ description: post.description,
55+ url: `/astro-proyect/${post.slug}`
56+ }));
57+
58+ posts = [...sectionPosts, ...contentPosts];
59+ }
60+
61+ function buscar(term) {
62+ const input = term.toLowerCase();
63+ const resultsBox = document.querySelector("#search-results");
64+
65+ if (!input) {
66+ resultsBox.innerHTML = '';
67+ return;
68+ }
69+
70+ const results = posts.filter(post =>
71+ post.title.toLowerCase().includes(input) ||
72+ post.description.toLowerCase().includes(input)
73+ );
74+
75+ if (results.length === 0) {
76+ resultsBox.innerHTML = '<li style="padding: 0.75rem 1rem; color: white;">No se encontraron resultados</li>';
77+ return;
78+ }
79+
80+ resultsBox.innerHTML = results.map(post => `
81+ <li class="search-result-item">
82+ <a href="${post.url}">
83+ <strong>${post.title}</strong><br>
84+ <span>${post.description}</span>
85+ </a>
86+ </li>
87+ `).join('');
88+ }
89+
90+ function initSearch() {
91+ const inputEl = document.querySelector("#search-input");
92+ if (inputEl) {
93+ inputEl.addEventListener("input", (e) => buscar(e.target.value));
94+ }
95+
96+ document.addEventListener("click", (e) => {
97+ const container = document.querySelector(".search-container");
98+ if (!container.contains(e.target)) {
99+ document.querySelector("#search-results").innerHTML = "";
100+ }
101+ });
102+
103+ document.addEventListener("keydown", (e) => {
104+ if (e.key === "Escape") {
105+ document.querySelector("#search-results").innerHTML = "";
106+ document.getElementById("search-input").value = "";
107+ }
108+ });
109+ }
110+
111+ // Inicializa en carga inicial
112+ document.addEventListener("DOMContentLoaded", async () => {
113+ await loadSearchData();
114+ initSearch();
115+
116+ document.addEventListener('astro:after-swap', () => {
117+ initSearch();
118+ })
119+ });
120+ </script >
121+
0 commit comments