This commit is contained in:
@@ -9,6 +9,7 @@ $search = trim((string)($_GET['q'] ?? ''));
|
||||
|
||||
$communityCfg = require __DIR__ . '/../../../config/community.php';
|
||||
$community = $pdo ? new \App\Community($pdo, $communityCfg) : null;
|
||||
$stats = $community ? $community->getStats() : ['threads' => 0, 'posts' => 0, 'members' => 0];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'thread_create') {
|
||||
if (!$userId) {
|
||||
@@ -29,52 +30,102 @@ $threads = $community ? ($search !== '' ? $community->searchThreads($search, 50)
|
||||
?>
|
||||
<main class="section">
|
||||
<div class="container">
|
||||
<p class="eyebrow">Community</p>
|
||||
<h1>Forum</h1>
|
||||
<div class="forum-hero">
|
||||
<div>
|
||||
<div class="forum-breadcrumbs">
|
||||
<a href="/">Home</a>
|
||||
<span>/</span>
|
||||
<span>Community</span>
|
||||
</div>
|
||||
<h1>Community</h1>
|
||||
<p class="forum-hero__copy">Fragen stellen, Erfahrungen teilen, Antworten finden und gemeinsam weiterdenken.</p>
|
||||
</div>
|
||||
<div class="forum-hero__actions">
|
||||
<?php if ($userId): ?>
|
||||
<button class="btn" type="button" data-modal-open="modalThread">Neues Thema</button>
|
||||
<?php else: ?>
|
||||
<a class="btn" href="/login">Einloggen und schreiben</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="toast-bar" style="border-color:#f87171; color:#991b1b;"><?= htmlspecialchars($error, ENT_QUOTES) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="flex between center-y" style="margin:14px 0; gap:12px; flex-wrap:wrap;">
|
||||
<form method="get" class="flex gap-8" style="flex-wrap:wrap; align-items:flex-end;">
|
||||
<div class="stack gap-4">
|
||||
<label class="label" for="searchQ">Suche nach Stichwort</label>
|
||||
<input id="searchQ" name="q" class="input" value="<?= htmlspecialchars($search, ENT_QUOTES) ?>" placeholder="Schlagwort eingeben">
|
||||
<div class="forum-stats">
|
||||
<div class="forum-stat">
|
||||
<span class="forum-stat__label">Themen</span>
|
||||
<strong><?= number_format($stats['threads']) ?></strong>
|
||||
</div>
|
||||
<div class="forum-stat">
|
||||
<span class="forum-stat__label">Beiträge</span>
|
||||
<strong><?= number_format($stats['posts']) ?></strong>
|
||||
</div>
|
||||
<div class="forum-stat">
|
||||
<span class="forum-stat__label">Mitglieder</span>
|
||||
<strong><?= number_format($stats['members']) ?></strong>
|
||||
</div>
|
||||
<button class="btn" type="submit">Suchen</button>
|
||||
</form>
|
||||
<?php if ($userId): ?>
|
||||
<button class="btn" type="button" data-modal-open="modalThread">Neue Frage</button>
|
||||
<?php else: ?>
|
||||
<a class="btn ghost" href="/login">Login für neue Frage</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="stack gap-8" style="margin-top:10px;">
|
||||
<div class="forum-board">
|
||||
<div class="forum-board__head">
|
||||
<div>
|
||||
<h2>Forum</h2>
|
||||
<p class="muted">Hier findest du die neuesten Themen, Antworten und laufenden Gespräche.</p>
|
||||
</div>
|
||||
<form method="get" class="forum-search">
|
||||
<label class="label" for="searchQ">Suche</label>
|
||||
<div class="forum-search__row">
|
||||
<input id="searchQ" name="q" class="input" value="<?= htmlspecialchars($search, ENT_QUOTES) ?>" placeholder="Schlagwort eingeben">
|
||||
<button class="btn" type="submit">Suchen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="forum-list">
|
||||
<div class="forum-list__header">
|
||||
<span>Thema</span>
|
||||
<span>Antworten</span>
|
||||
<span>Letzte Aktivität</span>
|
||||
</div>
|
||||
|
||||
<?php foreach ($threads as $t): ?>
|
||||
<?php
|
||||
$pts = ($community && $pdo) ? $community->computePoints((int)$t['uid']) : 0.0;
|
||||
$lvl = $community ? $community->membershipLevel($pts) : ['label'=>'','icon'=>''];
|
||||
$preview = mb_substr((string)$t['body'], 0, 220);
|
||||
?>
|
||||
<article class="card" style="padding:14px;">
|
||||
<div class="event__body">
|
||||
<div class="event__meta" style="flex-wrap:wrap; gap:8px;">
|
||||
<span><?= htmlspecialchars($t['created_at'], ENT_QUOTES) ?></span>
|
||||
<article class="forum-row">
|
||||
<div class="forum-row__topic">
|
||||
<div class="forum-row__icon" aria-hidden="true">💬</div>
|
||||
<div>
|
||||
<h3><a href="/community_thread?id=<?= (int)$t['id'] ?>"><?= htmlspecialchars($t['title'], ENT_QUOTES) ?></a></h3>
|
||||
<div class="forum-row__meta">
|
||||
<span><?= htmlspecialchars($t['display_name'] ?: 'Mitglied', ENT_QUOTES) ?></span>
|
||||
<span><?= htmlspecialchars($lvl['icon'] ?? '', ENT_QUOTES) ?> <?= htmlspecialchars($lvl['label'] ?? '', ENT_QUOTES) ?> (<?= number_format($pts,1) ?> Punkte)</span>
|
||||
<span>Beiträge: <?= (int)$t['user_posts'] + (int)$t['answers'] ?></span>
|
||||
<span>Antworten: <?= (int)$t['answers'] ?></span>
|
||||
<span><?= htmlspecialchars($lvl['icon'] ?? '', ENT_QUOTES) ?> <?= htmlspecialchars($lvl['label'] ?? '', ENT_QUOTES) ?></span>
|
||||
<span><?= number_format($pts, 1) ?> Punkte</span>
|
||||
</div>
|
||||
<h3 style="margin:6px 0;"><a href="/community_thread?id=<?= (int)$t['id'] ?>"><?= htmlspecialchars($t['title'], ENT_QUOTES) ?></a></h3>
|
||||
<p class="muted small"><?= nl2br(htmlspecialchars(substr($t['body'], 0, 200), ENT_QUOTES)) ?><?= strlen($t['body']) > 200 ? '…' : '' ?></p>
|
||||
<p><?= nl2br(htmlspecialchars($preview, ENT_QUOTES)) ?><?= mb_strlen((string)$t['body']) > 220 ? '…' : '' ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="forum-row__count">
|
||||
<strong><?= (int)$t['answers'] ?></strong>
|
||||
<span>Antworten</span>
|
||||
</div>
|
||||
<div class="forum-row__activity">
|
||||
<strong><?= htmlspecialchars($t['last_activity_by'] ?: 'Mitglied', ENT_QUOTES) ?></strong>
|
||||
<span><?= htmlspecialchars($t['last_activity_at'], ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (!$threads): ?>
|
||||
<p class="muted">Keine Treffer.</p>
|
||||
<div class="forum-empty">Keine Themen gefunden.</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php if ($userId): ?>
|
||||
|
||||
@@ -32,33 +32,77 @@ if (!$thread) {
|
||||
echo "<p>Thread nicht gefunden.</p>";
|
||||
return;
|
||||
}
|
||||
|
||||
$threadAuthor = (string)($thread['display_name'] ?: 'Mitglied');
|
||||
$threadPoints = ($community && $pdo) ? $community->computePoints((int)$thread['user_id']) : 0.0;
|
||||
$threadLevel = $community ? $community->membershipLevel($threadPoints) : ['label' => '', 'icon' => ''];
|
||||
?>
|
||||
<main class="section">
|
||||
<div class="container">
|
||||
<p class="eyebrow">Community</p>
|
||||
<div class="forum-breadcrumbs">
|
||||
<a href="/">Home</a>
|
||||
<span>/</span>
|
||||
<a href="/community">Community</a>
|
||||
<span>/</span>
|
||||
<span><?= htmlspecialchars($thread['title'], ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
|
||||
<div class="forum-thread-head">
|
||||
<div>
|
||||
<h1><?= htmlspecialchars($thread['title'], ENT_QUOTES) ?></h1>
|
||||
<p class="muted">Von <?= htmlspecialchars($thread['display_name'] ?: 'Mitglied', ENT_QUOTES) ?> · <?= htmlspecialchars($thread['created_at'], ENT_QUOTES) ?></p>
|
||||
<article class="card" style="margin-top:12px;">
|
||||
<div class="event__body">
|
||||
<p><?= nl2br(htmlspecialchars($thread['body'], ENT_QUOTES)) ?></p>
|
||||
<p class="forum-thread-head__meta">Erstellt von <?= htmlspecialchars($threadAuthor, ENT_QUOTES) ?> am <?= htmlspecialchars($thread['created_at'], ENT_QUOTES) ?></p>
|
||||
</div>
|
||||
<div class="forum-thread-head__meta-box">
|
||||
<strong><?= count($posts) ?></strong>
|
||||
<span>Antworten</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<article class="forum-post forum-post--lead">
|
||||
<aside class="forum-post__author">
|
||||
<div class="forum-post__avatar" aria-hidden="true"><?= strtoupper(mb_substr($threadAuthor, 0, 1)) ?></div>
|
||||
<strong><?= htmlspecialchars($threadAuthor, ENT_QUOTES) ?></strong>
|
||||
<span><?= htmlspecialchars($threadLevel['icon'] ?? '', ENT_QUOTES) ?> <?= htmlspecialchars($threadLevel['label'] ?? '', ENT_QUOTES) ?></span>
|
||||
<span><?= number_format($threadPoints, 1) ?> Punkte</span>
|
||||
</aside>
|
||||
<div class="forum-post__body">
|
||||
<div class="forum-post__head">
|
||||
<span><?= htmlspecialchars($thread['created_at'], ENT_QUOTES) ?></span>
|
||||
<span>#1</span>
|
||||
</div>
|
||||
<div class="forum-post__content">
|
||||
<?= nl2br(htmlspecialchars($thread['body'], ENT_QUOTES)) ?>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<h3 style="margin-top:16px;">Antworten (<?= count($posts) ?>)</h3>
|
||||
<div class="stack gap-12" style="margin-top:10px;">
|
||||
<?php foreach ($posts as $p): ?>
|
||||
<article class="card">
|
||||
<div class="event__body">
|
||||
<div class="event__meta">
|
||||
<span><?= htmlspecialchars($p['created_at'], ENT_QUOTES) ?></span>
|
||||
<span><?= htmlspecialchars($p['display_name'] ?: 'Mitglied', ENT_QUOTES) ?></span>
|
||||
<div class="forum-replies-head">
|
||||
<h2>Antworten</h2>
|
||||
<span><?= count($posts) ?> Beitrag/Beiträge</span>
|
||||
</div>
|
||||
|
||||
<div class="forum-replies">
|
||||
<?php foreach ($posts as $p): ?>
|
||||
<?php
|
||||
$postAuthor = (string)($p['display_name'] ?: 'Mitglied');
|
||||
?>
|
||||
<article class="forum-post">
|
||||
<aside class="forum-post__author">
|
||||
<div class="forum-post__avatar" aria-hidden="true"><?= strtoupper(mb_substr($postAuthor, 0, 1)) ?></div>
|
||||
<strong><?= htmlspecialchars($postAuthor, ENT_QUOTES) ?></strong>
|
||||
</aside>
|
||||
<div class="forum-post__body">
|
||||
<div class="forum-post__head">
|
||||
<span><?= htmlspecialchars($p['created_at'], ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
<div class="forum-post__content">
|
||||
<?= nl2br(htmlspecialchars($p['body'], ENT_QUOTES)) ?>
|
||||
</div>
|
||||
<p><?= nl2br(htmlspecialchars($p['body'], ENT_QUOTES)) ?></p>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
<?php if (!$posts): ?>
|
||||
<p class="muted">Noch keine Antworten.</p>
|
||||
<div class="forum-empty">Noch keine Antworten.</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
@@ -67,7 +111,7 @@ if (!$thread) {
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($userId): ?>
|
||||
<form method="post" class="stack gap-12 card" style="margin-top:14px; padding:16px;">
|
||||
<form method="post" class="forum-reply-form">
|
||||
<input type="hidden" name="action" value="reply">
|
||||
<div class="stack gap-6">
|
||||
<label class="label" for="replyBody">Antwort</label>
|
||||
@@ -76,7 +120,7 @@ if (!$thread) {
|
||||
<button class="btn" type="submit">Antwort senden</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<p class="muted" style="margin-top:12px;">Bitte <a href="/login">einloggen</a>, um zu antworten.</p>
|
||||
<div class="forum-login-note">Bitte <a href="/login">einloggen</a>, um zu antworten.</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -148,6 +148,55 @@ body {
|
||||
.page-copy p { margin: 0; font-size: 18px; line-height: 1.7; color: var(--color-text); }
|
||||
.section__intro p { margin: 0; font-size: 18px; line-height: 1.7; color: var(--color-text); text-align: left; }
|
||||
.section__intro p + p { margin-top: 18px; }
|
||||
.forum-breadcrumbs { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; color: var(--color-muted); font-size: 14px; margin-bottom: 16px; }
|
||||
.forum-breadcrumbs a:hover { color: var(--color-primary); }
|
||||
.forum-hero { display: flex; justify-content: space-between; align-items: flex-end; gap: 20px; padding: 26px 28px; background: linear-gradient(135deg, #fffdf8, #f8f2e7); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); }
|
||||
.forum-hero h1 { margin: 6px 0 8px; }
|
||||
.forum-hero__copy { margin: 0; max-width: 70ch; color: var(--color-muted); font-size: 16px; }
|
||||
.forum-hero__actions { display: flex; align-items: center; gap: 12px; }
|
||||
.forum-stats { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 14px; margin: 18px 0 24px; }
|
||||
.forum-stat { padding: 18px 20px; background: #fff; border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-card); }
|
||||
.forum-stat strong { display: block; font-size: 28px; line-height: 1.1; }
|
||||
.forum-stat__label { display: block; margin-bottom: 8px; color: var(--color-muted); font-size: 13px; text-transform: uppercase; letter-spacing: .4px; }
|
||||
.forum-board { background: #fff; border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); overflow: hidden; }
|
||||
.forum-board__head { display: flex; justify-content: space-between; gap: 20px; align-items: end; padding: 22px 24px; border-bottom: 1px solid var(--color-border); background: #fffdfa; }
|
||||
.forum-board__head h2 { margin: 0 0 6px; }
|
||||
.forum-search { display: grid; gap: 8px; min-width: min(100%, 360px); }
|
||||
.forum-search__row { display: flex; gap: 10px; }
|
||||
.forum-list__header { display: grid; grid-template-columns: minmax(0, 1fr) 120px 220px; gap: 16px; padding: 14px 24px; background: #f8f4ec; color: var(--color-muted); font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .35px; }
|
||||
.forum-row { display: grid; grid-template-columns: minmax(0, 1fr) 120px 220px; gap: 16px; padding: 20px 24px; border-top: 1px solid var(--color-border); align-items: start; }
|
||||
.forum-row__topic { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 14px; }
|
||||
.forum-row__icon { width: 40px; height: 40px; border-radius: 12px; display: flex; align-items: center; justify-content: center; background: var(--color-accent-soft); font-size: 18px; }
|
||||
.forum-row__topic h3 { margin: 0 0 8px; font-size: 20px; line-height: 1.2; }
|
||||
.forum-row__topic h3 a:hover { color: var(--color-primary); }
|
||||
.forum-row__meta { display: flex; flex-wrap: wrap; gap: 8px 12px; color: var(--color-muted); font-size: 13px; margin-bottom: 8px; }
|
||||
.forum-row__topic p { margin: 0; color: var(--color-text); line-height: 1.55; }
|
||||
.forum-row__count, .forum-row__activity { display: grid; gap: 4px; align-content: start; }
|
||||
.forum-row__count strong, .forum-row__activity strong { font-size: 18px; line-height: 1.1; }
|
||||
.forum-row__count span, .forum-row__activity span { color: var(--color-muted); font-size: 13px; }
|
||||
.forum-empty { padding: 28px 24px; color: var(--color-muted); }
|
||||
.forum-thread-head { display: flex; justify-content: space-between; gap: 20px; align-items: flex-start; margin-bottom: 18px; }
|
||||
.forum-thread-head h1 { margin: 0 0 8px; }
|
||||
.forum-thread-head__meta { margin: 0; color: var(--color-muted); }
|
||||
.forum-thread-head__meta-box { min-width: 120px; display: grid; gap: 4px; padding: 16px 18px; background: #fff; border: 1px solid var(--color-border); border-radius: var(--radius-md); text-align: center; box-shadow: var(--shadow-card); }
|
||||
.forum-thread-head__meta-box strong { font-size: 28px; line-height: 1; }
|
||||
.forum-thread-head__meta-box span { color: var(--color-muted); font-size: 13px; text-transform: uppercase; letter-spacing: .35px; }
|
||||
.forum-post { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 0; background: #fff; border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); overflow: hidden; }
|
||||
.forum-post + .forum-post { margin-top: 14px; }
|
||||
.forum-post--lead { margin-bottom: 24px; }
|
||||
.forum-post__author { display: grid; gap: 8px; align-content: start; padding: 22px 18px; background: #f8f4ec; border-right: 1px solid var(--color-border); }
|
||||
.forum-post__avatar { width: 52px; height: 52px; border-radius: 16px; display: flex; align-items: center; justify-content: center; background: var(--color-primary); color: #fff; font-size: 22px; font-weight: 700; }
|
||||
.forum-post__author strong { font-size: 17px; }
|
||||
.forum-post__author span { color: var(--color-muted); font-size: 14px; }
|
||||
.forum-post__body { padding: 20px 24px; }
|
||||
.forum-post__head { display: flex; justify-content: space-between; gap: 12px; color: var(--color-muted); font-size: 14px; margin-bottom: 14px; }
|
||||
.forum-post__content { font-size: 17px; line-height: 1.7; color: var(--color-text); }
|
||||
.forum-replies-head { display: flex; justify-content: space-between; gap: 16px; align-items: center; margin: 0 0 14px; }
|
||||
.forum-replies-head h2 { margin: 0; }
|
||||
.forum-replies-head span { color: var(--color-muted); }
|
||||
.forum-replies { display: grid; gap: 0; }
|
||||
.forum-reply-form { display: grid; gap: 14px; margin-top: 18px; padding: 22px 24px; background: #fff; border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); }
|
||||
.forum-login-note { margin-top: 18px; color: var(--color-muted); }
|
||||
|
||||
.flex { display:flex; }
|
||||
.between { justify-content: space-between; }
|
||||
@@ -155,10 +204,28 @@ body {
|
||||
.gap-12 { gap: 12px; }
|
||||
.stack { display:flex; flex-direction: column; }
|
||||
|
||||
@media (max-width: 980px){
|
||||
.forum-list__header,
|
||||
.forum-row { grid-template-columns: minmax(0, 1fr); }
|
||||
.forum-row__count,
|
||||
.forum-row__activity { grid-auto-flow: column; justify-content: start; gap: 10px; align-items: baseline; }
|
||||
.forum-post { grid-template-columns: 1fr; }
|
||||
.forum-post__author { border-right: 0; border-bottom: 1px solid var(--color-border); }
|
||||
}
|
||||
|
||||
@media (max-width: 720px){
|
||||
.nav-row { padding: 12px 0; }
|
||||
.hero { padding: 40px 0; }
|
||||
.section { padding: 48px 0; }
|
||||
.forum-hero,
|
||||
.forum-board__head,
|
||||
.forum-thread-head { grid-template-columns: 1fr; display: grid; }
|
||||
.forum-stats { grid-template-columns: 1fr; }
|
||||
.forum-search__row { flex-direction: column; }
|
||||
.forum-row,
|
||||
.forum-list__header { padding-left: 16px; padding-right: 16px; }
|
||||
.forum-post__body,
|
||||
.forum-reply-form { padding: 18px 16px; }
|
||||
}
|
||||
|
||||
/* Auth & Dashboard */
|
||||
|
||||
@@ -9,6 +9,19 @@ final class Community
|
||||
{
|
||||
}
|
||||
|
||||
public function getStats(): array
|
||||
{
|
||||
$threads = (int)$this->pdo->query('SELECT COUNT(*) FROM forum_threads')->fetchColumn();
|
||||
$posts = (int)$this->pdo->query('SELECT COUNT(*) FROM forum_posts')->fetchColumn();
|
||||
$members = (int)$this->pdo->query('SELECT COUNT(*) FROM users WHERE status = "active"')->fetchColumn();
|
||||
|
||||
return [
|
||||
'threads' => $threads,
|
||||
'posts' => $posts,
|
||||
'members' => $members,
|
||||
];
|
||||
}
|
||||
|
||||
public function createThread(int $userId, string $title, string $body): void
|
||||
{
|
||||
$stmt = $this->pdo->prepare('INSERT INTO forum_threads (user_id, title, body) VALUES (:uid, :title, :body)');
|
||||
@@ -45,10 +58,27 @@ final class Community
|
||||
}
|
||||
$where = $conditions ? ('AND ' . implode(' AND ', $conditions)) : '';
|
||||
|
||||
$sql = "SELECT ft.id, ft.title, ft.body, ft.created_at,
|
||||
$sql = "SELECT ft.id, ft.title, ft.body, ft.created_at, ft.updated_at,
|
||||
u.id as uid, u.created_at as user_created,
|
||||
p.display_name,
|
||||
(SELECT COUNT(*) FROM forum_posts fp WHERE fp.thread_id = ft.id) AS answers,
|
||||
COALESCE(
|
||||
(SELECT MAX(fp.created_at) FROM forum_posts fp WHERE fp.thread_id = ft.id),
|
||||
ft.created_at
|
||||
) AS last_activity_at,
|
||||
COALESCE(
|
||||
(
|
||||
SELECT p2.display_name
|
||||
FROM forum_posts fp3
|
||||
JOIN users u2 ON u2.id = fp3.user_id
|
||||
LEFT JOIN user_profiles p2 ON p2.user_id = u2.id
|
||||
WHERE fp3.thread_id = ft.id
|
||||
ORDER BY fp3.created_at DESC
|
||||
LIMIT 1
|
||||
),
|
||||
p.display_name,
|
||||
'Mitglied'
|
||||
) AS last_activity_by,
|
||||
(SELECT COUNT(*) FROM forum_posts fp2 WHERE fp2.user_id = u.id) +
|
||||
(SELECT COUNT(*) FROM forum_threads ft2 WHERE ft2.user_id = u.id) AS user_posts
|
||||
FROM forum_threads ft
|
||||
|
||||
Reference in New Issue
Block a user