feat: add comment replies and liking functionality

- Introduced support for nested comment replies in both frontend and backend.
- Added comment liking and unliking features, including like count and "isLiked" state tracking.
- Updated database schema with `parentId` and new `comment_likes` table.
- Enhanced UI for threaded comments and implemented display of like counts and reply actions.
- Refactored APIs and repositories to support replies, likes, and enriched comment data.
This commit is contained in:
Mathis HERRIOT
2026-01-29 15:26:54 +01:00
parent ed3ed66cab
commit 0976850c0c
11 changed files with 405 additions and 92 deletions

View File

@@ -8,18 +8,45 @@ import {
Req,
UseGuards,
} from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { getIronSession } from "iron-session";
import { AuthGuard } from "../auth/guards/auth.guard";
import { getSessionOptions } from "../auth/session.config";
import type { AuthenticatedRequest } from "../common/interfaces/request.interface";
import { JwtService } from "../crypto/services/jwt.service";
import { CommentsService } from "./comments.service";
import { CreateCommentDto } from "./dto/create-comment.dto";
@Controller()
export class CommentsController {
constructor(private readonly commentsService: CommentsService) {}
constructor(
private readonly commentsService: CommentsService,
private readonly jwtService: JwtService,
private readonly configService: ConfigService,
) {}
@Get("contents/:contentId/comments")
findAllByContentId(@Param("contentId") contentId: string) {
return this.commentsService.findAllByContentId(contentId);
async findAllByContentId(
@Param("contentId") contentId: string,
@Req() req: any,
) {
// Tentative de récupération de l'utilisateur pour isLiked (optionnel)
let userId: string | undefined;
try {
const session = await getIronSession<any>(
req,
req.res,
getSessionOptions(this.configService.get("SESSION_PASSWORD") as string),
);
if (session.accessToken) {
const payload = await this.jwtService.verifyJwt(session.accessToken);
userId = payload.sub;
}
} catch (_e) {
// Ignorer les erreurs de session
}
return this.commentsService.findAllByContentId(contentId, userId);
}
@Post("contents/:contentId/comments")
@@ -38,4 +65,16 @@ export class CommentsController {
const isAdmin = req.user.role === "admin" || req.user.role === "moderator";
return this.commentsService.remove(req.user.sub, id, isAdmin);
}
@Post("comments/:id/like")
@UseGuards(AuthGuard)
like(@Req() req: AuthenticatedRequest, @Param("id") id: string) {
return this.commentsService.like(req.user.sub, id);
}
@Delete("comments/:id/like")
@UseGuards(AuthGuard)
unlike(@Req() req: AuthenticatedRequest, @Param("id") id: string) {
return this.commentsService.unlike(req.user.sub, id);
}
}