Foro: paginación de temas (20/pág) y de posts (15/pág)
- lib/forum.ts: countTopics/countPosts + offset/limit en getTopics/getPosts (mismos límites que Django: FORUM_TOPICS_PER_PAGE=20, FORUM_POSTS_PER_PAGE=15). - components/Pagination.tsx: paginación reutilizable (ventana ±2, primera/última, prev/next) con enlaces ?page=N; no renderiza si solo hay una página. - Foro y tema aceptan ?page=N (clamp al rango válido). - El formulario de respuesta solo aparece en la última página; enlace a ella si no. - i18n: namespace Common (prev/next/page) + replyOnLastPage. Build OK. Sin datos de foro en acore_web (estado vacío correcto). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+28
-4
@@ -104,12 +104,24 @@ export async function getForum(id: number): Promise<{ name: string; description:
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTopics(forumId: number): Promise<Topic[]> {
|
||||
export async function countTopics(forumId: number): Promise<number> {
|
||||
try {
|
||||
const [rows] = await db(DB.web).query<RowDataPacket[]>(
|
||||
'SELECT id, name, poster, created, sticky, locked, views FROM forum_topics WHERE forum_id = ? AND deleted = 0 ORDER BY sticky DESC, updated_at DESC, id DESC',
|
||||
'SELECT COUNT(*) AS n FROM forum_topics WHERE forum_id = ? AND deleted = 0',
|
||||
[forumId],
|
||||
)
|
||||
return Number(rows[0]?.n ?? 0)
|
||||
} catch {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTopics(forumId: number, offset = 0, limit = 20): Promise<Topic[]> {
|
||||
try {
|
||||
const [rows] = await db(DB.web).query<RowDataPacket[]>(
|
||||
'SELECT id, name, poster, created, sticky, locked, views FROM forum_topics WHERE forum_id = ? AND deleted = 0 ORDER BY sticky DESC, updated_at DESC, id DESC LIMIT ? OFFSET ?',
|
||||
[forumId, limit, offset],
|
||||
)
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
@@ -146,12 +158,24 @@ export async function getTopic(id: number): Promise<TopicFull | null> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPosts(topicId: number): Promise<Post[]> {
|
||||
export async function countPosts(topicId: number): Promise<number> {
|
||||
try {
|
||||
const [rows] = await db(DB.web).query<RowDataPacket[]>(
|
||||
'SELECT id, poster, poster_id, text, time, created_at, updated_at FROM forum_posts WHERE topic_id = ? AND deleted = 0 ORDER BY time ASC, id ASC',
|
||||
'SELECT COUNT(*) AS n FROM forum_posts WHERE topic_id = ? AND deleted = 0',
|
||||
[topicId],
|
||||
)
|
||||
return Number(rows[0]?.n ?? 0)
|
||||
} catch {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPosts(topicId: number, offset = 0, limit = 15): Promise<Post[]> {
|
||||
try {
|
||||
const [rows] = await db(DB.web).query<RowDataPacket[]>(
|
||||
'SELECT id, poster, poster_id, text, time, created_at, updated_at FROM forum_posts WHERE topic_id = ? AND deleted = 0 ORDER BY time ASC, id ASC LIMIT ? OFFSET ?',
|
||||
[topicId, limit, offset],
|
||||
)
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
poster: r.poster,
|
||||
|
||||
Reference in New Issue
Block a user