- Add safety checks for direct Appwrite document index access across all root pages. - Harden NewsTicker and AdWrappers with robust fallback settings and length checks. - Apply strict typing to dashboard settings page and resolve icon conflicts. - Final global audit for deprecated Zod .errors usage (0 occurrences remaining). - Standardize PublicationLayout across creation and edit workflows for posts.
141 lines
6.0 KiB
TypeScript
141 lines
6.0 KiB
TypeScript
import { APPWRITE_ALMEIRA_CONFIG, Query } from '@/lib/appwrite';
|
|
import { createAdminClient } from '@/lib/appwrite.server';
|
|
import TopBanner from './TopBanner';
|
|
import ClientSidebars from './ClientSidebars';
|
|
|
|
import { Settings } from '@/types/settings';
|
|
|
|
async function fetchSettings(): Promise<Settings> {
|
|
try {
|
|
const client = await createAdminClient();
|
|
const res = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', [Query.limit(1)]);
|
|
if (res.documents.length > 0) return res.documents[0] as unknown as Settings;
|
|
} catch(e) {
|
|
console.error("fetchSettings error:", e);
|
|
}
|
|
return { rotation_seconds: 5, ticker_count: 10, feed_news_count: 12, show_news_date: true };
|
|
}
|
|
|
|
export async function GlobalTopBanner() {
|
|
let banners: any[] = [];
|
|
let settings = await fetchSettings();
|
|
|
|
try {
|
|
const client = await createAdminClient();
|
|
const typesRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'publication_types', [
|
|
Query.equal('codigo', 'DISPLAY_BANNER')
|
|
]);
|
|
|
|
if (typesRes.documents.length > 0) {
|
|
const firstType = typesRes.documents[0];
|
|
const typeId = firstType?.$id;
|
|
if (!typeId) return null;
|
|
|
|
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(20)
|
|
]);
|
|
|
|
// FIltrar caducados en memoria por seguridad (Appwrite no maneja > de fechas tan dinámico a veces sin índices exactos)
|
|
const now = new Date();
|
|
banners = postsRes.documents.filter(post => {
|
|
if (!post.fecha_finalizacion) return true;
|
|
return new Date(post.fecha_finalizacion) >= now;
|
|
});
|
|
}
|
|
} catch (e) {
|
|
console.error("TopBanner fetch error", e);
|
|
}
|
|
|
|
if (banners.length === 0) return null;
|
|
|
|
return <TopBanner initialBanners={banners} rotationSeconds={settings.rotation_seconds} />
|
|
}
|
|
|
|
export async function GlobalSidebar() {
|
|
let settings = { rotation_seconds: 5 } as Settings;
|
|
let groupedAds: Record<string, any[]> = {};
|
|
|
|
try {
|
|
settings = await fetchSettings();
|
|
const client = await createAdminClient();
|
|
|
|
// 1. Obtener tipos válidos para sidebar
|
|
const typesRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'publication_types', []);
|
|
const validCodes = ['DISPLAY_SLIDER', 'EVENTO', 'CLASIFICADO', 'AD_BANNER'];
|
|
const validTypeIds = typesRes.documents.filter(t => validCodes.includes(t.codigo)).map(t => t.$id);
|
|
|
|
if (validTypeIds.length > 0) {
|
|
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
|
Query.equal('estado', 'Publicado'),
|
|
Query.orderAsc('fecha_finalizacion'),
|
|
Query.limit(50)
|
|
]);
|
|
|
|
const now = new Date();
|
|
const activePosts = postsRes.documents.filter(post => {
|
|
if (!post.tipo_publicacion_id) return false;
|
|
const typeId = typeof post.tipo_publicacion_id === 'string' ? post.tipo_publicacion_id : post.tipo_publicacion_id.$id;
|
|
if (!validTypeIds.includes(typeId)) return false;
|
|
if (post.fecha_finalizacion && new Date(post.fecha_finalizacion) < now) return false;
|
|
return true;
|
|
});
|
|
|
|
for (const post of activePosts) {
|
|
let slogan = 'Patrocinado';
|
|
if (post.cliente_id) {
|
|
try {
|
|
const client_id = typeof post.cliente_id === 'string' ? post.cliente_id : post.cliente_id.$id;
|
|
const contracts = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'contracts', [
|
|
Query.equal('cliente_id', client_id),
|
|
Query.equal('estado', 'Activo'),
|
|
Query.limit(1)
|
|
]);
|
|
if (contracts.documents.length > 0 && contracts.documents[0].eslogan) {
|
|
slogan = contracts.documents[0].eslogan;
|
|
}
|
|
} catch(e) {}
|
|
}
|
|
|
|
if (!groupedAds[slogan]) groupedAds[slogan] = [];
|
|
groupedAds[slogan].push(post);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error("Sidebar fetch error", e);
|
|
}
|
|
|
|
if (Object.keys(groupedAds).length === 0) return null;
|
|
|
|
return <ClientSidebars groupedAds={groupedAds} rotationSeconds={settings.rotation_seconds} />
|
|
}
|
|
|
|
export async function hasSidebarContent(): Promise<boolean> {
|
|
try {
|
|
const client = await createAdminClient();
|
|
const typesRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'publication_types', []);
|
|
const validCodes = ['DISPLAY_SLIDER', 'EVENTO', 'CLASIFICADO', 'AD_BANNER'];
|
|
const validTypeIds = typesRes.documents.filter(t => validCodes.includes(t.codigo)).map(t => t.$id);
|
|
|
|
if (validTypeIds.length === 0) return false;
|
|
|
|
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
|
Query.equal('estado', 'Publicado'),
|
|
Query.limit(20)
|
|
]);
|
|
|
|
const now = new Date();
|
|
return postsRes.documents.some(post => {
|
|
if (!post.tipo_publicacion_id) return false;
|
|
const typeId = typeof post.tipo_publicacion_id === 'string' ? post.tipo_publicacion_id : post.tipo_publicacion_id.$id;
|
|
if (!validTypeIds.includes(typeId)) return false;
|
|
if (post.fecha_finalizacion && new Date(post.fecha_finalizacion) < now) return false;
|
|
return true;
|
|
});
|
|
} catch(e) {
|
|
return false;
|
|
}
|
|
}
|