import React, { useCallback, useRef, useState } from 'react' import axios from 'axios' import EmojiPickerButton from './EmojiPickerButton' /** * Comment form with emoji picker and Markdown-lite support. * * Props: * artworkId number Target artwork * onPosted (comment) => void Called when comment is successfully posted * isLoggedIn boolean * loginUrl string Where to redirect non-authenticated users */ export default function CommentForm({ artworkId, onPosted, isLoggedIn = false, loginUrl = '/login', }) { const [content, setContent] = useState('') const [submitting, setSubmitting] = useState(false) const [errors, setErrors] = useState([]) const textareaRef = useRef(null) // Insert text at current cursor position const insertAtCursor = useCallback((text) => { const el = textareaRef.current if (!el) { setContent((v) => v + text) return } const start = el.selectionStart ?? content.length const end = el.selectionEnd ?? content.length const next = content.slice(0, start) + text + content.slice(end) setContent(next) // Restore cursor after the inserted text requestAnimationFrame(() => { el.selectionStart = start + text.length el.selectionEnd = start + text.length el.focus() }) }, [content]) const handleEmojiSelect = useCallback((emoji) => { insertAtCursor(emoji) }, [insertAtCursor]) const handleSubmit = useCallback( async (e) => { e.preventDefault() if (!isLoggedIn) { window.location.href = loginUrl return } const trimmed = content.trim() if (!trimmed) return setSubmitting(true) setErrors([]) try { const { data } = await axios.post(`/api/artworks/${artworkId}/comments`, { content: trimmed, }) setContent('') onPosted?.(data.data) } catch (err) { if (err.response?.status === 422) { const apiErrors = err.response.data?.errors?.content ?? ['Invalid content.'] setErrors(Array.isArray(apiErrors) ? apiErrors : [apiErrors]) } else { setErrors(['Something went wrong. Please try again.']) } } finally { setSubmitting(false) } }, [artworkId, content, isLoggedIn, loginUrl, onPosted], ) if (!isLoggedIn) { return (
Sign in {' '} to leave a comment.
) } return (
{/* Textarea */}