Skip to content
This repository has been archived by the owner on Feb 16, 2024. It is now read-only.

Commit

Permalink
feat: add user search
Browse files Browse the repository at this point in the history
  • Loading branch information
relby committed Jan 14, 2024
1 parent 1400640 commit 9d04a8c
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 1 deletion.
53 changes: 53 additions & 0 deletions public/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,59 @@
]
}
},
"/api/users": {
"get": {
"operationId": "UsersController_getUsers",
"parameters": [
{
"name": "nameLike",
"required": false,
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "page",
"required": false,
"in": "query",
"schema": {
"default": 1,
"type": "number"
}
},
{
"name": "limit",
"required": false,
"in": "query",
"schema": {
"default": 10,
"type": "number"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserOutputDTO"
}
}
}
}
},
"tags": [
"Users"
],
"security": [
{
"AccessToken": []
}
]
}
},
"/api/users/me": {
"get": {
"operationId": "UsersController_getMe",
Expand Down
20 changes: 20 additions & 0 deletions src/api/controllers/users.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Pagination } from 'nestjs-typeorm-paginate';
import { UserInventoryEntriesUseCase } from 'src/core/use-cases/user-inventory-entries.use-case';
import { QuickSoldUserInventoryEntryEntity } from 'src/infra/postgres/entities/quick-sold-user-inventory-entry.entity';
import { QuickSoldUserInventoryEntryOutputDTO } from '../dtos/user-inventory-entries/quick-sold-user-inventory-entry.output.dto';
import { GetUsersInputDTO } from '../dtos/users/get-users.input.dto';

@ApiTags('Users')
@Controller('users')
Expand All @@ -26,10 +27,29 @@ export class UsersController {
@InjectMapper()
private readonly mapper: Mapper,

private readonly usersUseCase: UsersUseCase,
private readonly userInventoryEntriesUseCase: UserInventoryEntriesUseCase,
private readonly dataSource: DataSource,
) {}

@ApiOkResponse({ type: UserOutputDTO })
@ApiSecurity('AccessToken')
@Get()
@UseGuards(JwtAuthGuard)
public async getUsers(
@Query() dto: GetUsersInputDTO,
@Query() paginationDTO: PaginationInputDTO,
): Promise<Pagination<UserOutputDTO>> {
const users = await this.usersUseCase.findUsers(dto, paginationDTO);

return mapArrayWithPagination(
this.mapper,
users,
UserEntity,
UserOutputDTO,
)
}

@ApiOkResponse({ type: UserOutputDTO })
@ApiSecurity('AccessToken')
@Get('me')
Expand Down
9 changes: 9 additions & 0 deletions src/api/dtos/users/get-users.input.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ApiPropertyOptional } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';

export class GetUsersInputDTO {
@ApiPropertyOptional()
@IsString()
@IsOptional()
public readonly nameLike?: string;
}
15 changes: 15 additions & 0 deletions src/core/services/users.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IPaginationOptions, paginate, Pagination } from 'nestjs-typeorm-paginate';
import { Nullable } from 'src/common/types';
import { UserEntity, UserModel, CreateUserEntityFields, UpdateUserEntityFields } from 'src/infra/postgres/entities/user.entity';
import { FindEntityRelationsOptions } from 'src/infra/postgres/other/types';
Expand Down Expand Up @@ -33,6 +34,20 @@ export class UsersService {
}) as Promise<Nullable<UserModel<T>>>;
}

public async findManyWithPagination<
T extends FindEntityRelationsOptions<UserEntity> = {},
>(
paginationOptions: IPaginationOptions,
where?: FindOptionsWhere<UserEntity>,
relations?: T,
): Promise<Pagination<UserModel<T>>> {
return paginate(
this.usersRepository,
paginationOptions,
{ where, relations },
) as unknown as Promise<Pagination<UserModel<T>>>;
}

public async createOne(fields: CreateUserEntityFields): Promise<UserModel> {
const user = this.usersRepository.create(fields);

Expand Down
19 changes: 18 additions & 1 deletion src/core/use-cases/users.use-case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import { CreateUserInputDTO } from 'src/api/dtos/users/create-user.input.dto';
import { UpdateUserInputDTO } from 'src/api/dtos/users/update-user.input.dto';
import { UUIDv4 } from 'src/common/types';
import { FindEntityRelationsOptions } from 'src/infra/postgres/other/types';
import { FindOptionsWhere } from 'typeorm';
import { FindOptionsWhere, Like } from 'typeorm';
import { IPaginationOptions, Pagination } from 'nestjs-typeorm-paginate';
import { GetUsersInputDTO } from 'src/api/dtos/users/get-users.input.dto';

@Injectable()
export class UsersUseCase {
public constructor(
private readonly usersService: UsersService,
) {}

// TODO: Rename all methods in use cases starting with find to starting with get
public async findUser(
where: FindOptionsWhere<UserEntity>,
errorMessage?: string,
Expand All @@ -33,6 +36,20 @@ export class UsersUseCase {
return this.findUser({ id }, errorMessageFn?.(id) ?? `User (\`${id}\`) not found`);
}

public async findUsers(
dto: GetUsersInputDTO,
paginationOptions: IPaginationOptions
): Promise<Pagination<UserModel>> {
const where: FindOptionsWhere<UserEntity> = {
...(dto.nameLike && { name: Like(`%${dto.nameLike}%`) }),
};

return this.usersService.findManyWithPagination(
paginationOptions,
where,
);
}

public async checkIfUserExistsByName(name: string) {
return this.usersService.exist({ name });
}
Expand Down

0 comments on commit 9d04a8c

Please sign in to comment.