fix: resolve entity logo media URL, robust media upload, and UI media grid icons

This commit is contained in:
Carlos (Almeira) 2026-07-18 10:09:35 -05:00
parent 84d48ad096
commit 7432e8432b
4 changed files with 26 additions and 8 deletions

View File

@ -6,12 +6,11 @@ const nextConfig: NextConfig = {
outputFileTracingRoot: process.cwd(),
trailingSlash: true,
staticPageGenerationTimeout: 300,
experimental: {
serverActions: {
bodySizeLimit: (process.env.SERVER_ACTIONS_BODY_SIZE_LIMIT as any) || '100mb',
allowedOrigins: ['almeiraproducciones.com', 'news.almeira.com.co', 'www.almeiraproducciones.com', 'localhost:3000'],
},
serverActions: {
bodySizeLimit: (process.env.SERVER_ACTIONS_BODY_SIZE_LIMIT as any) || '100mb',
allowedOrigins: ['almeiraproducciones.com', 'news.almeira.com.co', 'www.almeiraproducciones.com', 'localhost:3000'],
},
experimental: {},
serverExternalPackages: ['isomorphic-dompurify', 'jsdom'],
};

View File

@ -120,6 +120,8 @@ export async function uploadMediaDocumentServer(formData: FormData) {
.replace(/\d+$/, '') // Eliminar números al final (foto1 -> foto)
.trim();
const smartTitle = cleanName.charAt(0).toUpperCase() + cleanName.slice(1);
const isImage = file.type ? file.type.startsWith('image/') : /\\.(jpg|jpeg|png|gif|webp|svg)$/i.test(file.name);
const doc = await databases.createDocument(DATABASE_ID, 'media', ID.unique(), {
file_id: uploadedFile.$id,
@ -127,7 +129,7 @@ export async function uploadMediaDocumentServer(formData: FormData) {
titulo: tituloBase || smartTitle || file.name,
alt_text: altTextBase || smartTitle || rawName,
descripcion_seo: descSeo,
tipo: file.type.startsWith('image/') ? 'imagen' : 'video'
tipo: isImage ? 'imagen' : 'video'
});
results.push(doc);
}

View File

@ -26,7 +26,21 @@ export async function getEntityConfig() {
COLLECTION_ID,
[Query.limit(1)]
);
return response.documents[0] ? JSON.parse(JSON.stringify(response.documents[0])) : null;
const doc = response.documents[0];
if (doc && doc.logotipo && !doc.logotipo.startsWith('http') && !doc.logotipo.startsWith('/')) {
try {
// Si es un ID de documento de la colección media, lo resolvemos
const mediaDoc = await databases.getDocument(DATABASE_ID, 'media', doc.logotipo);
if (mediaDoc && mediaDoc.file_id) {
const bucketId = mediaDoc.bucket_id || 'media';
doc.logotipo = `${ENDPOINT}/storage/buckets/${bucketId}/files/${mediaDoc.file_id}/view?project=${PROJECT_ID}`;
}
} catch (mediaErr) {
// Si falla (por ejemplo, si realmente era un file_id antiguo), no hacemos nada y dejamos que el frontend intente usarlo como file_id
console.warn("Could not resolve media doc for logotipo, keeping original value:", mediaErr.message);
}
}
return doc ? JSON.parse(JSON.stringify(doc)) : null;
} catch (error: any) {
// Silently handle 404 (collection not found)
if (error?.code === 404) {

View File

@ -2,7 +2,7 @@
import { useState, useEffect, useCallback, useRef } from 'react';
import { createPortal } from 'react-dom';
import { ImageIcon, X, Search, CheckCircle2, UploadCloud, Loader2 } from 'lucide-react';
import { ImageIcon, Video, X, Search, CheckCircle2, UploadCloud, Loader2 } from 'lucide-react';
import { databases, APPWRITE_ALMEIRA_CONFIG, endpoint, projectId } from '@/lib/appwrite';
import { uploadMediaDocumentServer, listMediaServer, getMediaServer } from '@/app/actions/appwrite';
@ -214,6 +214,9 @@ export const MediaGridSelector = ({
) : (
<img src={url} alt={item.titulo} title={item.titulo} className="w-full h-full object-cover transition-transform group-hover:scale-110" loading="lazy" />
)}
<div className="absolute top-2 left-2 bg-slate-900/80 backdrop-blur-md rounded-lg p-1.5 shadow-lg border border-slate-700/50">
{isVideo ? <Video size={14} className="text-cyan-400" /> : <ImageIcon size={14} className="text-pink-400" />}
</div>
<div className="absolute inset-0 bg-gradient-to-t from-cyan-500/20 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none" />
{value === item.$id && (
<div className="absolute top-2 right-2 bg-cyan-500 text-white rounded-full p-1 shadow-lg">