import { toDateTime } from "@app/shared/utils/time"; import pool from "../../db"; import { LOARequest, LOAType } from '@app/shared/types/loa' import { PagedData } from '@app/shared/types/pagination' import { DiscussionPost } from '@app/shared/types/discussion'; import { DiscussionComment } from '@app/shared/types/discussion'; /** * Retrieves all discussion posts with pagination and optional type filtering. * @template T - The type of content stored in discussion posts * @param {string} [type] - Optional type filter to retrieve only posts of a specific type * @param {number} [page=1] - The page number for pagination (1-indexed) * @param {number} [pageSize=10] - The number of posts per page * @returns {Promise>>} A promise that resolves to paginated discussion posts with metadata * @throws {Error} If the database query fails */ export async function getAllDiscussions(type?: string, page = 1, pageSize = 10, search?: string): Promise>> { const offset = (page - 1) * pageSize; const params: any[] = []; // Base query parts let whereClause = "WHERE is_deleted = FALSE"; if (type) { whereClause += " AND type = ?"; params.push(type); } const sql = ` SELECT p.*, m.name as poster_name FROM discussion_posts AS p LEFT JOIN members m ON p.poster_id = m.id ${whereClause} ORDER BY p.is_open DESC, -- Show active/unlocked threads first p.created_at DESC -- Then show newest first LIMIT ? OFFSET ?; `; // Add pagination params to the end params.push(pageSize, offset); // Execute queries const posts: DiscussionPost[] = await pool.query(sql, params) as DiscussionPost[]; // Get count for the specific types const countSql = `SELECT COUNT(*) as count FROM discussion_posts ${whereClause}`; const countResult = await pool.query(countSql, type ? [type] : []); const totalCount = Number(countResult[0].count); const totalPages = Math.ceil(totalCount / pageSize); return { data: posts, pagination: { page, pageSize, total: totalCount, totalPages } }; } /** * Creates a new discussion post. * @template T - The type of content for the discussion post * @param {string} type - The type/category of the discussion post * @param {number} authorID - The ID of the member creating the post * @param {postTitle} string - The title of the discussion post * @param {T} data - The content data to be stored in the post * @returns {Promise} A promise that resolves to the ID of the newly created post * @throws {Error} If the database insertion fails */ export async function createDiscussion(type: string, authorID: number, postTitle: string, data: T): Promise { const sql = ` INSERT INTO discussion_posts (type, poster_id, title, content) VALUES (?, ?, ?, ?) `; console.log(data); const result = await pool.query(sql, [ type, authorID, postTitle, JSON.stringify(data) ]); console.log(result); return Number(result.insertId); } /** * Retrieve a single discussion post by its ID. * @template T - type of the content stored in the post (e.g. ModRequest) * @param {number} id - The id of the discussion post to fetch * @returns {Promise | null>} The discussion post or null if not found */ export async function getDiscussionById(id: number): Promise | null> { // Get the post const postSql = ` SELECT p.*, m.name as poster_name FROM discussion_posts AS p LEFT JOIN members m ON p.poster_id = m.id WHERE p.id = ? LIMIT 1; `; const postResults = (await pool.query(postSql, [id])) as DiscussionPost[]; if (postResults.length === 0) { return null; } const post = postResults[0]; // Get comments for the post const commentSql = ` SELECT c.* FROM discussion_comments AS c WHERE c.post_id = ? AND c.is_deleted = FALSE ORDER BY c.created_at ASC; `; const comments = (await pool.query(commentSql, [id])) as DiscussionComment[]; // Attach comments to post post.comments = comments; return post; } export async function getPostComments(postID: number): Promise { let comments = await pool.query("SELECT * FROM discussion_comments WHERE post_id = ?", [postID]); return comments; } export async function postComment(commentData: DiscussionComment, poster: number) { const sql = ` INSERT INTO discussion_comments (post_id, poster_id, content) VALUES (?, ?, ?); `; const result = await pool.query(sql, [commentData.post_id, poster, commentData.content]); if (!result.affectedRows || result.affectedRows !== 1) { throw new Error('Failed to insert comment: expected 1 row to be inserted'); } return Number(result.insertId); }