feat: add FavoritesModule with service, controller, and CRUD endpoints
Implemented FavoritesModule to manage user favorites. Includes service methods for adding, removing, and listing favorites, along with appropriate database integrations and API endpoints.
This commit is contained in:
43
backend/src/favorites/favorites.controller.ts
Normal file
43
backend/src/favorites/favorites.controller.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
Controller,
|
||||
DefaultValuePipe,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
Query,
|
||||
Req,
|
||||
UseGuards,
|
||||
} from "@nestjs/common";
|
||||
import { AuthGuard } from "../auth/guards/auth.guard";
|
||||
import type { AuthenticatedRequest } from "../common/interfaces/request.interface";
|
||||
import { FavoritesService } from "./favorites.service";
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@Controller("favorites")
|
||||
export class FavoritesController {
|
||||
constructor(private readonly favoritesService: FavoritesService) {}
|
||||
|
||||
@Post(":contentId")
|
||||
add(@Req() req: AuthenticatedRequest, @Param("contentId") contentId: string) {
|
||||
return this.favoritesService.addFavorite(req.user.sub, contentId);
|
||||
}
|
||||
|
||||
@Delete(":contentId")
|
||||
remove(
|
||||
@Req() req: AuthenticatedRequest,
|
||||
@Param("contentId") contentId: string,
|
||||
) {
|
||||
return this.favoritesService.removeFavorite(req.user.sub, contentId);
|
||||
}
|
||||
|
||||
@Get()
|
||||
list(
|
||||
@Req() req: AuthenticatedRequest,
|
||||
@Query("limit", new DefaultValuePipe(10), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
) {
|
||||
return this.favoritesService.getUserFavorites(req.user.sub, limit, offset);
|
||||
}
|
||||
}
|
||||
12
backend/src/favorites/favorites.module.ts
Normal file
12
backend/src/favorites/favorites.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { DatabaseModule } from "../database/database.module";
|
||||
import { FavoritesController } from "./favorites.controller";
|
||||
import { FavoritesService } from "./favorites.service";
|
||||
|
||||
@Module({
|
||||
imports: [DatabaseModule],
|
||||
controllers: [FavoritesController],
|
||||
providers: [FavoritesService],
|
||||
exports: [FavoritesService],
|
||||
})
|
||||
export class FavoritesModule {}
|
||||
63
backend/src/favorites/favorites.service.ts
Normal file
63
backend/src/favorites/favorites.service.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
ConflictException,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from "@nestjs/common";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { DatabaseService } from "../database/database.service";
|
||||
import { contents, favorites } from "../database/schemas";
|
||||
|
||||
@Injectable()
|
||||
export class FavoritesService {
|
||||
constructor(private readonly databaseService: DatabaseService) {}
|
||||
|
||||
async addFavorite(userId: string, contentId: string) {
|
||||
// Vérifier si le contenu existe
|
||||
const content = await this.databaseService.db
|
||||
.select()
|
||||
.from(contents)
|
||||
.where(eq(contents.id, contentId))
|
||||
.limit(1);
|
||||
|
||||
if (content.length === 0) {
|
||||
throw new NotFoundException("Content not found");
|
||||
}
|
||||
|
||||
try {
|
||||
return await this.databaseService.db
|
||||
.insert(favorites)
|
||||
.values({ userId, contentId })
|
||||
.returning();
|
||||
} catch (_error) {
|
||||
// Probablement une violation de clé primaire (déjà en favori)
|
||||
throw new ConflictException("Content already in favorites");
|
||||
}
|
||||
}
|
||||
|
||||
async removeFavorite(userId: string, contentId: string) {
|
||||
const result = await this.databaseService.db
|
||||
.delete(favorites)
|
||||
.where(and(eq(favorites.userId, userId), eq(favorites.contentId, contentId)))
|
||||
.returning();
|
||||
|
||||
if (result.length === 0) {
|
||||
throw new NotFoundException("Favorite not found");
|
||||
}
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
async getUserFavorites(userId: string, limit: number, offset: number) {
|
||||
const data = await this.databaseService.db
|
||||
.select({
|
||||
content: contents,
|
||||
})
|
||||
.from(favorites)
|
||||
.innerJoin(contents, eq(favorites.contentId, contents.id))
|
||||
.where(eq(favorites.userId, userId))
|
||||
.limit(limit)
|
||||
.offset(offset);
|
||||
|
||||
return data.map((item) => item.content);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user