From 43dd3770b99d768e221fa8529c2c011f278a7f8b Mon Sep 17 00:00:00 2001 From: "Carlos (Almeira)" Date: Thu, 26 Mar 2026 14:29:16 -0500 Subject: [PATCH] Fix: Refactor feeds to Server Components, fix filters/counts, and add news detail route --- src/app/clasificados/page.tsx | 111 +++++++++++++++-------------- src/app/eventos/page.tsx | 111 +++++++++++++++-------------- src/app/noticia/[slug]/page.tsx | 102 +++++++++++++++++++++++++++ src/app/page.tsx | 119 +++++++++++++++++--------------- 4 files changed, 288 insertions(+), 155 deletions(-) create mode 100644 src/app/noticia/[slug]/page.tsx diff --git a/src/app/clasificados/page.tsx b/src/app/clasificados/page.tsx index ff96c49..39d034b 100644 --- a/src/app/clasificados/page.tsx +++ b/src/app/clasificados/page.tsx @@ -1,36 +1,43 @@ -"use client"; - -import { useState, useEffect } from 'react'; -import { databases, APPWRITE_ALMEIRA_CONFIG, Query } from '@/lib/appwrite'; +import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite'; +import { createAdminClient } from '@/lib/appwrite.server'; +import { Query } from 'node-appwrite'; import { NewsCard } from '@/components/NewsCard'; -import { Loader2 } from 'lucide-react'; +import { Loader2, Sparkles } from 'lucide-react'; -export default function ClasificadosPage() { - const [posts, setPosts] = useState([]); - const [isLoading, setIsLoading] = useState(true); +async function fetchClasificadosData() { + try { + const client = await createAdminClient(); + + // 1. Settings for count + const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []); + const postsCount = settingsRes.documents.length > 0 ? (settingsRes.documents[0].classifieds_count || 9) : 9; - useEffect(() => { - const fetchLatestPosts = async () => { - try { - const response = await databases.listDocuments( - APPWRITE_ALMEIRA_CONFIG.databaseId, - APPWRITE_ALMEIRA_CONFIG.collections.posts, - [ - Query.equal('tipo', 'clasificado'), - Query.orderDesc('$createdAt'), - Query.limit(6) - ] - ); - setPosts(response.documents); - } catch (error) { - console.error("Error fetching posts:", error); - } finally { - setIsLoading(false); - } - }; + // 2. Get CLASIFICADO type ID + const typeRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'publication_types', [ + Query.equal('codigo', 'CLASIFICADO') + ]); + + let posts: any[] = []; + if (typeRes.documents.length > 0) { + const typeId = typeRes.documents[0].$id; + const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [ + Query.equal('tipo_publicacion_id', typeId), + Query.equal('estado', 'Publicado'), + Query.orderDesc('fecha_publicacion'), + Query.limit(postsCount) + ]); + posts = postsRes.documents; + } - fetchLatestPosts(); - }, []); + return { posts }; + } catch (e) { + console.error("Clasificados fetch error", e); + return { posts: [] }; + } +} + +export default async function ClasificadosPage() { + const { posts } = await fetchClasificadosData(); return (
@@ -49,13 +56,13 @@ export default function ClasificadosPage() { Compra, venta y servicios en tu comunidad al instante con total seguridad.

- + @@ -70,12 +77,7 @@ export default function ClasificadosPage() { - {isLoading ? ( -
- -

Sincronizando Noticias...

-
- ) : posts.length === 0 ? ( + {posts.length === 0 ? (
@@ -85,18 +87,27 @@ export default function ClasificadosPage() {
) : (
- {posts.map((post) => ( - - ))} + {posts.map((post) => { + const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; + let imagenUrl = null; + if (post.imagen_destacada_id) { + imagenUrl = `${ENDPOINT}/storage/buckets/${post.imagen_destacada_id.bucket_id}/files/${post.imagen_destacada_id.file_id}/preview?project=${PROJECT_ID}&width=800&height=500&quality=85`; + } + + return ( + ]*>?/gm, '') + '...'} + tipo="Aviso" + fecha={post.fecha_publicacion || post.$createdAt} + imagenUrl={imagenUrl} + /> + ) + })}
)} diff --git a/src/app/eventos/page.tsx b/src/app/eventos/page.tsx index b38e29f..6ed18c4 100644 --- a/src/app/eventos/page.tsx +++ b/src/app/eventos/page.tsx @@ -1,36 +1,43 @@ -"use client"; - -import { useState, useEffect } from 'react'; -import { databases, APPWRITE_ALMEIRA_CONFIG, Query } from '@/lib/appwrite'; +import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite'; +import { createAdminClient } from '@/lib/appwrite.server'; +import { Query } from 'node-appwrite'; import { NewsCard } from '@/components/NewsCard'; -import { Loader2 } from 'lucide-react'; +import { Loader2, Calendar } from 'lucide-react'; -export default function EventosPage() { - const [posts, setPosts] = useState([]); - const [isLoading, setIsLoading] = useState(true); +async function fetchEventosData() { + try { + const client = await createAdminClient(); + + // 1. Settings for count + const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []); + const postsCount = settingsRes.documents.length > 0 ? (settingsRes.documents[0].events_count || 9) : 9; - useEffect(() => { - const fetchLatestPosts = async () => { - try { - const response = await databases.listDocuments( - APPWRITE_ALMEIRA_CONFIG.databaseId, - APPWRITE_ALMEIRA_CONFIG.collections.posts, - [ - Query.equal('tipo', 'evento'), - Query.orderDesc('$createdAt'), - Query.limit(6) - ] - ); - setPosts(response.documents); - } catch (error) { - console.error("Error fetching posts:", error); - } finally { - setIsLoading(false); - } - }; + // 2. Get EVENTO type ID + const typeRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'publication_types', [ + Query.equal('codigo', 'EVENTO') + ]); + + let posts: any[] = []; + if (typeRes.documents.length > 0) { + const typeId = typeRes.documents[0].$id; + const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [ + Query.equal('tipo_publicacion_id', typeId), + Query.equal('estado', 'Publicado'), + Query.orderDesc('fecha_publicacion'), + Query.limit(postsCount) + ]); + posts = postsRes.documents; + } - fetchLatestPosts(); - }, []); + return { posts }; + } catch (e) { + console.error("Eventos fetch error", e); + return { posts: [] }; + } +} + +export default async function EventosPage() { + const { posts } = await fetchEventosData(); return (
@@ -49,13 +56,13 @@ export default function EventosPage() { Los mejores eventos artísticos, culturales y sociales en un solo lugar.

- +
@@ -70,12 +77,7 @@ export default function EventosPage() { - {isLoading ? ( -
- -

Sincronizando Noticias...

-
- ) : posts.length === 0 ? ( + {posts.length === 0 ? (
@@ -85,18 +87,27 @@ export default function EventosPage() {
) : (
- {posts.map((post) => ( - - ))} + {posts.map((post) => { + const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; + let imagenUrl = null; + if (post.imagen_destacada_id) { + imagenUrl = `${ENDPOINT}/storage/buckets/${post.imagen_destacada_id.bucket_id}/files/${post.imagen_destacada_id.file_id}/preview?project=${PROJECT_ID}&width=800&height=500&quality=85`; + } + + return ( + ]*>?/gm, '') + '...'} + tipo="Evento" + fecha={post.fecha_publicacion || post.$createdAt} + imagenUrl={imagenUrl} + /> + ) + })}
)} diff --git a/src/app/noticia/[slug]/page.tsx b/src/app/noticia/[slug]/page.tsx new file mode 100644 index 0000000..bde37d1 --- /dev/null +++ b/src/app/noticia/[slug]/page.tsx @@ -0,0 +1,102 @@ +import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite'; +import { createAdminClient } from '@/lib/appwrite.server'; +import { Query } from 'node-appwrite'; +import { GlobalSidebar } from '@/components/AdWrappers'; +import { Calendar, User, ArrowLeft } from 'lucide-react'; +import Link from 'next/link'; + +async function fetchPostData(slug: string) { + try { + const client = await createAdminClient(); + + const res = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [ + Query.equal('slug', slug), + Query.limit(1) + ]); + + if (res.documents.length === 0) return null; + return res.documents[0]; + } catch (e) { + console.error("Post detail fetch error", e); + return null; + } +} + +export default async function NoticiaDetail({ params }: { params: { slug: string } }) { + const post = await fetchPostData(params.slug); + + if (!post) { + return ( +
+

404 - SEÑAL PERDIDA

+

No hemos podido localizar la transmisión solicitada en el núcleo central.

+ VOLVER AL FEED +
+ ); + } + + const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; + let imagenUrl = null; + if (post.imagen_destacada_id) { + imagenUrl = `${ENDPOINT}/storage/buckets/${post.imagen_destacada_id.bucket_id}/files/${post.imagen_destacada_id.file_id}/preview?project=${PROJECT_ID}&width=1200&height=600&quality=90`; + } + + const fechaObj = new Date(post.fecha_publicacion || post.$createdAt); + const fechaFormateada = fechaObj.toLocaleDateString('es-ES', { day: '2-digit', month: 'long', year: 'numeric' }); + + return ( +
+
+
+
+ + + VOLVER A NOTICIAS + + +
+
+ + {post.tipo?.toUpperCase() || 'NOTICIA'} + +
+ + {fechaFormateada} +
+
+ +

+ {post.titulo} +

+ + {post.resumen_redes && ( +

+ {post.resumen_redes} +

+ )} +
+ + {imagenUrl && ( +
+ {post.titulo} +
+
+ )} + +
+
+ + +
+
+
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 6d76847..498f536 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,37 +1,45 @@ -"use client"; - -import { useState, useEffect } from 'react'; -import { databases, APPWRITE_ALMEIRA_CONFIG, Query } from '@/lib/appwrite'; +import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite'; +import { createAdminClient } from '@/lib/appwrite.server'; +import { Query } from 'node-appwrite'; import { NewsCard } from '@/components/NewsCard'; import { GlobalSidebar } from '@/components/AdWrappers'; -import { Loader2, RadioTower, Sparkles, ChevronDown } from 'lucide-react'; +import { RadioTower, Sparkles, ChevronDown, Loader2 } from 'lucide-react'; +import { Suspense } from 'react'; -export default function Home() { - const [posts, setPosts] = useState([]); - const [isLoading, setIsLoading] = useState(true); +async function fetchHomeData() { + try { + const client = await createAdminClient(); + + // 1. Settings for count + const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []); + const postsCount = settingsRes.documents.length > 0 ? (settingsRes.documents[0].feed_count || settingsRes.documents[0].post_count || 9) : 9; - useEffect(() => { - const fetchLatestPosts = async () => { - try { - const response = await databases.listDocuments( - APPWRITE_ALMEIRA_CONFIG.databaseId, - APPWRITE_ALMEIRA_CONFIG.collections.posts, - [ - Query.equal('tipo', 'noticia'), - Query.orderDesc('$createdAt'), - Query.limit(6) - ] - ); - setPosts(response.documents); - } catch (error) { - console.error("Error fetching posts:", error); - } finally { - setIsLoading(false); - } - }; + // 2. Get NOTICIA type ID + const typeRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'publication_types', [ + Query.equal('codigo', 'NOTICIA') + ]); + + let posts: any[] = []; + if (typeRes.documents.length > 0) { + const typeId = typeRes.documents[0].$id; + const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [ + Query.equal('tipo_publicacion_id', typeId), + Query.equal('estado', 'Publicado'), + Query.orderDesc('fecha_publicacion'), + Query.limit(postsCount) + ]); + posts = postsRes.documents; + } - fetchLatestPosts(); - }, []); + return { posts }; + } catch (e) { + console.error("Home fetch error", e); + return { posts: [] }; + } +} + +export default async function Home() { + const { posts } = await fetchHomeData(); return (
@@ -56,22 +64,22 @@ export default function Home() { El primer portal transaccional hiperconectado. Sumérgete en la actualidad de la región en tiempo real con una interfaz sin precedentes.

- +
{/* Scroll Indicator */} -
document.getElementById('noticias')?.scrollIntoView({ behavior: 'smooth'})}> + Descubrir -
+ {/* Feed Section */} @@ -88,15 +96,7 @@ export default function Home() { - {isLoading ? ( -
-
-
- -
-

Sincronizando Noticias...

-
- ) : posts.length === 0 ? ( + {posts.length === 0 ? (
@@ -107,18 +107,27 @@ export default function Home() {
) : (
- {posts.map((post) => ( - - ))} + {posts.map((post) => { + const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1'; + let imagenUrl = null; + if (post.imagen_destacada_id) { + imagenUrl = `${ENDPOINT}/storage/buckets/${post.imagen_destacada_id.bucket_id}/files/${post.imagen_destacada_id.file_id}/preview?project=${PROJECT_ID}&width=800&height=500&quality=85`; + } + + return ( + ]*>?/gm, '') + '...'} + tipo="Noticia" + fecha={post.fecha_publicacion || post.$createdAt} + imagenUrl={imagenUrl} + /> + ) + })}
)}