import React, { useState, useCallback } from 'react'
import Breadcrumbs from '../../components/forum/Breadcrumbs'
import PostCard from '../../components/forum/PostCard'
import ReplyForm from '../../components/forum/ReplyForm'
import Pagination from '../../components/forum/Pagination'
export default function ForumThread({
thread,
category,
forumCategory,
author,
opPost,
posts = [],
pagination = {},
replyCount = 0,
sort = 'asc',
quotedPost = null,
replyPrefill = '',
isAuthenticated = false,
canModerate = false,
csrfToken = '',
status = null,
captcha = {},
}) {
const [currentSort, setCurrentSort] = useState(sort)
const breadcrumbs = [
{ label: 'Home', href: '/' },
{ label: 'Forum', href: '/forum' },
...(forumCategory?.name ? [{ label: forumCategory.name }] : []),
{ label: category?.name ?? 'Board', href: category?.slug ? `/forum/${category.slug}` : '/forum' },
{ label: thread?.title ?? 'Thread' },
]
const handleSortToggle = useCallback(() => {
const newSort = currentSort === 'asc' ? 'desc' : 'asc'
setCurrentSort(newSort)
const url = new URL(window.location.href)
url.searchParams.set('sort', newSort)
window.location.href = url.toString()
}, [currentSort])
return (
{/* Status flash */}
{status && (
{status}
)}
{/* Thread header card */}
{thread?.title}
By {author?.name ?? 'Unknown'}
•
{thread?.created_at && (
)}
{number(thread?.views ?? 0)} views
{number(replyCount)} replies
{thread?.is_pinned && (
Pinned
)}
{thread?.is_locked && (
Locked
)}
{/* Moderation tools */}
{canModerate && (
{thread?.is_locked ? (
) : (
)}
{thread?.is_pinned ? (
) : (
)}
)}
{/* Sort toggle + reply count */}
{number(replyCount)} {replyCount === 1 ? 'reply' : 'replies'}
{/* OP Post */}
{opPost && (
)}
{/* Reply list */}
{posts.length === 0 ? (
No replies yet. Be the first to respond!
) : (
posts.map((post) => (
))
)}
{/* Pagination */}
{pagination?.last_page > 1 && (
)}
{/* Reply form or locked / auth prompt */}
{isAuthenticated ? (
thread?.is_locked ? (
This thread is locked. Replies are disabled.
) : (
)
) : (
)}
)
}
function ModForm({ action, csrf, label, variant }) {
const colors = variant === 'danger'
? 'bg-red-500/15 text-red-300 hover:bg-red-500/25 border-red-500/20'
: 'bg-amber-500/15 text-amber-300 hover:bg-amber-500/25 border-amber-500/20'
return (
)
}
function number(n) {
return (n ?? 0).toLocaleString()
}
function formatDate(dateStr) {
try {
const d = new Date(dateStr)
return d.toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })
+ ' ' + d.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })
} catch {
return ''
}
}