// --------------------------------------------------------------------------- // DataForm — pre-built form component wired to AnyDB insertOne // --------------------------------------------------------------------------- // PRE-INSTALLED. CodeWriterAgent just uses: // import { DataForm } from "@/components/DataForm" // // --------------------------------------------------------------------------- import { useState } from "react"; import { useMutation } from "@/hooks/use-anydb"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { useToast } from "@/hooks/use-toast"; import { Loader2, CheckCircle } from "lucide-react"; interface FormField { name: string; label: string; type?: "text" | "email" | "tel" | "number" | "date" | "time" | "url" | "textarea" | "select"; placeholder?: string; required?: boolean; options?: { value: string; label: string }[]; // For select type rows?: number; // For textarea min?: number; max?: number; defaultValue?: string | number; className?: string; gridCol?: number; // 1 or 2 — for grid layout } interface DataFormProps { collection: string; fields: FormField[]; submitLabel?: string; successMessage?: string; onSuccess?: (data: any) => void; className?: string; layout?: "stack" | "grid"; // stack = vertical, grid = 2-col } export function DataForm({ collection, fields, submitLabel = "Submit", successMessage = "Saved successfully!", onSuccess, className = "", layout = "stack", }: DataFormProps) { const { toast } = useToast(); const { mutate, loading } = useMutation(collection); const [submitted, setSubmitted] = useState(false); // Build initial form state from fields const initialState: Record = {}; fields.forEach(f => { initialState[f.name] = f.defaultValue || ""; }); const [formData, setFormData] = useState(initialState); const handleChange = (name: string, value: any) => { setFormData(prev => ({ ...prev, [name]: value })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); // Basic validation for (const field of fields) { if (field.required && !formData[field.name]) { toast({ title: "Required field", description: `Please fill in ${field.label}`, variant: "destructive", }); return; } if (field.type === "email" && formData[field.name] && !formData[field.name].includes("@")) { toast({ title: "Invalid email", description: "Please enter a valid email address", variant: "destructive", }); return; } } try { const result = await mutate(formData); setSubmitted(true); toast({ title: "Success", description: successMessage }); setFormData(initialState); onSuccess?.(result); // Reset submitted state after 3 seconds setTimeout(() => setSubmitted(false), 3000); } catch (err) { toast({ title: "Error", description: "Something went wrong. Please try again.", variant: "destructive", }); } }; const renderField = (field: FormField) => { const id = `form-${collection}-${field.name}`; return (
{field.type === "textarea" ? (