feat: add CategoriesModule with CRUD operations

Implemented CategoriesModule with controller, service, and DTOs for managing categories. Includes endpoints for creation, retrieval, updating, and deletion, integrated with database logic.
This commit is contained in:
Mathis HERRIOT
2026-01-08 15:24:48 +01:00
parent 42805e371e
commit 705f1ad6e0
5 changed files with 138 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Patch,
Post,
} from "@nestjs/common";
import { CategoriesService } from "./categories.service";
import { CreateCategoryDto } from "./dto/create-category.dto";
import { UpdateCategoryDto } from "./dto/update-category.dto";
@Controller("categories")
export class CategoriesController {
constructor(private readonly categoriesService: CategoriesService) {}
@Get()
findAll() {
return this.categoriesService.findAll();
}
@Get(":id")
findOne(@Param("id") id: string) {
return this.categoriesService.findOne(id);
}
// Ces routes devraient être protégées par un AdminGuard
@Post()
create(@Body() createCategoryDto: CreateCategoryDto) {
return this.categoriesService.create(createCategoryDto);
}
@Patch(":id")
update(@Param("id") id: string, @Body() updateCategoryDto: UpdateCategoryDto) {
return this.categoriesService.update(id, updateCategoryDto);
}
@Delete(":id")
remove(@Param("id") id: string) {
return this.categoriesService.remove(id);
}
}

View File

@@ -0,0 +1,12 @@
import { Module } from "@nestjs/common";
import { DatabaseModule } from "../database/database.module";
import { CategoriesController } from "./categories.controller";
import { CategoriesService } from "./categories.service";
@Module({
imports: [DatabaseModule],
controllers: [CategoriesController],
providers: [CategoriesService],
exports: [CategoriesService],
})
export class CategoriesModule {}

View File

@@ -0,0 +1,64 @@
import { Injectable } from "@nestjs/common";
import { eq } from "drizzle-orm";
import { DatabaseService } from "../database/database.service";
import { categories } from "../database/schemas";
import { CreateCategoryDto } from "./dto/create-category.dto";
import { UpdateCategoryDto } from "./dto/update-category.dto";
@Injectable()
export class CategoriesService {
constructor(private readonly databaseService: DatabaseService) {}
async findAll() {
return await this.databaseService.db
.select()
.from(categories)
.orderBy(categories.name);
}
async findOne(id: string) {
const result = await this.databaseService.db
.select()
.from(categories)
.where(eq(categories.id, id))
.limit(1);
return result[0] || null;
}
async create(data: CreateCategoryDto) {
const slug = data.name
.toLowerCase()
.replace(/ /g, "-")
.replace(/[^\w-]/g, "");
return await this.databaseService.db
.insert(categories)
.values({ ...data, slug })
.returning();
}
async update(id: string, data: UpdateCategoryDto) {
const updateData = {
...data,
updatedAt: new Date(),
slug: data.name
? data.name
.toLowerCase()
.replace(/ /g, "-")
.replace(/[^\w-]/g, "")
: undefined,
};
return await this.databaseService.db
.update(categories)
.set(updateData)
.where(eq(categories.id, id))
.returning();
}
async remove(id: string) {
return await this.databaseService.db
.delete(categories)
.where(eq(categories.id, id))
.returning();
}
}

View File

@@ -0,0 +1,15 @@
import { IsNotEmpty, IsOptional, IsString } from "class-validator";
export class CreateCategoryDto {
@IsString()
@IsNotEmpty()
name!: string;
@IsOptional()
@IsString()
description?: string;
@IsOptional()
@IsString()
iconUrl?: string;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from "@nestjs/mapped-types";
import { CreateCategoryDto } from "./create-category.dto";
export class UpdateCategoryDto extends PartialType(CreateCategoryDto) {}