Unify portal thread rows and add summary API

This commit is contained in:
Micha
2026-01-16 02:44:04 +01:00
parent f9de433545
commit 24c16ed0dd
12 changed files with 380 additions and 188 deletions

View File

@@ -0,0 +1,91 @@
import { Link } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
export default function PortalTopicRow({ thread, forumName, forumId, showForum = true }) {
const { t } = useTranslation()
const authorName = thread.user_name || t('thread.anonymous')
const lastAuthorName = thread.last_post_user_name || authorName
const lastPostAnchor = thread.last_post_id ? `#post-${thread.last_post_id}` : ''
const formatDateTime = (value) => {
if (!value) return '—'
const date = new Date(value)
if (Number.isNaN(date.getTime())) return '—'
const day = String(date.getDate()).padStart(2, '0')
const month = String(date.getMonth() + 1).padStart(2, '0')
const year = String(date.getFullYear())
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`
}
return (
<div className="bb-portal-topic-row">
<div className="bb-portal-topic-main">
<span className="bb-portal-topic-icon" aria-hidden="true">
<i className="bi bi-chat-left-text" />
</span>
<div>
<Link to={`/thread/${thread.id}`} className="bb-portal-topic-title">
{thread.title}
</Link>
<div className="bb-portal-topic-meta">
<div className="bb-portal-topic-meta-line">
<span className="bb-portal-topic-meta-label">{t('portal.posted_by')}</span>
{thread.user_id ? (
<Link to={`/profile/${thread.user_id}`} className="bb-portal-topic-author">
{authorName}
</Link>
) : (
<span className="bb-portal-topic-author">{authorName}</span>
)}
<span className="bb-portal-topic-meta-sep">»</span>
<span className="bb-portal-topic-meta-date">{formatDateTime(thread.created_at)}</span>
</div>
{showForum && (
<div className="bb-portal-topic-meta-line">
<span className="bb-portal-topic-meta-label">{t('portal.forum_label')}</span>
<span className="bb-portal-topic-forum">
{forumId ? (
<Link to={`/forum/${forumId}`} className="bb-portal-topic-forum-link">
{forumName}
</Link>
) : (
forumName
)}
</span>
</div>
)}
</div>
</div>
</div>
<div className="bb-portal-topic-cell">{thread.posts_count ?? 0}</div>
<div className="bb-portal-topic-cell">{thread.views_count ?? 0}</div>
<div className="bb-portal-topic-cell bb-portal-topic-cell--last">
<div className="bb-portal-last">
<span className="bb-portal-last-by">
{t('thread.by')}{' '}
{thread.last_post_user_id ? (
<Link to={`/profile/${thread.last_post_user_id}`} className="bb-portal-last-user">
{lastAuthorName}
</Link>
) : (
<span className="bb-portal-last-user">{lastAuthorName}</span>
)}
<Link
to={`/thread/${thread.id}${lastPostAnchor}`}
className="bb-portal-last-jump ms-2"
aria-label={t('thread.view')}
>
<i className="bi bi-eye" aria-hidden="true" />
</Link>
</span>
<span className="bb-portal-last-date">
{formatDateTime(thread.last_post_at || thread.created_at)}
</span>
</div>
</div>
</div>
)
}