'use client';
import { useState, useEffect, useTransition } from 'react';
import { useRouter } from 'next/navigation';
import { ArrowLeft, Save, Globe, Calendar, Tag, Image as ImageIcon, Eye, Code } from 'lucide-react';
import Link from 'next/link';
import { FieldDefinition } from '@/lib/schema';
import { MediaPickerMini } from './MediaPickerMini';
import { RichTextEditor } from './RichTextEditor';
import { QuickCreateModal } from './QuickCreateModal';
import { collectionMap } from '@/lib/schema';
import { Client, Databases } from 'appwrite';
// Minimalistic image preview for relations with 'media'
const MediaPreview = ({ fileId, bucketId, endpoint, projectId }: any) => {
if(!fileId) return null;
const url = `${endpoint}/storage/buckets/${bucketId}/files/${fileId}/view?project=${projectId}`;
return (
// eslint-disable-next-line @next/next/no-img-element
Imagen Seleccionada
);
}
interface EntityFormProps {
entity: string;
entityName: string;
initialData?: any;
fields: FieldDefinition[];
relationData: Record;
submitAction: (formData: FormData) => Promise;
appwriteConfig: {
endpoint: string;
projectId: string;
}
}
export const EntityForm = ({
entity,
entityName,
initialData,
fields,
relationData,
submitAction,
appwriteConfig
}: EntityFormProps) => {
const router = useRouter();
const [isPending, startTransition] = useTransition();
const [title, setTitle] = useState(initialData?.titulo || initialData?.nombre || '');
const [slug, setSlug] = useState(initialData?.slug || '');
const [isAutoSlug, setIsAutoSlug] = useState(!initialData?.slug);
const [featuredImageId, setFeaturedImageId] = useState(initialData?.imagen_destacada_id || '');
const [editorValues, setEditorValues] = useState>({});
const [localRelationData, setLocalRelationData] = useState(relationData);
const [activeTab, setActiveTab] = useState('');
const [isModalOpen, setIsModalOpen] = useState(false);
const [modalEntity, setModalEntity] = useState('');
const [activeRelationField, setActiveRelationField] = useState('');
// Initialize editor values
useEffect(() => {
const initialValues: Record = {};
fields.forEach(f => {
if (f.type === 'textarea') {
initialValues[f.name] = initialData?.[f.name] || '';
}
});
setEditorValues(initialValues);
}, [fields, initialData]);
// Update slug automatically if auto-slug is enabled
useEffect(() => {
if (isAutoSlug) {
const generated = title
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
setSlug(generated);
}
}, [title, isAutoSlug]);
const sections = Array.from(new Set(fields.map(f => f.section || 'General')));
useEffect(() => {
if (sections.length > 0 && !activeTab) {
setActiveTab(sections[0]);
}
}, [sections, activeTab]);
const refreshRelation = async (field: string, collectionId: string) => {
const client = new Client()
.setEndpoint(appwriteConfig.endpoint)
.setProject(appwriteConfig.projectId);
const databases = new Databases(client);
try {
const res = await databases.listDocuments('almeira', collectionId, []);
setLocalRelationData(prev => ({ ...prev, [field]: res.documents }));
} catch (err) {
console.error("Error al refrescar relación:", err);
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
// Add editor values to formData
for (const [key, value] of Object.entries(editorValues)) {
formData.set(key, value);
}
// Ensure featured image ID is set if present
if (featuredImageId) {
formData.set('imagen_destacada_id', featuredImageId);
}
startTransition(async () => {
await submitAction(formData);
});
};
// Organize fields into Main Content and Sidebar Metadata
const sidebarFieldNames = ['estado', 'fecha_publicacion', 'fecha_finalizacion', 'slug', 'imagen_destacada_id', 'categoria_id', 'tipo_publicacion_id'];
const mainFields = fields.filter(f => !sidebarFieldNames.includes(f.name));
const sidebarFields = fields.filter(f => sidebarFieldNames.includes(f.name));
const getDefValue = (field: FieldDefinition) => {
const val = initialData ? initialData[field.name] : null;
// Set smart defaults for new items
if (!initialData) {
if (field.name === 'estado') return 'borrador';
if (field.name === 'fecha_publicacion' || field.type === 'date') {
// Get local ISO string for datetime-local input
const now = new Date();
return new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString().slice(0, 16);
}
if (field.type === 'boolean') return 'false';
}
if (val === undefined || val === null) return '';
if (field.type === 'boolean') return val ? 'true' : 'false';
if (field.type === 'date') return new Date(val).toISOString().slice(0, 16);
if (field.type === 'relation') return typeof val === 'object' ? val.$id : val;
return val;
};
return (
<>
setIsModalOpen(false)}
onSuccess={async (newId) => {
const relField = fields.find(f => f.name === activeRelationField);
if (relField?.relationCollection) {
await refreshRelation(activeRelationField, collectionMap[relField.relationCollection]);
// Set wait to ensure state has updated options before selecting
setTimeout(() => {
const selectElement = document.querySelector(`select[name="${activeRelationField}"]`) as HTMLSelectElement;
if (selectElement) {
selectElement.value = newId;
}
}, 1000);
}
}}
/>
>
);
};