From 399e412f07ba54d51f06c9bee1744974f128c9c5 Mon Sep 17 00:00:00 2001 From: yubinquitous Date: Fri, 10 Nov 2023 17:55:10 +0900 Subject: [PATCH 1/7] feat: POST /users/friends #4 --- src/users/entities/friend.entity.ts | 15 +++++++ src/users/friends.repository.ts | 9 ++++ src/users/friends.service.ts | 67 +++++++++++++++++++++++++++++ src/users/users.controller.ts | 28 +++++++++++- src/users/users.module.ts | 7 ++- 5 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 src/users/entities/friend.entity.ts create mode 100644 src/users/friends.repository.ts create mode 100644 src/users/friends.service.ts diff --git a/src/users/entities/friend.entity.ts b/src/users/entities/friend.entity.ts new file mode 100644 index 0000000..6701ee8 --- /dev/null +++ b/src/users/entities/friend.entity.ts @@ -0,0 +1,15 @@ +import { IsNumber, IsPositive } from 'class-validator'; +import { BaseEntity } from 'src/common/base-entity'; +import { Column, Entity } from 'typeorm'; +@Entity() +export class Friend extends BaseEntity { + @Column() + @IsNumber() + @IsPositive() + fromUserId: number; + + @Column() + @IsNumber() + @IsPositive() + toUserId: number; +} diff --git a/src/users/friends.repository.ts b/src/users/friends.repository.ts new file mode 100644 index 0000000..a9cf3fa --- /dev/null +++ b/src/users/friends.repository.ts @@ -0,0 +1,9 @@ +import { InjectRepository } from '@nestjs/typeorm'; +import { Friend } from './entities/friend.entity'; +import { Repository, DataSource } from 'typeorm'; + +export class FriendRepository extends Repository { + constructor(@InjectRepository(Friend) private dataSource: DataSource) { + super(Friend, dataSource.manager); + } +} diff --git a/src/users/friends.service.ts b/src/users/friends.service.ts new file mode 100644 index 0000000..ef9816c --- /dev/null +++ b/src/users/friends.service.ts @@ -0,0 +1,67 @@ +import { BadRequestException, Injectable, Logger } from '@nestjs/common'; +import { FriendRepository } from './friends.repository'; +import { UserRepository } from './users.repository'; + +@Injectable() +export class FriendsService { + constructor( + private readonly friendRepository: FriendRepository, + private readonly userRepository: UserRepository, + ) {} + + private readonly logger = new Logger(FriendsService.name); + + /** + * 친구 추가 + * @param fromUserId 친구요청을 보낸 유저의 id + * @param toUserId 친구요청을 받은 유저의 id + * @returns + */ + async createFriend(fromUserId: number, toUserId: number) { + // 본인->본인 친구요청 + if (fromUserId === toUserId) { + throw new BadRequestException(`Can't be friend with yourself`); + } + + // 이미 친구인지 검사 + const isExistFriend = await this.isExistFriend(fromUserId, toUserId); + if (isExistFriend) { + throw new BadRequestException(`Already friend`); + } + + // 존재하는 유저인지 검사 + const isExistUser = await this.isExistUser(toUserId); + if (!isExistUser) { + throw new BadRequestException(`User with id ${toUserId} doesn't exist`); + } + + // 친구 추가 + const friend = this.friendRepository.create({ + fromUserId, + toUserId, + }); + this.logger.log('friend: ', friend); + await this.friendRepository.save(friend); + } + + async isExistFriend(fromUserId: number, toUserId: number) { + const friend = await this.friendRepository.findOne({ + where: { + fromUserId, + toUserId, + }, + }); + + return friend !== null; + } + + async isExistUser(userId: number) { + const user = await this.userRepository.findOne({ + where: { + id: userId, + }, + }); + + return user !== null; + } +} diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 527b7a7..3e56f8e 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -1,7 +1,31 @@ -import { Controller } from '@nestjs/common'; +import { + Body, + Controller, + ParseIntPipe, + Post, + UseGuards, +} from '@nestjs/common'; +import { GetUser } from 'src/auth/get-user.decorator'; +import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'; +import { PositiveIntPipe } from 'src/common/pipes/positiveInt.pipe'; +import { User } from './entities/user.entity'; +import { FriendsService } from './friends.service'; import { UsersService } from './users.service'; @Controller('users') export class UsersController { - constructor(private readonly usersService: UsersService) {} + constructor( + private readonly usersService: UsersService, + private readonly friendsService: FriendsService, + ) {} + + @Post('/friends') + @UseGuards(JwtAuthGuard) + async createFriend( + @GetUser() user: User, + @Body('friendId', ParseIntPipe, PositiveIntPipe) toUserId: number, + ) { + await this.friendsService.createFriend(user.id, toUserId); + // TODO: 친구요청을 받은 유저에게 알림 보내기 + } } diff --git a/src/users/users.module.ts b/src/users/users.module.ts index ba8ebf4..3bbef07 100644 --- a/src/users/users.module.ts +++ b/src/users/users.module.ts @@ -4,11 +4,14 @@ import { UsersController } from './users.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './entities/user.entity'; import { UserRepository } from './users.repository'; +import { Friend } from './entities/friend.entity'; +import { FriendRepository } from './friends.repository'; +import { FriendsService } from './friends.service'; @Module({ - imports: [TypeOrmModule.forFeature([User])], + imports: [TypeOrmModule.forFeature([User, Friend])], controllers: [UsersController], - providers: [UsersService, UserRepository], + providers: [UsersService, FriendsService, UserRepository, FriendRepository], exports: [UsersService], }) export class UsersModule {} From 4edfa64d5c48d9053bec6832a6c13571d66f15a6 Mon Sep 17 00:00:00 2001 From: yubinquitous Date: Sun, 12 Nov 2023 18:58:34 +0900 Subject: [PATCH 2/7] =?UTF-8?q?chore:=20submodule=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BE-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BE-config b/BE-config index 14eea85..f46b550 160000 --- a/BE-config +++ b/BE-config @@ -1 +1 @@ -Subproject commit 14eea8524949c9fed7b885f727159d4722ce0caa +Subproject commit f46b5504905b34d5daa9a984be8c93e7af547097 From 69b393b911544bbbd37d6b50871b2a12c3261adf Mon Sep 17 00:00:00 2001 From: yubinquitous Date: Sun, 12 Nov 2023 19:00:12 +0900 Subject: [PATCH 3/7] =?UTF-8?q?chore:=20submodule=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BE-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BE-config b/BE-config index f46b550..b50bdd7 160000 --- a/BE-config +++ b/BE-config @@ -1 +1 @@ -Subproject commit f46b5504905b34d5daa9a984be8c93e7af547097 +Subproject commit b50bdd7f5530f1436984cef6b3ec7e22f8716ed5 From 6dfb8409527dc08e94177b0a59dbb5ee83fe0f99 Mon Sep 17 00:00:00 2001 From: yubinquitous Date: Mon, 13 Nov 2023 17:21:24 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=EC=B9=9C=EA=B5=AC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20api=20=EA=B5=AC=ED=98=84=20#4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/users/friends.service.ts | 88 ++++++++++++++++++++++++++--------- src/users/users.controller.ts | 10 ++++ 2 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/users/friends.service.ts b/src/users/friends.service.ts index ef9816c..dbaa3a6 100644 --- a/src/users/friends.service.ts +++ b/src/users/friends.service.ts @@ -4,13 +4,13 @@ import { UserRepository } from './users.repository'; @Injectable() export class FriendsService { + private readonly logger = new Logger(FriendsService.name); + constructor( private readonly friendRepository: FriendRepository, private readonly userRepository: UserRepository, ) {} - private readonly logger = new Logger(FriendsService.name); - /** * 친구 추가 * @param fromUserId 친구요청을 보낸 유저의 id @@ -18,22 +18,14 @@ export class FriendsService { * @returns */ async createFriend(fromUserId: number, toUserId: number) { - // 본인->본인 친구요청 - if (fromUserId === toUserId) { - throw new BadRequestException(`Can't be friend with yourself`); - } + // 본인에게 친구요청을 보내는지 확인 + this.checkSelfFriendship(fromUserId, toUserId); - // 이미 친구인지 검사 - const isExistFriend = await this.isExistFriend(fromUserId, toUserId); - if (isExistFriend) { - throw new BadRequestException(`Already friend`); - } + // 친구요청을 받은 유저가 존재하는지 확인 + await this.validateUserExists(toUserId); - // 존재하는 유저인지 검사 - const isExistUser = await this.isExistUser(toUserId); - if (!isExistUser) { - throw new BadRequestException(`User with id ${toUserId} doesn't exist`); - } + // 이미 친구인지 확인 + await this.checkAlreadyFriends(fromUserId, toUserId); // 친구 추가 const friend = this.friendRepository.create({ @@ -44,24 +36,76 @@ export class FriendsService { await this.friendRepository.save(friend); } - async isExistFriend(fromUserId: number, toUserId: number) { - const friend = await this.friendRepository.findOne({ + /** + * 친구 삭제 + * @param fromUserId 친구 삭제 요청을 보낸 유저의 id + * @param toUserId 친구 삭제 요청을 받은 유저의 id + */ + async deleteFriend(fromUserId: number, toUserId: number) { + // 본인에게 친구 삭제 요청을 보내는지 확인 + this.checkSelfFriendship(fromUserId, toUserId); + + // 친구 삭제 요청을 받은 유저가 존재하는지 확인 + await this.validateUserExists(toUserId); + + // 친구인지 확인 + const friend = await this.findFriend(fromUserId, toUserId); + if (!friend) { + throw new BadRequestException(`Not friend with ${toUserId}`); + } + + // 친구 삭제 + const result = await this.friendRepository.softDelete(friend.id); + if (result.affected !== 1) { + throw new BadRequestException(`Failed to delete friend with ${toUserId}`); + } + this.logger.log('result: ', result); + } + + /** + * 친구 entity 조회 + * @returns 친구 entity 또는 null + */ + async findFriend(fromUserId: number, toUserId: number) { + return await this.friendRepository.findOne({ where: { fromUserId, toUserId, }, }); - - return friend !== null; } - async isExistUser(userId: number) { + /** + * 유저가 존재하는지 확인 + */ + async validateUserExists(userId: number) { const user = await this.userRepository.findOne({ where: { id: userId, }, }); - return user !== null; + if (!user) { + throw new BadRequestException(`User with id ${userId} doesn't exist`); + } + } + + /** + * 본인에게 친구/친구삭제 요청을 보내는지 확인 + */ + private checkSelfFriendship(fromUserId: number, toUserId: number) { + if (fromUserId === toUserId) { + throw new BadRequestException(`Can't be friend with yourself`); + } + } + + /** + * 이미 친구인지 확인 + */ + private async checkAlreadyFriends(fromUserId: number, toUserId: number) { + const isExistFriend = await this.findFriend(fromUserId, toUserId); + if (isExistFriend) { + throw new BadRequestException(`Already friends`); + } } } diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 3e56f8e..c3ec653 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -1,6 +1,7 @@ import { Body, Controller, + Delete, ParseIntPipe, Post, UseGuards, @@ -28,4 +29,13 @@ export class UsersController { await this.friendsService.createFriend(user.id, toUserId); // TODO: 친구요청을 받은 유저에게 알림 보내기 } + + @Delete('/friends') + @UseGuards(JwtAuthGuard) + async deleteFriend( + @GetUser() user: User, + @Body('friendId', ParseIntPipe, PositiveIntPipe) toUserId: number, + ) { + await this.friendsService.deleteFriend(user.id, toUserId); + } } From 27a0a22cd2c83d1cdaae2706c1c77d2951a86e6e Mon Sep 17 00:00:00 2001 From: yubinquitous Date: Tue, 14 Nov 2023 02:00:39 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=EC=B9=9C=EA=B5=AC=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84,=20Us?= =?UTF-8?q?er=20Entity=EC=97=90=20status=20column=20=EC=B6=94=EA=B0=80=20#?= =?UTF-8?q?4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/constants.ts | 2 ++ src/common/enum.ts | 5 +++++ src/users/dto/friend-info.dto.ts | 6 +++++ src/users/dto/page-info.dto.ts | 5 +++++ src/users/entities/user.entity.ts | 16 ++++++++++++- src/users/friends.repository.ts | 27 ++++++++++++++++++++++ src/users/friends.service.ts | 37 ++++++++++++++++++++++++------- src/users/users.controller.ts | 15 +++++++++++++ 8 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 src/common/constants.ts create mode 100644 src/common/enum.ts create mode 100644 src/users/dto/friend-info.dto.ts create mode 100644 src/users/dto/page-info.dto.ts diff --git a/src/common/constants.ts b/src/common/constants.ts new file mode 100644 index 0000000..fec863e --- /dev/null +++ b/src/common/constants.ts @@ -0,0 +1,2 @@ +// pagenation에서 한 페이지에 보여줄 데이터 개수 +export const DATA_PER_PAGE = 10; diff --git a/src/common/enum.ts b/src/common/enum.ts new file mode 100644 index 0000000..b034e5e --- /dev/null +++ b/src/common/enum.ts @@ -0,0 +1,5 @@ +export enum UserStatus { + ONLINE = 'ONLINE', + OFFLINE = 'OFFLINE', + IN_GAME = 'IN_GAME', +} diff --git a/src/users/dto/friend-info.dto.ts b/src/users/dto/friend-info.dto.ts new file mode 100644 index 0000000..800518c --- /dev/null +++ b/src/users/dto/friend-info.dto.ts @@ -0,0 +1,6 @@ +export class friendInfo { + id: number; + nickname: string; + avatar: string; + status: string; +} diff --git a/src/users/dto/page-info.dto.ts b/src/users/dto/page-info.dto.ts new file mode 100644 index 0000000..f7ef3c6 --- /dev/null +++ b/src/users/dto/page-info.dto.ts @@ -0,0 +1,5 @@ +export class PageInfo { + total: number; + page: number; + lastPage: number; +} diff --git a/src/users/entities/user.entity.ts b/src/users/entities/user.entity.ts index d7a99bc..2f11e8e 100644 --- a/src/users/entities/user.entity.ts +++ b/src/users/entities/user.entity.ts @@ -1,5 +1,6 @@ import { IsBoolean, + IsNotEmpty, IsNumber, IsOptional, IsString, @@ -7,6 +8,7 @@ import { Matches, } from 'class-validator'; import { BaseEntity } from 'src/common/base-entity'; +import { UserStatus } from 'src/common/enum'; import { Column, Entity, Unique } from 'typeorm'; @Entity() @@ -15,6 +17,7 @@ export class User extends BaseEntity { @Column({ unique: true }) @IsString() @Length(1, 10) + @IsNotEmpty() @Matches(/^[ㄱ-ㅎ가-힣a-zA-Z0-9!]+$/) nickname: string; @@ -23,26 +26,32 @@ export class User extends BaseEntity { avatar: string; @Column() + @IsNotEmpty() @IsString() email: string; @Column({ default: false }) + @IsNotEmpty() @IsBoolean() isMfaEnabled: boolean; - @Column({ default: 1000 }) // TODO: 기본점수 검사 + @Column({ default: 1200 }) + @IsNotEmpty() @IsNumber() ladderScore: number; @Column({ default: 1000 }) + @IsNotEmpty() @IsNumber() ladderMaxScore: number; @Column({ default: 0 }) + @IsNotEmpty() @IsNumber() winCount: number; @Column({ default: 0 }) + @IsNotEmpty() @IsNumber() loseCount: number; @@ -68,4 +77,9 @@ export class User extends BaseEntity { @IsOptional() @Matches(/^[ㄱ-ㅎ가-힣a-zA-Z0-9]+$/) statusMessage: string; + + @Column({ default: UserStatus.OFFLINE }) + @IsNotEmpty() + @IsString() + status: UserStatus; } diff --git a/src/users/friends.repository.ts b/src/users/friends.repository.ts index a9cf3fa..08bf23f 100644 --- a/src/users/friends.repository.ts +++ b/src/users/friends.repository.ts @@ -1,9 +1,36 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Friend } from './entities/friend.entity'; import { Repository, DataSource } from 'typeorm'; +import { friendInfo } from './dto/friend-info.dto'; +import { DATA_PER_PAGE } from 'src/common/constants'; export class FriendRepository extends Repository { constructor(@InjectRepository(Friend) private dataSource: DataSource) { super(Friend, dataSource.manager); } + + async findFriend(fromUserId: number, toUserId: number) { + return await this.findOne({ + where: { + fromUserId, + toUserId, + }, + }); + } + + async findFriendInfos(userId: number, page: number): Promise { + // raw query + const friends = await this.dataSource.query( + ` + SELECT u.id, u.nickname, u.avatar, u.status + FROM friend f + JOIN "user" u + ON u.id = f."toUserId" + WHERE f."fromUserId" = $1 + LIMIT $2 OFFSET $3 + `, + [userId, DATA_PER_PAGE, (page - 1) * DATA_PER_PAGE], + ); + return friends; + } } diff --git a/src/users/friends.service.ts b/src/users/friends.service.ts index dbaa3a6..2e31ded 100644 --- a/src/users/friends.service.ts +++ b/src/users/friends.service.ts @@ -1,6 +1,8 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common'; +import { PageInfo } from './dto/page-info.dto'; import { FriendRepository } from './friends.repository'; import { UserRepository } from './users.repository'; +import { DATA_PER_PAGE } from 'src/common/constants'; @Injectable() export class FriendsService { @@ -49,7 +51,7 @@ export class FriendsService { await this.validateUserExists(toUserId); // 친구인지 확인 - const friend = await this.findFriend(fromUserId, toUserId); + const friend = await this.friendRepository.findFriend(fromUserId, toUserId); if (!friend) { throw new BadRequestException(`Not friend with ${toUserId}`); } @@ -63,16 +65,32 @@ export class FriendsService { } /** - * 친구 entity 조회 - * @returns 친구 entity 또는 null + * 친구 목록 조회 + * @param userId 친구 목록을 조회할 유저의 id + * @param page 페이지 번호 + * @returns 친구 목록 */ - async findFriend(fromUserId: number, toUserId: number) { - return await this.friendRepository.findOne({ + async findFriendsWithPage(userId: number, page: number) { + // 친구 목록 조회 + const friends = await this.friendRepository.findFriendInfos(userId, page); + + // 페이지 정보 조회 + const total = await this.friendRepository.count({ where: { - fromUserId, - toUserId, + fromUserId: userId, }, }); + const lastPage = Math.ceil(total / DATA_PER_PAGE); + const pageInfo: PageInfo = { + total, + page, + lastPage, + }; + + this.logger.log('friends: ', friends); + this.logger.log('pageInfo: ', pageInfo); + + return { friends, pageInfo }; } /** @@ -103,7 +121,10 @@ export class FriendsService { * 이미 친구인지 확인 */ private async checkAlreadyFriends(fromUserId: number, toUserId: number) { - const isExistFriend = await this.findFriend(fromUserId, toUserId); + const isExistFriend = await this.friendRepository.findFriend( + fromUserId, + toUserId, + ); if (isExistFriend) { throw new BadRequestException(`Already friends`); } diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index c3ec653..ad91635 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -2,6 +2,8 @@ import { Body, Controller, Delete, + Get, + Param, ParseIntPipe, Post, UseGuards, @@ -38,4 +40,17 @@ export class UsersController { ) { await this.friendsService.deleteFriend(user.id, toUserId); } + + @Get('/friends/:page') + @UseGuards(JwtAuthGuard) + async findFriendsWithPage( + @GetUser() user: User, + @Param('page', ParseIntPipe, PositiveIntPipe) page: number, + ) { + const { friends, pageInfo } = await this.friendsService.findFriendsWithPage( + user.id, + page, + ); + return { friends, pageInfo }; + } } From 439739403137d847e667d5395630d259e5ba7514 Mon Sep 17 00:00:00 2001 From: yubinquitous Date: Tue, 14 Nov 2023 14:00:37 +0900 Subject: [PATCH 6/7] =?UTF-8?q?chore:=20DTO=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC=20#4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/auth/auth.service.ts | 8 ++------ src/auth/dto/user-find-return.dto.ts | 6 ++++++ src/users/dto/friend-info.dto.ts | 4 ++-- src/users/dto/page-info.dto.ts | 4 ++-- src/users/friends.repository.ts | 7 +++++-- src/users/friends.service.ts | 4 ++-- 6 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 src/auth/dto/user-find-return.dto.ts diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index d45aa9c..cbaee4b 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -5,11 +5,7 @@ import userConfig from 'src/config/user.config'; import { User } from 'src/users/entities/user.entity'; import { UserRepository } from './../users/users.repository'; import { User42Dto } from './dto/user-42.dto'; - -type UserFindreturn = { - user: User; - mfaCode?: string; -}; +import { UserFindReturnDto } from './dto/user-find-return.dto'; @Injectable() export class AuthService { @@ -28,7 +24,7 @@ export class AuthService { return Promise.resolve('mfaCode'); // TODO: 2FA 코드 생성 } - async findOrCreateUser(userData: User42Dto): Promise { + async findOrCreateUser(userData: User42Dto): Promise { const user = await this.userRepository.findOne({ where: { email: userData.email }, }); diff --git a/src/auth/dto/user-find-return.dto.ts b/src/auth/dto/user-find-return.dto.ts new file mode 100644 index 0000000..2d095a1 --- /dev/null +++ b/src/auth/dto/user-find-return.dto.ts @@ -0,0 +1,6 @@ +import { User } from 'src/users/entities/user.entity'; + +export type UserFindReturnDto = { + user: User; + mfaCode?: string; +}; diff --git a/src/users/dto/friend-info.dto.ts b/src/users/dto/friend-info.dto.ts index 800518c..bd953a9 100644 --- a/src/users/dto/friend-info.dto.ts +++ b/src/users/dto/friend-info.dto.ts @@ -1,6 +1,6 @@ -export class friendInfo { +export type friendInfoDto = { id: number; nickname: string; avatar: string; status: string; -} +}; diff --git a/src/users/dto/page-info.dto.ts b/src/users/dto/page-info.dto.ts index f7ef3c6..5ebf68b 100644 --- a/src/users/dto/page-info.dto.ts +++ b/src/users/dto/page-info.dto.ts @@ -1,5 +1,5 @@ -export class PageInfo { +export type PageInfoDto = { total: number; page: number; lastPage: number; -} +}; diff --git a/src/users/friends.repository.ts b/src/users/friends.repository.ts index 08bf23f..9ac0d56 100644 --- a/src/users/friends.repository.ts +++ b/src/users/friends.repository.ts @@ -1,7 +1,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Friend } from './entities/friend.entity'; import { Repository, DataSource } from 'typeorm'; -import { friendInfo } from './dto/friend-info.dto'; +import { friendInfoDto } from './dto/friend-info.dto'; import { DATA_PER_PAGE } from 'src/common/constants'; export class FriendRepository extends Repository { @@ -18,7 +18,10 @@ export class FriendRepository extends Repository { }); } - async findFriendInfos(userId: number, page: number): Promise { + async findFriendInfos( + userId: number, + page: number, + ): Promise { // raw query const friends = await this.dataSource.query( ` diff --git a/src/users/friends.service.ts b/src/users/friends.service.ts index 2e31ded..a95b2a8 100644 --- a/src/users/friends.service.ts +++ b/src/users/friends.service.ts @@ -1,5 +1,5 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common'; -import { PageInfo } from './dto/page-info.dto'; +import { PageInfoDto } from './dto/page-info.dto'; import { FriendRepository } from './friends.repository'; import { UserRepository } from './users.repository'; import { DATA_PER_PAGE } from 'src/common/constants'; @@ -81,7 +81,7 @@ export class FriendsService { }, }); const lastPage = Math.ceil(total / DATA_PER_PAGE); - const pageInfo: PageInfo = { + const pageInfo: PageInfoDto = { total, page, lastPage, From c979121b546b7d5b05380d0e8c85d24544451d74 Mon Sep 17 00:00:00 2001 From: yubinquitous Date: Tue, 14 Nov 2023 14:18:07 +0900 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20pageInfo=EB=A5=BC=20totalItemCount?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/users/dto/friend-info.dto.ts | 2 +- src/users/dto/friend-response.dto.ts | 7 +++++++ src/users/friends.repository.ts | 4 ++-- src/users/friends.service.ts | 20 ++++++++------------ src/users/users.controller.ts | 5 +++-- 5 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 src/users/dto/friend-response.dto.ts diff --git a/src/users/dto/friend-info.dto.ts b/src/users/dto/friend-info.dto.ts index bd953a9..b7b8122 100644 --- a/src/users/dto/friend-info.dto.ts +++ b/src/users/dto/friend-info.dto.ts @@ -1,4 +1,4 @@ -export type friendInfoDto = { +export type FriendInfoDto = { id: number; nickname: string; avatar: string; diff --git a/src/users/dto/friend-response.dto.ts b/src/users/dto/friend-response.dto.ts new file mode 100644 index 0000000..d9823bd --- /dev/null +++ b/src/users/dto/friend-response.dto.ts @@ -0,0 +1,7 @@ +import { FriendInfoDto } from './friend-info.dto'; + +export type FriendResponseDto = { + friends: FriendInfoDto[]; + + totalItemCount: number; +}; diff --git a/src/users/friends.repository.ts b/src/users/friends.repository.ts index 9ac0d56..7114443 100644 --- a/src/users/friends.repository.ts +++ b/src/users/friends.repository.ts @@ -1,7 +1,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Friend } from './entities/friend.entity'; import { Repository, DataSource } from 'typeorm'; -import { friendInfoDto } from './dto/friend-info.dto'; +import { FriendInfoDto } from './dto/friend-info.dto'; import { DATA_PER_PAGE } from 'src/common/constants'; export class FriendRepository extends Repository { @@ -21,7 +21,7 @@ export class FriendRepository extends Repository { async findFriendInfos( userId: number, page: number, - ): Promise { + ): Promise { // raw query const friends = await this.dataSource.query( ` diff --git a/src/users/friends.service.ts b/src/users/friends.service.ts index a95b2a8..44b34b1 100644 --- a/src/users/friends.service.ts +++ b/src/users/friends.service.ts @@ -1,8 +1,7 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common'; -import { PageInfoDto } from './dto/page-info.dto'; import { FriendRepository } from './friends.repository'; import { UserRepository } from './users.repository'; -import { DATA_PER_PAGE } from 'src/common/constants'; +import { FriendResponseDto } from './dto/friend-response.dto'; @Injectable() export class FriendsService { @@ -70,27 +69,24 @@ export class FriendsService { * @param page 페이지 번호 * @returns 친구 목록 */ - async findFriendsWithPage(userId: number, page: number) { + async findFriendsWithPage( + userId: number, + page: number, + ): Promise { // 친구 목록 조회 const friends = await this.friendRepository.findFriendInfos(userId, page); // 페이지 정보 조회 - const total = await this.friendRepository.count({ + const totalItemCount = await this.friendRepository.count({ where: { fromUserId: userId, }, }); - const lastPage = Math.ceil(total / DATA_PER_PAGE); - const pageInfo: PageInfoDto = { - total, - page, - lastPage, - }; this.logger.log('friends: ', friends); - this.logger.log('pageInfo: ', pageInfo); + this.logger.log('pageInfo: ', totalItemCount); - return { friends, pageInfo }; + return { friends, totalItemCount }; } /** diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index ad91635..7402ec0 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -47,10 +47,11 @@ export class UsersController { @GetUser() user: User, @Param('page', ParseIntPipe, PositiveIntPipe) page: number, ) { - const { friends, pageInfo } = await this.friendsService.findFriendsWithPage( + const friendResponseDto = await this.friendsService.findFriendsWithPage( user.id, page, ); - return { friends, pageInfo }; + + return friendResponseDto; } }