diff --git a/src/form/dto/query-form.dto.ts b/src/form/dto/query-form.dto.ts new file mode 100644 index 0000000..12fec3f --- /dev/null +++ b/src/form/dto/query-form.dto.ts @@ -0,0 +1,47 @@ +import { ApiPropertyOptional } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; +import { IsEnum, IsInt, IsOptional, IsString, Max, Min } from 'class-validator'; + +export enum SortOrder { + ASC = 'asc', + DESC = 'desc', +} + +export enum SortBy { + NAME = 'name', + CREATED_AT = 'createdAt', + UPDATED_AT = 'updatedAt', + STATUS = 'status', +} + +export class QueryFormDto { + @ApiPropertyOptional({ example: 1 }) + @Type(() => Number) + @IsInt() + @Min(1) + @IsOptional() + page?: number = 1; + + @ApiPropertyOptional({ example: 10 }) + @Type(() => Number) + @IsInt() + @Min(1) + @Max(100) + @IsOptional() + limit?: number = 10; + + @ApiPropertyOptional({ example: '' }) + @IsString() + @IsOptional() + search?: string; + + @ApiPropertyOptional({ enum: SortBy, example: SortBy.CREATED_AT }) + @IsEnum(SortBy) + @IsOptional() + sortBy?: SortBy = SortBy.CREATED_AT; + + @ApiPropertyOptional({ enum: SortOrder, example: SortOrder.DESC }) + @IsEnum(SortOrder) + @IsOptional() + sortOrder?: SortOrder = SortOrder.DESC; +} diff --git a/src/form/form.controller.ts b/src/form/form.controller.ts index c97bc0a..073a2ff 100644 --- a/src/form/form.controller.ts +++ b/src/form/form.controller.ts @@ -6,12 +6,13 @@ import { Patch, Param, Delete, + Query, } from '@nestjs/common'; import { FormService } from './form.service'; import { ApiOperation } from '@nestjs/swagger'; import { UpdateFieldDto } from './dto/update-field.dto'; import { CreateUpdateDto } from './dto/create-update.dto'; - +import { QueryFormDto } from './dto/query-form.dto'; @Controller('form') export class FormController { @@ -24,9 +25,9 @@ export class FormController { } @Get() - @ApiOperation({ summary: 'Find all forms' }) - async findAll() { - return await this.formService.findAll(); + @ApiOperation({ summary: 'Get all forms with pagination, search, sort' }) + findAll(@Query() query: QueryFormDto) { + return this.formService.findAll(query); } @Get(':formId') diff --git a/src/form/form.service.ts b/src/form/form.service.ts index 2329808..2dad1eb 100644 --- a/src/form/form.service.ts +++ b/src/form/form.service.ts @@ -1,4 +1,3 @@ -import { FormModule } from './form.module'; import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Form, FormDocument, Status } from './schemas/form.schema'; @@ -6,7 +5,20 @@ import { Model } from 'mongoose'; import { v4 as uuidv4 } from 'uuid'; import { UpdateFieldDto } from './dto/update-field.dto'; import { CreateUpdateDto } from './dto/create-update.dto'; +import { QueryFormDto } from './dto/query-form.dto'; +import { FormQueryBuilder } from './helpers/form-query.builder'; +import { PaginatedResponse } from 'src/interfaces/paginated-response.interface'; +// Reusable projections +const LIST_PROJECTION = { + _id: 0, + id: 1, + name: 1, + status: 1, + deletedAt: 1, + createdAt: 1, +}; +const DETAIL_PROJECTION = { _id: 0, __v: 0 }; @Injectable() export class FormService { @@ -30,18 +42,50 @@ export class FormService { const updatedForm = await this.formModel.findOneAndUpdate( { id: dto.id }, { $push: { fields: newField } }, - { new: true }, + { new: true, projection: DETAIL_PROJECTION }, ); + if (!updatedForm) throw new NotFoundException(`Form ${dto.id} not found`); - return form; + return updatedForm; } - async findAll(): Promise