diff --git a/web-next/app/[locale]/forum/topic/[topicId]/page.tsx b/web-next/app/[locale]/forum/topic/[topicId]/page.tsx index 83d60f7..8dc9f1d 100644 --- a/web-next/app/[locale]/forum/topic/[topicId]/page.tsx +++ b/web-next/app/[locale]/forum/topic/[topicId]/page.tsx @@ -65,7 +65,9 @@ export default async function TopicPage({
- {post.poster} + + {post.poster} + {post.deleted && [{t('deletedMark')}]} {post.time && ( diff --git a/web-next/app/[locale]/forum/user/[username]/page.tsx b/web-next/app/[locale]/forum/user/[username]/page.tsx new file mode 100644 index 0000000..bff13fd --- /dev/null +++ b/web-next/app/[locale]/forum/user/[username]/page.tsx @@ -0,0 +1,68 @@ +import { getTranslations, setRequestLocale } from 'next-intl/server' +import { Link } from '@/i18n/navigation' +import { getForumProfile } from '@/lib/forum' + +export const dynamic = 'force-dynamic' + +export default async function ForumProfilePage({ + params, +}: { + params: Promise<{ locale: string; username: string }> +}) { + const { locale, username } = await params + setRequestLocale(locale) + const t = await getTranslations('Forum') + const p = await getForumProfile(decodeURIComponent(username)) + + return ( +
+

+ + ← {t('backToForum')} + +

+ +
+

+ {p.username} + {p.status && ( + + {p.status === 'admin' ? t('roleAdmin') : t('roleGm')} + + )} +

+
+
+

{t('posts')}

+

{p.postCount}

+
+
+

{t('topics')}

+

{p.topicCount}

+
+
+

{t('memberSince')}

+

+ {p.joindate ? new Date(p.joindate).toLocaleDateString(locale) : '—'} +

+
+
+
+ + {p.recentTopics.length > 0 && ( +
+

{t('recentTopics')}

+
    + {p.recentTopics.map((topic) => ( +
  • + + {topic.name} + +
  • + ))} +
+
+ )} +
+ ) +} diff --git a/web-next/lib/forum.ts b/web-next/lib/forum.ts index a03e722..7496971 100644 --- a/web-next/lib/forum.ts +++ b/web-next/lib/forum.ts @@ -211,6 +211,67 @@ export async function getPosts(topicId: number, offset = 0, limit = 15, includeD } } +export interface ForumProfile { + username: string + postCount: number + topicCount: number + joindate: string | null + gmlevel: number + status: 'admin' | 'gm' | null + recentTopics: { id: number; name: string; forum_id: number }[] +} + +/** Perfil público de un usuario del foro (contadores + antigüedad + rango). */ +export async function getForumProfile(username: string): Promise { + const profile: ForumProfile = { + username, + postCount: 0, + topicCount: 0, + joindate: null, + gmlevel: 0, + status: null, + recentTopics: [], + } + try { + const [pc] = await db(DB.web).query( + 'SELECT COUNT(*) AS n FROM forum_posts WHERE poster = ? AND deleted = 0', + [username], + ) + profile.postCount = Number(pc[0]?.n ?? 0) + const [tc] = await db(DB.web).query( + 'SELECT COUNT(*) AS n FROM forum_topics WHERE poster = ? AND deleted = 0', + [username], + ) + profile.topicCount = Number(tc[0]?.n ?? 0) + const [rt] = await db(DB.web).query( + 'SELECT id, name, forum_id FROM forum_topics WHERE poster = ? AND deleted = 0 ORDER BY updated_at DESC, id DESC LIMIT 5', + [username], + ) + profile.recentTopics = rt.map((r) => ({ id: r.id, name: r.name, forum_id: r.forum_id })) + } catch { + /* tablas de foro no pobladas */ + } + try { + const [acc] = await db(DB.auth).query( + 'SELECT id, joindate FROM account WHERE username = ?', + [username], + ) + if (acc[0]) { + profile.joindate = acc[0].joindate ? new Date(acc[0].joindate).toISOString() : null + const [ga] = await db(DB.auth).query( + 'SELECT MAX(gmlevel) AS lvl FROM account_access WHERE id = ?', + [acc[0].id], + ) + profile.gmlevel = ga[0]?.lvl != null ? Number(ga[0].lvl) : 0 + } + } catch { + /* account_access puede no existir */ + } + if (profile.gmlevel >= 16) profile.status = 'admin' + else if (profile.gmlevel >= 1) profile.status = 'gm' + return profile +} + /** Nº de temas que coinciden con la búsqueda (foros visibles). */ export async function countSearchTopics(query: string): Promise { const like = `%${query}%` diff --git a/web-next/messages/en.json b/web-next/messages/en.json index 9d09ca3..3fd4702 100644 --- a/web-next/messages/en.json +++ b/web-next/messages/en.json @@ -297,7 +297,11 @@ "moveTopic": "Move to", "restore": "Restore", "restoreTopic": "Restore topic", - "deletedMark": "Deleted" + "deletedMark": "Deleted", + "memberSince": "Member since", + "recentTopics": "Recent topics", + "roleAdmin": "Administrator", + "roleGm": "GM" }, "Admin": { "title": "Admin panel", diff --git a/web-next/messages/es.json b/web-next/messages/es.json index 45d6a2c..d657ac8 100644 --- a/web-next/messages/es.json +++ b/web-next/messages/es.json @@ -297,7 +297,11 @@ "moveTopic": "Mover a", "restore": "Restaurar", "restoreTopic": "Restaurar tema", - "deletedMark": "Borrado" + "deletedMark": "Borrado", + "memberSince": "Miembro desde", + "recentTopics": "Temas recientes", + "roleAdmin": "Administrador", + "roleGm": "GM" }, "Admin": { "title": "Panel de administración",