149 lines
6.6 KiB
TypeScript
149 lines
6.6 KiB
TypeScript
'use server'
|
|
|
|
import { Client, Databases, ID, Query } from 'node-appwrite';
|
|
import { databaseId } from '@/lib/appwrite';
|
|
import { revalidatePath } from 'next/cache';
|
|
|
|
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 DATABASE_ID = databaseId;
|
|
const COLLECTION_ID = 'entity_config';
|
|
|
|
async function getAdminClient() {
|
|
const client = new Client()
|
|
.setEndpoint(ENDPOINT)
|
|
.setProject(PROJECT_ID)
|
|
.setKey(process.env.APPWRITE_API_KEY || '');
|
|
return new Databases(client);
|
|
}
|
|
|
|
export async function getEntityConfig() {
|
|
try {
|
|
const databases = await getAdminClient();
|
|
const response = await databases.listDocuments(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
[Query.limit(1)]
|
|
);
|
|
return response.documents[0] ? JSON.parse(JSON.stringify(response.documents[0])) : null;
|
|
} catch (error: any) {
|
|
// Silently handle 404 (collection not found)
|
|
if (error?.code === 404) {
|
|
return null;
|
|
}
|
|
console.error('Error fetching entity config:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// ALIAS PARA COMPATIBILIDAD CON DASHBOARD
|
|
export const getEntity = getEntityConfig;
|
|
|
|
export async function updateEntityConfig(data: any) {
|
|
try {
|
|
const databases = await getAdminClient();
|
|
const existing = await getEntityConfig();
|
|
|
|
let parsedData: any = data;
|
|
if (typeof FormData !== 'undefined' && data instanceof FormData) {
|
|
parsedData = {};
|
|
|
|
// Los checkboxes no vienen en el FormData si no están marcados.
|
|
// Manejamos explícitamente los booleanos conocidos aquí para que puedan actualizarse a false,
|
|
// y para que se envíen como boolean en lugar de string "true".
|
|
parsedData['mostrar_texto_logo'] = data.has('mostrar_texto_logo');
|
|
|
|
for (const [key, value] of Array.from(data.entries())) {
|
|
// Ignorar claves tratadas explícitamente y claves internas
|
|
if (key === 'mostrar_texto_logo' || key.startsWith('$ACTION') || key === '$id' || key === '$collectionId' || key === '$databaseId') {
|
|
continue;
|
|
}
|
|
if (typeof value === 'object' && 'size' in value && 'name' in value) {
|
|
const file = value as File;
|
|
if (file.size > 0) {
|
|
try {
|
|
const { uploadMediaServer } = await import('@/app/actions/appwrite');
|
|
const tempForm = new FormData();
|
|
tempForm.append('files', file);
|
|
const uploadRes = await uploadMediaServer(tempForm);
|
|
if (uploadRes.success && uploadRes.data && uploadRes.data[0]) {
|
|
const m = uploadRes.data[0];
|
|
parsedData[key] = `${ENDPOINT}/storage/buckets/${m.bucketId || 'media'}/files/${m.$id}/view?project=${PROJECT_ID}`;
|
|
}
|
|
} catch (uploadErr) {
|
|
console.error('Error uploading file for entity config:', uploadErr);
|
|
}
|
|
}
|
|
} else {
|
|
// Solo incluir el campo si tiene valor real (evita errores en Appwrite con campos vacíos opcionales)
|
|
if (value !== '' && value !== null && value !== undefined) {
|
|
parsedData[key] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!parsedData || Object.keys(parsedData).length === 0) {
|
|
console.warn('updateEntityConfig: Data is empty, skipping update.');
|
|
return existing;
|
|
}
|
|
|
|
const SINGLETON_ID = existing?.$id || 'main_profile_singleton';
|
|
|
|
if (existing) {
|
|
const result = await databases.updateDocument(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
existing.$id,
|
|
parsedData
|
|
);
|
|
revalidatePath('/');
|
|
return result;
|
|
} else {
|
|
try {
|
|
const result = await databases.createDocument(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
SINGLETON_ID,
|
|
parsedData
|
|
);
|
|
revalidatePath('/');
|
|
return result;
|
|
} catch (createErr: any) {
|
|
// If the collection genuinely does not exist, auto-create it natively
|
|
if (createErr?.code === 404 && createErr?.type === 'collection_not_found') {
|
|
console.log('Colección entity_config no existe. Creando automáticamente...');
|
|
await databases.createCollection(DATABASE_ID, COLLECTION_ID, 'Configuración de Entidad');
|
|
await new Promise(r => setTimeout(r, 1500)); // Propagate
|
|
|
|
// Create minimal schema attributes lazily, Appwrite handles conflicts on re-runs
|
|
const textAttrs = ['razon_social', 'logotipo', 'ciudad', 'direccion', 'numero_contacto', 'numero_whatsapp', 'email', 'sitio_web', 'tv_url', 'radio_url', 'facebook_url', 'instagram_url', 'x_url', 'youtube_url', 'telegram_url'];
|
|
for (const a of textAttrs) {
|
|
try { await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, a, 500, false); } catch (e) {}
|
|
}
|
|
try { await databases.createBooleanAttribute(DATABASE_ID, COLLECTION_ID, 'mostrar_texto_logo', false, false); } catch(e){}
|
|
|
|
console.log('Atributos inyectados. Esperando 3 segundos...');
|
|
await new Promise(r => setTimeout(r, 3500)); // Wait for attributes to be Available
|
|
|
|
const result = await databases.createDocument(DATABASE_ID, COLLECTION_ID, SINGLETON_ID, parsedData);
|
|
revalidatePath('/');
|
|
return result;
|
|
} else {
|
|
throw createErr;
|
|
}
|
|
}
|
|
}
|
|
} catch (error: any) {
|
|
console.error('Error updating entity config:', error);
|
|
// Devolver un objeto de error estructurado en lugar de relanzar para evitar crash de la página
|
|
return {
|
|
success: false,
|
|
error: error?.message || 'Error desconocido al guardar la configuración de la entidad.'
|
|
};
|
|
}
|
|
}
|
|
|
|
// ALIAS PARA COMPATIBILIDAD CON DASHBOARD
|
|
export const updateEntity = updateEntityConfig;
|