diff --git a/almeira-live b/almeira-live
index 07ecfa5..4ea666b 160000
--- a/almeira-live
+++ b/almeira-live
@@ -1 +1 @@
-Subproject commit 07ecfa5268f8b17294a25d08ed82340479f4aaae
+Subproject commit 4ea666b69d9f37cb0589be5659572a7ea6440bd0
diff --git a/publish-dummies.js b/publish-dummies.js
new file mode 100644
index 0000000..bee04be
--- /dev/null
+++ b/publish-dummies.js
@@ -0,0 +1,78 @@
+const sdk = require('node-appwrite');
+require('dotenv').config({ path: '.env.local' });
+
+const client = new sdk.Client();
+const databases = new sdk.Databases(client);
+
+const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1';
+const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c';
+const API_KEY = process.env.APPWRITE_API_KEY;
+
+client
+ .setEndpoint(ENDPOINT)
+ .setProject(PROJECT_ID)
+ .setKey(API_KEY);
+
+const dbId = process.env.APPWRITE_DATABASE_ID || 'almeira';
+
+async function publishDummies() {
+ try {
+ console.log('Obteniendo tipos de publicación...');
+ const typesRes = await databases.listDocuments(dbId, 'publication_types');
+ const types = typesRes.documents;
+
+ const typeClasif = types.find(t => t.codigo === 'CLASIFICADO');
+ const typeEvento = types.find(t => t.codigo === 'EVENTO');
+ const typeBanner = types.find(t => t.codigo === 'DISPLAY_BANNER');
+
+ if (!typeClasif || !typeEvento || !typeBanner) {
+ console.log('Faltan algunos tipos de publicación en la base de datos.');
+ return;
+ }
+
+ console.log('Insertando Clasificado de prueba...');
+ await databases.createDocument(dbId, 'posts', sdk.ID.unique(), {
+ titulo: 'Vendo Hermosa Casa en el Centro',
+ slug: 'vendo-hermosa-casa-centro-' + Date.now(),
+ resumen_redes: 'Oportunidad única para adquirir una casa con excelentes acabados y ubicación estratégica.',
+ contenido: '
Oportunidad única para adquirir una casa con excelentes acabados y ubicación estratégica. 3 habitaciones, 2 baños, garaje.
',
+ estado: 'Publicado',
+ fecha_publicacion: new Date().toISOString(),
+ tipo_publicacion_id: typeClasif.$id,
+ og_image_url: 'https://images.unsplash.com/photo-1512917774080-9991f1c4c750?q=80&w=1000&auto=format&fit=crop'
+ });
+
+ console.log('Insertando Evento de prueba...');
+ await databases.createDocument(dbId, 'posts', sdk.ID.unique(), {
+ titulo: 'Gran Concierto de Fin de Año',
+ slug: 'gran-concierto-fin-de-ano-' + Date.now(),
+ resumen_redes: 'No te pierdas el evento musical más esperado del año con artistas locales e internacionales.',
+ contenido: 'No te pierdas el evento musical más esperado del año con artistas locales e internacionales. Entrada libre.
',
+ estado: 'Publicado',
+ fecha_publicacion: new Date().toISOString(),
+ fecha_finalizacion: new Date(Date.now() + 86400000 * 30).toISOString(), // + 30 days
+ tipo_publicacion_id: typeEvento.$id,
+ og_image_url: 'https://images.unsplash.com/photo-1540039155733-d76e6148e18e?q=80&w=1000&auto=format&fit=crop'
+ });
+
+ console.log('Insertando Banner de prueba...');
+ await databases.createDocument(dbId, 'posts', sdk.ID.unique(), {
+ titulo: 'Gran Promoción Almeira',
+ slug: 'banner-promo-almeira-' + Date.now(),
+ contenido: '', // Requerido por el schema de posts
+ estado: 'Publicado',
+ fecha_publicacion: new Date().toISOString(),
+ fecha_finalizacion: new Date(Date.now() + 86400000 * 30).toISOString(),
+ tipo_publicacion_id: typeBanner.$id,
+ url_destino: 'https://almeira.com.co',
+ og_image_url: 'https://images.unsplash.com/photo-1504222490345-c075b6008014?q=80&w=1000&auto=format&fit=crop'
+ });
+
+ console.log('¡Publicaciones de prueba insertadas con éxito!');
+
+ } catch (e) {
+ console.error('Error insertando dummies:', e);
+ }
+}
+
+publishDummies();
diff --git a/src/app/clasificados/page.tsx b/src/app/clasificados/page.tsx
index 395992b..1307aad 100644
--- a/src/app/clasificados/page.tsx
+++ b/src/app/clasificados/page.tsx
@@ -1,5 +1,5 @@
import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite';
-import { createAdminClient } from '@/lib/appwrite.server';
+import { createAdminClient, getLoggedInUser } from '@/lib/appwrite.server';
import { Query } from 'node-appwrite';
import { NewsCard } from '@/components/NewsCard';
import { GlobalSidebar, hasSidebarContent } from '@/components/AdWrappers';
@@ -40,11 +40,16 @@ async function fetchClasificadosData() {
if (!typeId) return { posts: [], cardSettings };
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
Query.equal('tipo_publicacion_id', typeId),
- Query.equal('estado', 'Publicado'),
+ Query.equal('estado', ['Publicado', 'publicado']),
Query.orderDesc('fecha_publicacion'),
- Query.limit(postsCount)
+ Query.limit(postsCount * 2)
]);
- posts = postsRes.documents as unknown as Post[];
+
+ const now = new Date();
+ posts = postsRes.documents.filter((post: any) => {
+ if (!post.fecha_finalizacion) return true;
+ return new Date(post.fecha_finalizacion) >= now;
+ }).slice(0, postsCount) as unknown as Post[];
// 3. Resolve Media
const mediaIds = posts.map(p => p.imagen_destacada_id).filter(id => id && typeof id === 'string') as string[];
@@ -73,6 +78,9 @@ export default async function ClasificadosPage() {
const { posts, cardSettings } = await fetchClasificadosData();
const hasSidebar = await hasSidebarContent();
+ const user = await getLoggedInUser();
+ const isAdmin = (user as any)?.labels?.includes('admin') || (user as any)?.labels?.includes('editor') || user?.$id === 'admin-emergency';
+
return (
{/* Sci-Fi Hero Section */}
@@ -127,9 +135,11 @@ export default async function ClasificadosPage() {
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 = post.og_image_url || null;
+
+ const mediaObj = post.resolved_media || (typeof post.imagen_destacada_id === 'object' ? post.imagen_destacada_id : null) as MediaItem | null;
- if (post.resolved_media) {
- imagenUrl = `${ENDPOINT}/storage/buckets/${post.resolved_media.bucket_id}/files/${post.resolved_media.file_id}/preview?project=${PROJECT_ID}&width=800&height=500&quality=85`;
+ if (mediaObj) {
+ imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/preview?project=${PROJECT_ID}&width=800&height=800&quality=85`;
}
return (
@@ -146,6 +156,8 @@ export default async function ClasificadosPage() {
showFooterDate={cardSettings.showFooterDate}
showFooterButton={cardSettings.showFooterButton}
footerText={cardSettings.footerText}
+ imageAspect="aspect-square"
+ isAdmin={isAdmin}
/>
)
})}
diff --git a/src/app/eventos/page.tsx b/src/app/eventos/page.tsx
index 91887e6..8221fc9 100644
--- a/src/app/eventos/page.tsx
+++ b/src/app/eventos/page.tsx
@@ -1,5 +1,5 @@
import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite';
-import { createAdminClient } from '@/lib/appwrite.server';
+import { createAdminClient, getLoggedInUser } from '@/lib/appwrite.server';
import { Query } from 'node-appwrite';
import { NewsCard } from '@/components/NewsCard';
import { GlobalSidebar, hasSidebarContent } from '@/components/AdWrappers';
@@ -40,11 +40,16 @@ async function fetchEventosData() {
if (!typeId) return { posts: [], cardSettings };
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
Query.equal('tipo_publicacion_id', typeId),
- Query.equal('estado', 'Publicado'),
+ Query.equal('estado', ['Publicado', 'publicado']),
Query.orderDesc('fecha_publicacion'),
- Query.limit(postsCount)
+ Query.limit(postsCount * 2)
]);
- posts = postsRes.documents as unknown as Post[];
+
+ const now = new Date();
+ posts = postsRes.documents.filter((post: any) => {
+ if (!post.fecha_finalizacion) return true;
+ return new Date(post.fecha_finalizacion) >= now;
+ }).slice(0, postsCount) as unknown as Post[];
// 3. Resolve Media
const mediaIds = posts.map(p => p.imagen_destacada_id).filter(id => id && typeof id === 'string') as string[];
@@ -73,6 +78,9 @@ export default async function EventosPage() {
const { posts, cardSettings } = await fetchEventosData();
const hasSidebar = await hasSidebarContent();
+ const user = await getLoggedInUser();
+ const isAdmin = (user as any)?.labels?.includes('admin') || (user as any)?.labels?.includes('editor') || user?.$id === 'admin-emergency';
+
return (
{/* Sci-Fi Hero Section */}
@@ -127,9 +135,11 @@ export default async function EventosPage() {
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 = post.og_image_url || null;
+
+ const mediaObj = post.resolved_media || (typeof post.imagen_destacada_id === 'object' ? post.imagen_destacada_id : null) as MediaItem | null;
- if (post.resolved_media) {
- imagenUrl = `${ENDPOINT}/storage/buckets/${post.resolved_media.bucket_id}/files/${post.resolved_media.file_id}/preview?project=${PROJECT_ID}&width=800&height=500&quality=85`;
+ if (mediaObj) {
+ imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/preview?project=${PROJECT_ID}&width=800&height=800&quality=85`;
}
return (
@@ -146,6 +156,8 @@ export default async function EventosPage() {
showFooterDate={cardSettings.showFooterDate}
showFooterButton={cardSettings.showFooterButton}
footerText={cardSettings.footerText}
+ imageAspect="aspect-square"
+ isAdmin={isAdmin}
/>
)
})}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 1e2b6ea..10a5e3c 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -53,7 +53,7 @@ async function fetchHomeData(page: number = 1, isAdmin: boolean = false, adminMo
];
if (isAdmin) {
- queries.push(Query.equal('estado', ['Publicado', 'borrador']));
+ queries.push(Query.equal('estado', ['Publicado', 'publicado', 'borrador']));
if (adminMonth) {
const currentYear = new Date().getFullYear();
// First day of the selected month
@@ -64,7 +64,7 @@ async function fetchHomeData(page: number = 1, isAdmin: boolean = false, adminMo
queries.push(Query.lessThan('fecha_publicacion', endDate));
}
} else {
- queries.push(Query.equal('estado', 'Publicado'));
+ queries.push(Query.equal('estado', ['Publicado', 'publicado']));
}
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', queries);
@@ -216,8 +216,10 @@ export default async function Home(props: { searchParams: Promise<{ [key: string
const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1';
let imagenUrl = post.og_image_url || null;
- if (post.resolved_media) {
- imagenUrl = `${ENDPOINT}/storage/buckets/${post.resolved_media.bucket_id}/files/${post.resolved_media.file_id}/preview?project=${PROJECT_ID}&width=800&height=500&quality=85`;
+ const mediaObj = post.resolved_media || (typeof post.imagen_destacada_id === 'object' ? post.imagen_destacada_id : null) as MediaItem | null;
+
+ if (mediaObj) {
+ imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/preview?project=${PROJECT_ID}&width=800&height=500&quality=85`;
}
return (
diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts
index 9723374..d125019 100644
--- a/src/app/sitemap.ts
+++ b/src/app/sitemap.ts
@@ -22,7 +22,7 @@ export default async function sitemap(): Promise {
// Fetch all published posts
const postsRes = await client.databases.listDocuments(dbId, 'posts', [
- Query.equal('estado', 'Publicado'),
+ Query.equal('estado', ['Publicado', 'publicado']),
Query.limit(1000), // Get up to 1000 posts. For more, pagination is needed.
Query.orderDesc('fecha_publicacion')
]);
diff --git a/src/components/AdWrappers.tsx b/src/components/AdWrappers.tsx
index 411ccd0..d966be4 100644
--- a/src/components/AdWrappers.tsx
+++ b/src/components/AdWrappers.tsx
@@ -33,7 +33,7 @@ export async function GlobalTopBanner() {
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
Query.equal('tipo_publicacion_id', typeId),
- Query.equal('estado', 'Publicado'),
+ Query.equal('estado', ['Publicado', 'publicado']),
Query.orderDesc('fecha_publicacion'),
Query.limit(20)
]);
@@ -82,7 +82,7 @@ export async function GlobalSidebar() {
if (validTypeIds.length > 0) {
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
- Query.equal('estado', 'Publicado'),
+ Query.equal('estado', ['Publicado', 'publicado']),
Query.orderAsc('fecha_finalizacion'),
Query.limit(50)
]);
@@ -135,7 +135,7 @@ export async function hasSidebarContent(): Promise {
if (validTypeIds.length === 0) return false;
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
- Query.equal('estado', 'Publicado'),
+ Query.equal('estado', ['Publicado', 'publicado']),
Query.limit(20)
]);
diff --git a/src/components/NewsCard.tsx b/src/components/NewsCard.tsx
index 5e367db..4a10937 100644
--- a/src/components/NewsCard.tsx
+++ b/src/components/NewsCard.tsx
@@ -15,6 +15,7 @@ interface NewsCardProps {
showFooterButton?: boolean;
footerText?: string;
isAdmin?: boolean;
+ imageAspect?: string;
}
export const NewsCard = ({
@@ -29,7 +30,8 @@ export const NewsCard = ({
showFooterDate = false,
showFooterButton = false,
footerText,
- isAdmin = false
+ isAdmin = false,
+ imageAspect = 'aspect-[16/10]'
}: NewsCardProps) => {
const titulo = decodeHtmlEntities(rawTitulo);
const resumen = decodeHtmlEntities(rawResumen);
@@ -59,7 +61,7 @@ export const NewsCard = ({
)}
{/* Imagen Destacada */}
-
+
{imagenUrl ? (

diff --git a/src/components/NewsTicker.tsx b/src/components/NewsTicker.tsx
index 5c94225..2d80f03 100644
--- a/src/components/NewsTicker.tsx
+++ b/src/components/NewsTicker.tsx
@@ -41,7 +41,7 @@ export default async function NewsTicker() {
if (!typeId) throw new Error("Could not find typeId for NOTICIA");
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
Query.equal('tipo_publicacion_id', typeId),
- Query.equal('estado', 'Publicado'),
+ Query.equal('estado', ['Publicado', 'publicado']),
Query.orderDesc('fecha_publicacion'),
Query.limit(tickerCount)
]);
@@ -57,7 +57,7 @@ export default async function NewsTicker() {
}
postsRes.documents.forEach((post: any) => {
- const media = mediaMap.get(post.imagen_destacada_id);
+ const media = typeof post.imagen_destacada_id === 'object' ? post.imagen_destacada_id : mediaMap.get(post.imagen_destacada_id);
let imagenUrl = post.og_image_url || null;
if (media) {
imagenUrl = `${APPWRITE_ALMEIRA_CONFIG.endpoint}/storage/buckets/${media.bucket_id}/files/${media.file_id}/preview?project=${APPWRITE_ALMEIRA_CONFIG.projectId}`;
diff --git a/src/components/TopBanner.tsx b/src/components/TopBanner.tsx
index 2b0a2a8..a4963bd 100644
--- a/src/components/TopBanner.tsx
+++ b/src/components/TopBanner.tsx
@@ -22,7 +22,7 @@ export default function TopBanner({ initialBanners, rotationSeconds }: { initial
const activeBanner = initialBanners[currentIndex];
- if (!activeBanner.imagen_destacada_id) return null;
+ if (!activeBanner.imagen_destacada_id && !activeBanner.og_image_url) return null;
const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://appwrite.almeira.com.co/v1';
const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c';