Files
SkinbaseNova/resources/js/components/forum/ReplyForm.jsx
2026-03-12 07:22:38 +01:00

83 lines
2.3 KiB
JavaScript

import React, { useState, useRef, useCallback } from 'react'
import Button from '../ui/Button'
import RichTextEditor from './RichTextEditor'
export default function ReplyForm({ topicKey, prefill = '', quotedAuthor = null, csrfToken }) {
const [content, setContent] = useState(prefill)
const [submitting, setSubmitting] = useState(false)
const [error, setError] = useState(null)
const formRef = useRef(null)
const handleSubmit = useCallback(async (e) => {
e.preventDefault()
if (submitting || content.trim().length < 2) return
setSubmitting(true)
setError(null)
try {
const res = await fetch(`/forum/topic/${topicKey}/reply`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken,
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
credentials: 'same-origin',
body: JSON.stringify({ content: content.trim() }),
})
if (res.ok) {
// Reload page to show new reply
window.location.reload()
} else if (res.status === 422) {
const json = await res.json()
setError(json.errors?.content?.[0] ?? 'Validation error.')
} else {
setError('Failed to post reply. Please try again.')
}
} catch {
setError('Network error. Please try again.')
}
setSubmitting(false)
}, [content, topicKey, csrfToken, submitting])
return (
<form
ref={formRef}
onSubmit={handleSubmit}
className="space-y-4 rounded-2xl border border-white/[0.06] bg-nova-800/50 p-5 backdrop-blur"
>
{quotedAuthor && (
<p className="text-xs text-cyan-400/70">
Replying with quote from <strong className="text-cyan-300">{quotedAuthor}</strong>
</p>
)}
{/* Rich text editor */}
<RichTextEditor
content={content}
onChange={setContent}
placeholder="Write your reply…"
error={error}
minHeight={10}
/>
{/* Submit */}
<div className="flex items-center justify-end">
<Button
type="submit"
variant="primary"
size="md"
loading={submitting}
disabled={content.trim().length < 2}
>
Post reply
</Button>
</div>
</form>
)
}