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:
43
backend/src/categories/categories.controller.ts
Normal file
43
backend/src/categories/categories.controller.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
backend/src/categories/categories.module.ts
Normal file
12
backend/src/categories/categories.module.ts
Normal 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 {}
|
||||||
64
backend/src/categories/categories.service.ts
Normal file
64
backend/src/categories/categories.service.ts
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
backend/src/categories/dto/create-category.dto.ts
Normal file
15
backend/src/categories/dto/create-category.dto.ts
Normal 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;
|
||||||
|
}
|
||||||
4
backend/src/categories/dto/update-category.dto.ts
Normal file
4
backend/src/categories/dto/update-category.dto.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from "@nestjs/mapped-types";
|
||||||
|
import { CreateCategoryDto } from "./create-category.dto";
|
||||||
|
|
||||||
|
export class UpdateCategoryDto extends PartialType(CreateCategoryDto) {}
|
||||||
Reference in New Issue
Block a user