import ReactDOM from 'react-dom' import { useState, useRef } from 'react' import { Plus, X } from 'lucide-react' import { useCanDo } from '../../store/permissionsStore' import { useTripStore } from '../../store/tripStore' import { FONT } from './CollabNotes.constants' import { AuthedImg } from './CollabNotesAuthedImg' import type { CollabNote } from './CollabNotes.types' // ── New Note Modal (portal to body) ───────────────────────────────────────── interface NoteFormModalProps { onClose: () => void onSubmit: (data: { title: string; content: string; category: string | null; website: string | null; color?: string | null; _pendingFiles?: File[]; files?: File[] }) => Promise onDeleteFile?: (noteId: number, fileId: number) => Promise existingCategories: string[] categoryColors: Record getCategoryColor: (category: string) => string note: CollabNote | null tripId: number t: (key: string) => string } export function NoteFormModal({ onClose, onSubmit, onDeleteFile, existingCategories, categoryColors, getCategoryColor, note, tripId, t }: NoteFormModalProps) { const can = useCanDo() const tripObj = useTripStore((s) => s.trip) const canUploadFiles = can('file_upload', tripObj) const isEdit = !!note const allCategories = [...new Set([...existingCategories, ...Object.keys(categoryColors || {})])].filter(Boolean) const [title, setTitle] = useState(note?.title || '') const [content, setContent] = useState(note?.content || '') const [category, setCategory] = useState(note?.category || allCategories[0] || '') const [website, setWebsite] = useState(note?.website || '') const [pendingFiles, setPendingFiles] = useState([]) const [existingAttachments, setExistingAttachments] = useState(note?.attachments || []) const [submitting, setSubmitting] = useState(false) const fileRef = useRef(null) const finalCategory = category const handleSubmit = async (e) => { e.preventDefault() if (!title.trim()) return setSubmitting(true) try { await onSubmit({ title: title.trim(), content: content.trim(), category: finalCategory || null, color: getCategoryColor(finalCategory), website: website.trim() || null, _pendingFiles: pendingFiles, }) onClose() } catch { } finally { setSubmitting(false) } } const handleDeleteAttachment = async (fileId) => { if (onDeleteFile && note) { await onDeleteFile(note.id, fileId) setExistingAttachments(prev => prev.filter(a => a.id !== fileId)) } } const canSubmit = title.trim() && !submitting return ReactDOM.createPortal(
e.stopPropagation()} onPaste={e => { if (!canUploadFiles) return const items = e.clipboardData?.items if (!items) return for (const item of Array.from(items)) { if (item.type.startsWith('image/') || item.type === 'application/pdf') { e.preventDefault() const file = item.getAsFile() if (file) setPendingFiles(prev => [...prev, file]) return } } }} onSubmit={handleSubmit} > {/* Modal header */}

{isEdit ? t('collab.notes.edit') : t('collab.notes.new')}

{/* Modal body */}
{/* Title */}
{t('collab.notes.title')}
setTitle(e.target.value)} placeholder={t('collab.notes.titlePlaceholder')} style={{ width: '100%', border: '1px solid var(--border-primary)', borderRadius: 10, padding: '8px 12px', fontSize: 13, background: 'var(--bg-input)', color: 'var(--text-primary)', fontFamily: 'inherit', outline: 'none', boxSizing: 'border-box', }} />
{/* Content */}
{t('collab.notes.contentPlaceholder')}