'use client' import { useState, useRef, useEffect, useCallback } from 'react' import { useRouter } from 'next/navigation' import { toast } from 'sonner' import { Input } from '@/components/ui/input' import { Textarea } from '@/components/ui/textarea' import { cn } from '@/lib/utils' import { Plus, Loader2, Text, Sparkles, X } from 'lucide-react' import { inferNoteType, formatContentForType } from '@/lib/type-inference' import { NoteType } from '@/types/note' interface TypeSuggestion { type: NoteType confidence: 'high' | 'medium' | 'low' reason: string formattedContent: string } const TYPE_LABELS: Record = { command: 'Comando', snippet: 'Snippet', procedure: 'Procedimiento', recipe: 'Receta', decision: 'Decisión', inventory: 'Inventario', note: 'Nota', } export function QuickAdd() { const [value, setValue] = useState('') const [isLoading, setIsLoading] = useState(false) const [isExpanded, setIsExpanded] = useState(false) const [isMultiline, setIsMultiline] = useState(false) const [typeSuggestion, setTypeSuggestion] = useState(null) const [dismissedSuggestion, setDismissedSuggestion] = useState(false) const inputRef = useRef(null) const textareaRef = useRef(null) const router = useRouter() const detectContentType = useCallback((text: string) => { if (!text.trim() || text.length < 10) { setTypeSuggestion(null) return } if (dismissedSuggestion) return const suggestion = inferNoteType(text) if (suggestion && suggestion.confidence === 'high') { const formatted = formatContentForType(text, suggestion.type) setTypeSuggestion({ ...suggestion, formattedContent: formatted, }) } else { setTypeSuggestion(null) } }, [dismissedSuggestion]) const handlePaste = (e: React.ClipboardEvent) => { // Let the paste happen first setDismissedSuggestion(false) setTimeout(() => { detectContentType(value) }, 0) } const acceptSuggestion = () => { if (typeSuggestion) { setValue(typeSuggestion.formattedContent) setTypeSuggestion(null) setIsMultiline(true) setIsExpanded(true) } } const dismissSuggestion = () => { setTypeSuggestion(null) setDismissedSuggestion(true) } const handleSubmit = async (e?: React.FormEvent) => { e?.preventDefault() if (!value.trim() || isLoading) return setIsLoading(true) try { const response = await fetch('/api/notes/quick', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: value }), }) if (!response.ok) { const error = await response.json() throw new Error(error.error || 'Error creating note') } const note = await response.json() toast.success('Nota creada', { description: note.title, }) setValue('') setIsExpanded(false) router.refresh() } catch (error) { toast.error('Error', { description: error instanceof Error ? error.message : 'No se pudo crear la nota', }) } finally { setIsLoading(false) } } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey && !isMultiline) { e.preventDefault() handleSubmit() } if (e.key === 'Escape') { setValue('') setIsExpanded(false) setIsMultiline(false) inputRef.current?.blur() textareaRef.current?.blur() } } const toggleMultiline = () => { setIsMultiline(!isMultiline) if (!isMultiline) { setIsExpanded(true) setTimeout(() => textareaRef.current?.focus(), 0) } } // Focus on keyboard shortcut useEffect(() => { const handleGlobalKeyDown = (e: KeyboardEvent) => { // Ctrl+N or Cmd+N to focus quick add if ((e.key === 'n' && (e.metaKey || e.ctrlKey)) || (e.key === 'n' && e.altKey)) { e.preventDefault() inputRef.current?.focus() inputRef.current?.select() setIsExpanded(true) } // Escape to blur if (e.key === 'Escape' && document.activeElement === inputRef.current) { inputRef.current?.blur() setIsExpanded(false) } } window.addEventListener('keydown', handleGlobalKeyDown) return () => window.removeEventListener('keydown', handleGlobalKeyDown) }, []) return (
{isMultiline ? (