fix(serialization): resolve typescript types in map functions preventing successful production build, and add global error boundary failover
This commit is contained in:
parent
6ed5cb69e6
commit
84d48ad096
@ -132,7 +132,7 @@ export default async function ClasificadosPage() {
|
||||
</div>
|
||||
) : (
|
||||
<div className={`grid grid-cols-1 md:grid-cols-2 ${hasSidebar ? 'lg:grid-cols-2 xl:grid-cols-3' : 'lg:grid-cols-3 xl:grid-cols-4'} gap-6`}>
|
||||
{posts.map((post) => {
|
||||
{posts.map((post: 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 = post.og_image_url || null;
|
||||
|
||||
32
src/app/error.tsx
Normal file
32
src/app/error.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export default function Error({
|
||||
error,
|
||||
reset,
|
||||
}: {
|
||||
error: Error & { digest?: string }
|
||||
reset: () => void
|
||||
}) {
|
||||
useEffect(() => {
|
||||
// Solo redirigir si no estamos ya en el dominio de respaldo para evitar bucles infinitos
|
||||
if (typeof window !== 'undefined' && window.location.hostname !== 'news.almeira.co') {
|
||||
window.location.href = 'https://news.almeira.co';
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col items-center justify-center bg-slate-950 text-white p-4 font-sans">
|
||||
<h2 className="text-3xl font-black mb-4 uppercase tracking-widest text-cyan-500">SEÑAL INTERRUMPIDA</h2>
|
||||
<p className="text-slate-400 mb-8 max-w-md text-center text-lg">
|
||||
Hemos detectado una anomalía en este servidor. Redirigiendo automáticamente a nuestro portal de respaldo...
|
||||
</p>
|
||||
<div className="w-10 h-10 border-4 border-cyan-500 border-t-transparent rounded-full animate-spin"></div>
|
||||
|
||||
<a href="https://news.almeira.co" className="mt-8 px-6 py-2 border border-slate-700 rounded-full text-sm text-slate-400 hover:text-white hover:border-slate-500 transition-colors">
|
||||
Ir manualmente
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -132,7 +132,7 @@ export default async function EventosPage() {
|
||||
</div>
|
||||
) : (
|
||||
<div className={`grid grid-cols-1 md:grid-cols-2 ${hasSidebar ? 'lg:grid-cols-2 xl:grid-cols-3' : 'lg:grid-cols-3 xl:grid-cols-4'} gap-6`}>
|
||||
{posts.map((post) => {
|
||||
{posts.map((post: 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 = post.og_image_url || null;
|
||||
|
||||
45
src/app/global-error.tsx
Normal file
45
src/app/global-error.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
'use client'
|
||||
|
||||
export default function GlobalError({
|
||||
error,
|
||||
reset,
|
||||
}: {
|
||||
error: Error & { digest?: string }
|
||||
reset: () => void
|
||||
}) {
|
||||
return (
|
||||
<html lang="es">
|
||||
<head>
|
||||
<script dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
if (window.location.hostname !== 'news.almeira.co') {
|
||||
window.location.href = 'https://news.almeira.co';
|
||||
}
|
||||
`
|
||||
}} />
|
||||
</head>
|
||||
<body style={{ backgroundColor: '#020617', color: 'white', fontFamily: 'sans-serif', margin: 0, padding: 0 }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', padding: '20px', textAlign: 'center' }}>
|
||||
<h2 style={{ fontSize: '2rem', fontWeight: 900, marginBottom: '1rem', color: '#06b6d4', textTransform: 'uppercase', letterSpacing: '0.1em' }}>SEÑAL CRÍTICA INTERRUMPIDA</h2>
|
||||
<p style={{ color: '#94a3b8', marginBottom: '2rem', maxWidth: '400px', fontSize: '1.125rem' }}>
|
||||
Fallo mayor en la transmisión principal. Reencaminando el tráfico a nuestro servidor secundario...
|
||||
</p>
|
||||
<div style={{ width: '40px', height: '40px', border: '4px solid #06b6d4', borderTopColor: 'transparent', borderRadius: '50%', animation: 'spin 1s linear infinite' }}></div>
|
||||
|
||||
<a href="https://news.almeira.co" style={{ marginTop: '2rem', padding: '10px 20px', border: '1px solid #334155', borderRadius: '9999px', color: '#94a3b8', textDecoration: 'none', fontSize: '0.875rem' }}>
|
||||
Ir a news.almeira.co
|
||||
</a>
|
||||
|
||||
<style dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
`
|
||||
}} />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@ -212,7 +212,7 @@ export default async function Home(props: { searchParams: Promise<{ [key: string
|
||||
</div>
|
||||
) : (
|
||||
<div className={`grid grid-cols-1 md:grid-cols-2 ${hasSidebar ? 'lg:grid-cols-2 xl:grid-cols-3' : 'lg:grid-cols-3 xl:grid-cols-4'} gap-6`}>
|
||||
{posts.map((post) => {
|
||||
{posts.map((post: 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 = post.og_image_url || null;
|
||||
|
||||
@ -34,7 +34,10 @@ export const NewsCard = ({
|
||||
imageAspect = 'aspect-[16/10]'
|
||||
}: NewsCardProps) => {
|
||||
const titulo = decodeHtmlEntities(rawTitulo);
|
||||
const resumen = decodeHtmlEntities(rawResumen);
|
||||
|
||||
// Strip HTML tags safely for a plain text excerpt
|
||||
const plainTextResumen = (rawResumen || '').replace(/<[^>]*>?/gm, ' ').replace(/\s+/g, ' ').trim();
|
||||
const resumen = decodeHtmlEntities(plainTextResumen);
|
||||
|
||||
// Formatear fecha
|
||||
const fechaObj = new Date(fecha);
|
||||
@ -62,9 +65,14 @@ export const NewsCard = ({
|
||||
|
||||
{/* Imagen Destacada */}
|
||||
<div className={`relative ${imageAspect} w-full overflow-hidden bg-slate-800 z-0`}>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-slate-950 via-slate-950/20 to-transparent z-10 opacity-90 pointer-events-none"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-slate-950 via-slate-950/20 to-transparent z-20 opacity-90 pointer-events-none"></div>
|
||||
{imagenUrl ? (
|
||||
<img src={imagenUrl} alt={titulo} className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110" />
|
||||
<>
|
||||
{/* Blurred Background to fill empty spaces nicely */}
|
||||
<img src={imagenUrl} alt="" className="absolute inset-0 w-full h-full object-cover blur-2xl opacity-40 scale-110" aria-hidden="true" />
|
||||
{/* Main Image contained properly without crop */}
|
||||
<img src={imagenUrl} alt={titulo} className="relative z-10 w-full h-full object-contain transition-transform duration-700 group-hover:scale-105" />
|
||||
</>
|
||||
) : (
|
||||
<div className="w-full h-full flex items-center justify-center bg-[radial-gradient(ellipse_at_center,_var(--tw-gradient-stops))] from-slate-800 to-slate-900">
|
||||
{/* No placeholder text as per user request */}
|
||||
@ -73,14 +81,12 @@ export const NewsCard = ({
|
||||
|
||||
{/* Badge/Tag - Habilitable por prop */}
|
||||
{showCategory && (
|
||||
<div className="absolute top-4 left-4 z-20">
|
||||
<div className="absolute top-4 left-4 z-30">
|
||||
<span className="px-3 py-1.5 rounded-full text-xs font-bold uppercase tracking-wider backdrop-blur-md border border-white/20 bg-black/40 text-cyan-300 shadow-[0_0_10px_rgba(6,182,212,0.2)]">
|
||||
{tipo?.toUpperCase() || 'NOTICIA'}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* No button here */}
|
||||
</div>
|
||||
|
||||
{/* Contenido */}
|
||||
|
||||
@ -71,8 +71,7 @@ export async function createAdminClient() {
|
||||
|
||||
patchClientInstance(client);
|
||||
|
||||
const keyPrefix = process.env.APPWRITE_API_KEY ? process.env.APPWRITE_API_KEY.trim().substring(0, 15) + '...' : 'EMPTY_KEY';
|
||||
console.log('Admin Client initialized with key:', keyPrefix, 'Length:', process.env.APPWRITE_API_KEY?.length);
|
||||
|
||||
|
||||
return {
|
||||
get account() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user