'use client'; /** * NOVA CMS - CONVERSATIONAL CONTENT CREATOR * ========================================== * * Una experiencia de creación de contenido conversacional e interactiva, * que no parece un formulario tradicional sino un asistente inteligente. */ import { useForm, FormProvider } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Switch } from '@/components/ui/switch'; import { FormField, FormItem, FormLabel, FormControl, FormMessage } from '@/components/ui/form'; import { useToast } from '@/hooks/use-toast'; import { ArrowRight, Sparkles, MessageCircle, Edit3, Calendar, Hash, ToggleRight, Image, CheckCircle2, Bot, FileText } from 'lucide-react'; import { cn } from '@/lib/utils'; // Types para el contenido dinámico interface Field { id: string; label: string; apiIdentifier: string; type: 'TEXT' | 'RICH_TEXT' | 'NUMBER' | 'BOOLEAN' | 'DATE' | 'MEDIA'; isRequired: boolean; } interface ContentType { id: string; name: string; apiIdentifier: string; description?: string; fields: Field[]; } interface DynamicContentFormProps { contentType: ContentType; initialData?: Record; entryId?: string; mode?: 'create' | 'edit'; onSave?: (data: Record) => Promise; } // Generador de schema dinámico basado en fields function generateDynamicSchema(fields: Field[]) { const schemaShape: Record = {}; fields.forEach(field => { let fieldValidator; switch (field.type) { case 'TEXT': case 'RICH_TEXT': case 'MEDIA': fieldValidator = z.string(); if (field.isRequired) { fieldValidator = fieldValidator.min(1, `${field.label} es requerido`); } break; case 'NUMBER': fieldValidator = z.number(); if (field.isRequired) { fieldValidator = fieldValidator.min(0, `${field.label} debe ser un número válido`); } break; case 'BOOLEAN': fieldValidator = z.boolean(); break; case 'DATE': fieldValidator = z.string(); if (field.isRequired) { fieldValidator = fieldValidator.min(1, `${field.label} es requerido`); } break; default: fieldValidator = z.string(); } if (!field.isRequired) { fieldValidator = fieldValidator.optional(); } schemaShape[field.apiIdentifier] = fieldValidator; }); return z.object(schemaShape); } // Componente de conversación para cada campo function ConversationField({ field, control, isActive, onNext }: { field: Field; control: any; isActive: boolean; onNext?: () => void; }) { const getFieldEmoji = (type: Field['type']) => { switch (type) { case 'TEXT': return '✍️'; case 'RICH_TEXT': return '📝'; case 'NUMBER': return '🔢'; case 'BOOLEAN': return '⚡'; case 'DATE': return '📅'; case 'MEDIA': return '🖼️'; default: return '💭'; } }; const getConversationalPrompt = (field: Field) => { switch (field.type) { case 'TEXT': return `Hola! 👋 Me puedes contar ${field.label.toLowerCase()}?`; case 'RICH_TEXT': return `Perfecto! Ahora cuéntame más sobre ${field.label.toLowerCase()}. Puedes escribir todo lo que quieras aquí:`; case 'NUMBER': return `¿Cuál sería el valor numérico para ${field.label.toLowerCase()}?`; case 'BOOLEAN': return `Una pregunta rápida: ¿${field.label.toLowerCase()}?`; case 'DATE': return `¿Cuándo sería la fecha para ${field.label.toLowerCase()}?`; case 'MEDIA': return `¡Genial! ¿Tienes alguna imagen o archivo para ${field.label.toLowerCase()}? Puedes pegar la URL aquí:`; default: return `Cuéntame sobre ${field.label.toLowerCase()}:`; } }; return ( (
{/* Mensaje del asistente mejorado */}
{getFieldEmoji(field.type)}
{field.label} {field.isRequired && ( Campo Importante )}

{getConversationalPrompt(field)}

{/* Respuesta del usuario mejorada */}
{field.type === 'TEXT' && ( { if (e.key === 'Enter' && onNext) { onNext(); } }} /> )} {field.type === 'RICH_TEXT' && (