fix: media search server-side and data serialization in actions

This commit is contained in:
Carlos (Almeira) 2026-03-30 09:18:02 -05:00
parent 86b2e704e9
commit 20a1695305
3 changed files with 28 additions and 9 deletions

View File

@ -80,7 +80,8 @@ export async function uploadMediaServer(formData: FormData) {
}
revalidatePath('/dashboard/media');
return { success: true, count: results.length, data: results };
// Sanitizar documentos para evitar problemas de serialización en Next.js
return { success: true, count: results.length, data: results.map(doc => ({ ...doc })) };
} catch (error: any) {
console.error('Error uploading media:', error);
return { success: false, error: error.message };
@ -116,7 +117,8 @@ export async function uploadMediaDocumentServer(formData: FormData) {
revalidatePath('/dashboard/media');
revalidatePath('/');
return { success: true, count: results.length, data: results };
// Sanitizar para Next.js
return { success: true, count: results.length, data: results.map(doc => ({ ...doc })) };
} catch (error: any) {
console.error('Error uploading media and creating document:', error);
return { success: false, error: error.message };

View File

@ -80,8 +80,8 @@ export default async function NewsTicker() {
Query.limit(5)
]);
} catch (queryError: any) {
// If 'status' attribute is missing, try fetching without it but still limited
console.warn("WhatsApp 'status' query failed, trying fallback fetch:", queryError.message);
// El atributo 'status' puede no estar todavía en el esquema de Appwrite (Modo Gracia)
// Usamos fallback de todos los mensajes limitados si falla el filtro
waRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'whatsapp_messages', [
Query.orderDesc('$createdAt'),
Query.limit(5)

View File

@ -48,15 +48,21 @@ export const MediaGridSelector = ({
if (isOpen) fetchMedia();
}, [isOpen]);
const fetchMedia = async (more = false) => {
const fetchMedia = async (more = false, search = '') => {
setIsLoading(true);
try {
const currentOffset = more ? mediaItems.length : 0;
const res = await databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'media', [
const queries = [
Query.limit(20),
Query.offset(currentOffset),
Query.orderDesc('$createdAt')
]);
];
if (search) {
queries.push(Query.contains('titulo', search));
}
const res = await databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'media', queries);
if (more) {
setMediaItems(prev => [...prev, ...res.documents]);
@ -72,6 +78,17 @@ export const MediaGridSelector = ({
}
};
// Handle Search Debouncing
useEffect(() => {
if (!isOpen) return;
const timer = setTimeout(() => {
fetchMedia(false, searchTerm);
}, 500);
return () => clearTimeout(timer);
}, [searchTerm, isOpen]);
useEffect(() => {
// If we have a value but haven't loaded its document, fetch just that one
if (value && mode === 'field' && !mediaItems.some(m => m.$id === value)) {
@ -118,7 +135,7 @@ export const MediaGridSelector = ({
if (onClose) onClose();
}, [onClose]);
const filteredItems = mediaItems.filter(item => item.titulo.toLowerCase().includes(searchTerm.toLowerCase()));
const filteredItems = mediaItems;
// Render modal structure
const renderModal = () => {
@ -218,7 +235,7 @@ export const MediaGridSelector = ({
{hasMore && (
<button
onClick={() => fetchMedia(true)}
onClick={() => fetchMedia(true, searchTerm)}
disabled={isLoading}
className="text-[10px] font-black uppercase tracking-widest text-cyan-500 hover:text-cyan-400 disabled:opacity-50 transition-colors flex items-center gap-2"
>