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 && (
+
+

+
+
+ )}
+
+
+
+
+
+
+
+
+ );
+}
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}
+ />
+ )
+ })}
)}